vue之vue3


一、vue3简介

1.性能的提升
    打包大小减少41%
    初次渲染快55%, 更新渲染快133%
    内存减少54%
2.源码的升级
    使用Proxy代替defineProperty实现响应式
    重写虚拟DOM的实现和Tree-Shaking
3.拥抱TypeScript
    Vue3可以更好的支持TypeScript
4.新的特性
    Composition API(组合API)
        setup配置
        ref与reactive
        watch与watchEffect
        provide与inject
    新的内置组件
        Fragment
        Teleport
        Suspense
    其他改变
        新的生命周期钩子
        data 选项应始终被声明为一个函数
        移除keyCode支持作为 v-on 的修饰符

5 组合式API和配置项API
    -使用组合式API
    -配置项API
        -{
            name:'xx',
            data:function(){},
            methods:{}
        }

二、创建vue3的两种方式

# 打开终端输入命令 

# vue-cli:创建vue2和vue3   
    -跟之前一样
# vite:创建vue3,创建最新
    npm init vue@latest
    # 根据自己的需要选择是否要下载依赖
    # Pinai 这个就相当于是vuex
    
# vite创建另一种方式:创建vue3.0.4版本
    npm init vite-app <project-name>
    ## 进入工程目录
    cd <project-name>
    ## 安装依赖
    npm install
    ## 运行
    npm run dev
    
# 以后在页面中的this,已经不是vue2中的vc对象了,是一个代理对象

三、setup函数

# 向之前vue2编写变量和函数的时候是在data和methods中编写 
eg:
export default {
    data(){
        name:'jason'
},
    methods:{
        handleClick(){
             alert('弹出')
}}}  # 这是vue2的写法  像这种写法 叫做配置项api

# 在vue3中也是能够支持这样写的 但是vue3推荐写在setup函数中 就是把定义变量和写函数都下载setup中
eg:
export default {setup(){
    let name = 'jason'
    let age = 19
    function handleClick(){
             alert('弹出')
    return {name, age, handleClick}  # 这些变量都必须返回出去 这样页面才可以使用
}}}

3.1 代码演示

<template>
  <h2>{{ name }}</h2>
  <h3>{{ age }}</h3>
</template>

<script>
export default {
  name: 'App',
  setup() {   // setup中没有this了
    let age = 19
    let name = 'lqz'
    // 函数必须有返回值
    return {
      age, name  // 只要返回了 页面上直接使用插值语法即可
    } 
  }
}
</script>

四、ref和reactive

'''
使用了setup函数的话 那么setup就没有了响应式布局了 
之前vue2只要定义了变量 那么就可以使用响应式布局 
修改变量 页面上的数据也会跟着改变
现在vue3是没有了响应式布局了 如果想把变量变成响应式布局 
那么需要关键字帮助才可以 就是自己可以决定了哪些变量可以响应式'''

4.1 ref

<!--基本数据类型 数字,字符串,布尔值 如果想让这些数据类型加响应式, 那么需要ref包裹
然后js通过对象.value取值修改-->

<script>
import {ref, reactive} from 'vue'  // 先导入
export default {
    let age = ref(19) // age 已经不是数字了,是RefImpl的对象 RefImpl中有value
    let name = ref('lqz')
}
    let handleAdd = () => {
      console.log('我要开始加了,age是', age)  // 通过点击事件 把age加1
      age.value = age.value + 1  // 但是需要通过 age.value才能够取到值
}
    return {
      age, name, handleAdd  // 这样通过ref就可以使用响应式布局  这样变量修改 页面就会实时变化
    }
</script>

4.2 reactive

<!--#  对象,数组引用使用reactive, js直接点值就可以取到值  
ref也可以包对象类型,但是用的时候必须.value-->

<script>

import {ref, reactive} from 'vue'

export default {
    let person = reactive({
        'name':'lqz',
        'age':19
    })

      let handleAdd = () => {
      console.log('我要开始加了,age是', age)
      person.age = person.age + 1   // 通过reactive可以直接点出值来修改  
    }
    return {
      person, handleAdd 
    }
}

五、计算和监听属性

5.1 计算属性

<template>
    <input type="text" v-model="firstName "></input>
    <input type="text" v-model="lastName "></input>      
    {{fullName }} 
    <!--就是通过两个输入框的输入的变化 然后触发computed的执行 然后该computed返回了 两个输入框的和  所以一个输入框发生变化 那么fullName也就跟着发生了变化-->
</template>

<script>
import {computed,} from 'vue'  // 导入
   // computed:{   vue2的写法
     //   fullName:function (){}
    // },

  setup() {
    // 1 计算属性案例1
        let firstName = ref('')
        let lastName = ref('清政')
       // 定义计算属性
        let fullName = computed(() => {  // 使用computed写计算属性
         return firstName.value + lastName.value
        })
        return {firstName ,lastName ,fullName }  // 这样页面上拿到的就是一个数据


        // 2 计算属性案例2
        let person = reactive({  // 使用了reactive包裹了 响应式  页面上就可以直接使用person.firstName显示了
              firstName: '',
              lastName: '清政',
        })
        // 定义计算属性
        person.fullName = computed({  // 现在把fullName 添加到了person对象中
          get() {  // 可以写get对象
            return person.firstName + '-' + person.lastName  // 也可以直接点出数据了
      },
          set(value) {  // 也可以写set对象
            console.log(value)
            const nameArr = value.split('-')  // 使用split将get返回出来的值分割
            person.firstName = nameArr[0]  
            person.lastName = nameArr[1]  // 然后在赋值给firstName和lastName 这样我们修改fullName的时候 firstName也会跟着修改
      }
    })
        return {
          person
    }
}
</script>

