你是否从还在焦虑从vue2过渡到vue3,那就看看这里(二)

126 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第四天,点击查看活动详情

1.jpg

这篇文章主要记录vue3的基础知识点,提供给需要从vue2过渡到vue3的朋友,因为我也是需要从vue2过渡到vue3,所以在此记录学习过程,vue3知识点文章将会持续更新
祝愿看到文章的朋友身体健康;如果可以麻烦一键三连

计算属性和侦听属性

computed

语法和vue2.x相差不大

import {computed,reactive} from 'vue'
setup(){
    let person = reactive({
        firstName:'张',
        lastName:'三'
    })
	//计算属性——简写
    let fullName = computed(()=>{
        return person.firstName + '-' + person.lastName
    })
    //计算属性——完整
    let fullName = computed({
        get(){
            return person.firstName + '-' + person.lastName
        },
        set(value){
            const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
}

watch

语法和vue2.x相差不大,但是有一点小不同

  1. 监视reactive定义的响应式数据时

    1.1. oldValue无法正确获取

    1.2 强制开启了深度监视(deep配置为false也没有用)

  2. 监视reactive定义的响应式数据中的某个属性

    2.1 如果该属性是基本数据类型,oldValue获取的值是正确的,但是深度监听无效,设置为false也可以监听

    2.2 如果该属性是引用数据类型,oldValue获取的值不正确和newValue一样深度监听有效,设置为false不会被监听

    2.3 如果监听数据中的多个属性,只要属性中有引用类型和基本类型,只有基本数据类型的oldValue正确,并且deep为false也可以监听(深度监听无效

    2.4 如果监听数据中的多个属性,全为引用类型或者全为基本类型和第一个第二个规则一样

监听ref所定义的响应式数据

<template>
    <button ref="btn" @click="clickBtn">点击</button>
</template>
<script>
import {ref,watch} from "vue"
export default {
    name: 'App',
    setup() {
        let msg = ref('这里是组件的双向绑定')
        let msg1 = ref('这里是组件的双向绑定1')
        // 监听一个ref所定义的响应式数据
        watch(msg,(newValue,oldValue)=>{
            console.log('msg变化了',newValue,oldValue)
        },{immediate:true})


        // 监听多个个ref所定义的响应式数据;newValue和oldValue都是数组
        watch([msg1,msg],(newValue,oldValue)=>{
            console.log('msg1或msg变化了',newValue,oldValue)
        })


        // 点击按钮以改变
        function clickBtn() {
            msg.value = '这里是组件的双向绑定1';
            msg1.value = '这里是组件的双向绑定这里是组件的双向绑定11';
        }
        return {msg,msg1,clickBtn}
    }
}
</script>

image.png

监听reactive所定义的响应式数据

<template>
    <button ref="btn" @click="clickBtn">点击</button>
</template>
<script>
import {reactive,watch} from "vue"
export default {
    name: 'App',
    setup() {
        const obj = reactive({
            a:1,
            b:{
                a:2,
                b:{
                    a:3
                }
            },
            c:2
        })


        // 监听reactive所定义的响应式数据
        //此处的deep配置没有用,并且oldValue获取的值是newValue的值
        // watch(obj,(newValue,oldValue)=>{
        //     console.log('obj变化了',newValue,oldValue)
        // },{immediate:true,deep:false}) 


        //监视reactive定义的响应式数据中的引用类型属性
        // 这里的oldValue依然获取的是newValue的值
        // 因为obj.b也是引用类型设置deep为false改变obj的b不会被监听,只有设置为true才会被监听
        // watch(()=>obj.b,(newValue,oldValue)=>{
        //     console.log('obj的b变化了',newValue,oldValue)
        // },{immediate:true,deep:false}) 


        //监视reactive定义的响应式数据中的基本类型属性
        // 这里的oldValue正确,设置deep无效,设置为false也会被监听
        // watch(()=>obj.a,(newValue,oldValue)=>{
        //     console.log('obj的a变化了',newValue,oldValue)
        // },{immediate:true,deep:false}) 


        //监视reactive定义的响应式数据中的某些属性
        // 这里的oldValue值中的a是对的,b是不对的,b的值和newValue一样
        // 这里a是基本数据类型,b是对象,将deep设置为false如果只改变a也可以监听
        watch([()=>obj.a,()=>obj.b],(newValue,oldValue)=>{
            console.log('obj的a或者b变化了',newValue,oldValue)
        },{immediate:true,deep:false})


        // 点击按钮以改变
        function clickBtn() {
            obj.a = 4;
        }
        return {obj,clickBtn}
    }
}
</script>

image.png

watchEffect函数

watch需要指定监听的值和监听回调

watchEffect不需要指定监听的属性,回调中用到哪个属性就是监听的哪个属性,和computed有点像

watchEffect和computed的比较

computed注重返回值(计算出来的值),必须有返回值

watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值

<template>
    <button ref="btn" @click="clickBtn">点击{{msg}}</button>
</template>
<script>
import {reactive,watchEffect,ref} from "vue"
export default {
    name: 'App',
    setup() {
        const obj = reactive({
            a:1,
            b:{
                a:2,
                b:{
                    a:3
                }
            },
            c:2,
            d:{
                a:2
            }
        })
        let msg = ref(10)
        watchEffect(()=>{
            msg.value = obj.a;
            console.log('watchEffect被执行了')
        })
        // 点击按钮以改变
        function clickBtn() {
            obj.a = 4;
        }
        return {obj,clickBtn,msg}
    }
}
</script>

image.png

生命周期钩子

beforeCreate -> 使用 setup()

created -> 使用 setup()

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeDestroy -> onBeforeUnmount

destroyed -> onUnmounted

errorCaptured -> onErrorCaptured

vue3.x中的mixin

vue3.x中的自定义hook函数,类似于vue2.x中的mixin

可以在任意你想抽离复用代码的地方创建一个js文件(一般我们把自定义的hook函数都放到src下面的hooks文件夹中)

hooks/hook1.js

import { ref } from "vue"
export default function(){
    let title = ref('这里是hook函数的')
    function clickBtn() {
        title.value+='1'
    }
    return {title,clickBtn}
}

组件useHook

<template>
    <div class="hello">{{title}}</div>
    <button @click="clickBtn">点击title加1</button>
</template>
<script>
import hook1 from "./hooks/hook1"
export default {
    name: 'useHook',
    setup() {
        const hook = hook1()
        // 因为hook1.js返回的是对象,所以需要解构
        return {
            ...hook
        }
    }
}
</script>

toRef和toRefs函数

根据名字可以看出是创建ref对象

toRef:

当我们定义一个数据不是响应式的时候,可以使用toRef将其变成响应式的数据;比如我们将一个响应式对象中的某个属性赋值给一个变量时,这时这个变量就不是响应式的,可以使用toRef让其变为响应式,语法为toRef(对象,'属性')

<template>
    <div>{{numA}}</div>
    <button @click="clickBtn">点击按钮</button>
</template>
<script>
import { reactive } from "vue"
export default {
    name: 'HelloWorld',
    setup() {
        const obj = reactive({
            a:1,
            b:{
                a:1
            }
        })        
        // 点击按钮改变numA,但是页面不会更新因为numA不是响应式的
        let numA = obj.b.a;
        function clickBtn() {
            numA = 5
        }
        // 点击按钮改变numA,页面会更新因为numA是响应式的
        let numA = toRef(obj.b,'a');
        // 点击按钮改变a
        function clickBtn() {
            numA.value = 5
        }
        return {numA,clickBtn}
    }
}
</script>

toRefs:

和toRef的功能一样,只是可以创建多个ref对象;用的最多就是解构返回的对象;我们直接解构定义的响应式对象之后就不再是响应式的了,利用toRefs函数就可以避免这个问题(如果不解构的话在模板中就要写{{obj.a}})

<template>
    <div>{{a}}</div>
    <button @click="clickBtn">点击按钮</button>
</template>
<script>
import { reactive,toRefs } from "vue"
export default {
    name: 'HelloWorld',
    setup() {
        const obj = reactive({
            a:1,
            b:{
                a:1
            }
        })
        function clickBtn() {
            obj.a++;
        }
        // 直接解构点击按钮页面也不会改变
        // return {...obj,clickBtn}
        return {...toRefs(obj),clickBtn}
    }
}
</script>