5.2 监听属性

import {watch, ref, watchEffect} from 'vue'

export default {
  name: 'App',
  setup() {
    let name = ref('lqz')

    // 定义监听属性
    watch(name, (newValue, old) => {  // 就当name变化的时候 就会触发watch函数
      console.log('name变了')
          console.log(old)  // old就是修改之前的值
          console.log(newValue)  // newValue就是修改后的值
    })
    // vue3 又多了个watchEffect,只要函数中使用的变量发生变化,它就会触发
    watchEffect(() => {
      // 只要该函数中使用的变量发生变化,它就会触发
      let a = name.value + '?'  // 将name赋值给了a然后name加?  那么name就是发生了变化 然后就会触发watchEffect函数
      console.log('watchEffect配置的回调执行了')
    })
    return {
      name
    }
  }
}

六、生命周期

# Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
        beforeDestroy 改名为 beforeUnmount  # 删除组件之前
        destroyed 改名为 unmounted  # 删除组件之后
# Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
    # vue.2           vue.3
    beforeCreate===>setup()
    created=======>setup()
    beforeMount ===>onBeforeMount
    mounted=======>onMounted
    beforeUpdate===>onBeforeUpdate
    updated =======>onUpdated
    beforeUnmount ==>onBeforeUnmount
    unmounted =====>onUnmounted
<script>
export default {
  import {onMounted, onBeforeUpdate} from 'vue'  // 需要导入
  name: 'test',
    // 其实在setup外面也是可以写vue2的钩子函数的写法的 但是推荐在setup中编写  如果都写了的话  那么会优先执行setup中的在执行setup外面的钩子函数
    setup(){
        // beforeCreate和created可以直接在setup中编写函数 可以之间往后端发送axios请求
        // 其他的钩子函数其实写法都一样就是名字变了
        onMounted(() => {  // 页面挂载之后 就会触发
            console.log('onMounted')
    })
        onBeforeUpdate(() => {  // 页面修改之后 重新挂载之前触发  其他的写法也是一样的
            console.log('onMounted')
    })
    }
}
</script>

七、hooks

# 什么是hook?—— 
    本质是一个函数,把setup函数中使用的Composition API进行了封装。
    类似于vue2.x中的mixin。 就是把重复的代码可以提取出来 然后哪里需要用 那么在导入即可
    自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂

7.1 hooks/index.js

import {onMounted, onUnmounted, reactive} from "vue";

// 我们编写一个 只要在页面上点击 那么立刻打印这个点的xy轴

export default function () {
    let p = reactive({  // 顶一个p对象,该对象中有x和y轴
        x: 0,
        y: 0  
    })

    function getPoint(event) {  // 定义一个getPoint函数
        console.log(event)
        p.x = event.pageX
        p.y = event.pageY
    }

    // 声明周期钩子的onMounted,当页面挂载就会执行
    onMounted(() => {
        // 给数鼠标点击增加监听,就是当点击鼠标的时候,就会执行这个函数
        window.addEventListener('click', getPoint)  // 该函数就是帮我们知道点击的这个地方的x和y轴是多少
    })
    // 组件被销毁时,把功能去掉  组件销毁之后就需要把该功能去掉 不去掉会浪费资源
    onUnmounted(() => {
        window.removeEventListener('click', getPoint)  // 该函数就是去掉该功能
    })

    return p  // 然后把p对象返回
}  // 然后把上述代码写到hooks文件中的index.js文件中

7.2 其他组件

<template>
    <h2>x坐标是:{{ p.x }},y坐标是:{{ p.y }}</h2>
</template>

<script>
import hooks from './hooks/index'

export default {

    setup() {
    let p = hooks()  // 需要加括号调用
    return {p}  // 接收的函数有几个返回值 就返回一个变量
  }
}
</script>

八、toRefs

<template>
    <!-- <h1>{{data.name}}</h1> -->
    <!-- 本来我们在页面上显示对象的值 需要使用句点符的形式显示 但是如果我们使用了toRefs的话那么我们可以直接使用对象中的值 -->
    <h1>{{name}}</h1>
    <h1>{{age}}</h1>
    <button @click="handleShow">点击</button>
    dhiwhoidhwo
</template>

<script>
import {toRefs} from 'vue'
export default {
  name: 'App',
  setup() {
    let data = reactive({
      name: 'lqz',
      age: 19,
      isShow: true
    })

    function handleShow() {
      console.log('ssdaf')
      data.isShow = !data.isShow
      data.age++
    }

    return {
      ...data,  
      // 就相当于解压了 然后 就等于name:'lqz',age:19返回了出去 但是如果就这样解压出去的话 页面修改的值不会修改data中的值 这样就不会关联起来了 
      ...toRefs(data),  
     // 需要加上toRefs这样 页面上的变量才能继续跟data中的值绑定 页面变化 数据也跟着变化
      handleShow
    }
  }
}
</script>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-11-02 20:05  stephen_hao  阅读(258)  评论(0编辑  收藏  举报