1. 双向数据绑定原理

vue2 是结合发布者订阅者模式,结合es6Object.defineProperty()对数据进行劫持,进一步通过vue中的watcher的update实现双向数据绑定。
vue3 中使用了es6的proxy进行数据代理。

相对于vue2,使用proxy的优势:

  1. defineProperty只能监听某个属性,不能对全对象监听;
  2. 可以监听到数组内部的变化;
  3. vue2中我们给对象添加一个新属性,它不会更新到视图上,只是因为新添加的属性并没有通过Object.defineProperty()进行响应式设置,但是vue3中的proxy对于动态添加的属性也是具有响应式的.

2. vue3支持碎片

也就是说,vue3在组件中支持多个根节点.

vue2

<template>
    <div>
        <h1></h1>
    </div>
</template>

vue3

<template>
    <div>
        <h1></h1>
    </div>
    <div>
        <span></span>
    </div>
</template>

3. Composition API (组合api)

vue2和vue3最大的区别就是,vue3使用了Composition API (组合api)

在vue2中是使用的Options API,这种写法不方便我们的阅读和交流,逻辑过于分散。

vue2

<script>
export default {
	// 数据
    data() {
        return {};
    },
    mounted() {},
    // 方法
    methods: {},
    computed: {},
    components:{}
};
</script>

vue3

这样代码会更加简洁和整洁。
<script>
export default {
    setup() {
        // 数据 和 方法都在setup里面使用
    }
};
</script>

4. 生命周期钩子

Vue2--------------vue3
beforeCreate  -> setup()			比beforeCreate和created执行的还要早
created       -> setup()	
beforeMount   -> onBeforeMount		组件挂载到节点之前执行的函数
mounted       -> onMounted			组件挂载完成后执行的函数
beforeUpdate  -> onBeforeUpdate		组件更新之前执行的函数
updated       -> onUpdated			组件更新完成之后执行的函数
beforeDestroy -> onBeforeUnmount	组件卸载之前执行的函数
destroyed     -> onUnmounted		组件卸载完成后执行的函数

若组件被keep-alive包含,则会多出两个钩子函数:
activated     -> onActivated		组件激活时触发	
deactivated   -> onDeactivated		组件失活时触发

5. 父子传参不同,setup()函数

因为在setup里面是获取不到this,所以在vue3中我们通过setup(props,context)两个参数进行父子之间的传参。

vue2

# 父组件
<template>
    <div class='father'>
        <my :msg="msg" @get="get"></my>
        {{sonMsg}}
    </div>
</template>

<script>
import my from '@/components/my'
export default {
    data() {
        return {
            msg:'父组件的数据',
            sonMsg:''
        };
    },
    methods: {
        get(val) {
            this.sonMsg = val
            console.log(val);
        }
    },
    components:{
        my
    }
};
</script>

# 子组件
<template>
    <div class='son'>
        {{msg}}
        <button @click="handler">点击获取数据</button>
    </div>
</template>

<script>
export default {
    props:["msg"],
    methods:{
        handler() {
            this.$emit('get','子组件的数据')
        }
    }
};
</script>

vue3

# 父组件
<template>
    <div class='father'>
        <my :msg="msg" @get="get"></my>
        {{sonMsg}}
    </div>
</template>

<script>
import my from '@/components/my'
import { reactive,toRefs } from 'vue'
export default {
    setup() {
        const obj = reactive({
            msg:'父组件的数据',
            sonMsg:''
        })

        const get = (val) =>{
            console.log(val);
            obj.sonMsg = val
        }

        return {
            ...toRefs(obj),
            get
        }
    },
    components:{
        my
    }
};
</script>
# 子组件
<template>
    <div class='son'>
        {{msg}}
        <button @click="handler">点击获取数据</button>
    </div>
</template>

<script>
export default {
    props:["msg"],
    setup(props,{attrs,slots,emit}) {
        const handler = ()=>{
            emit('get','子组件的数据')
        }

        return {
            handler
        }
    }
};
</script>

6. 移除了filter过滤器

在vue3中,移除了filter,我们可以使用计算属性进行代替

7. vue2和vue3的diff算法

vue2

vue2 diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。
vue2 diff算法会比较每一个vnode,而对于一些不参与更新的元素,进行比较是有点消耗性能的。

vue3

vue3 diff算法在初始化的时候会给每个虚拟节点添加一个patchFlags,patchFlags就是优化的标识
只会比较patchFlags发生变化的vnode,进行更新视图,对于没有变化的元素做静态标记,在渲染的时候直接复用。

8. v-if 和 v-for的优先级

vue2
我们最好不要把v-ifv-for同时用在一个元素上,这样会带来性能的浪费(每次都要先渲染才会进行条件判断)

v-for 优先于 v-if 生效
<div v-if="index == 1" v-for="(item,index) in arr" :key="index">{{item}}</div>

vue3

v-if 优先于 v-for 生效
<div v-if="index == 1" v-for="(item,index) in arr" :key="index">{{item}}</div>

在这里插入图片描述
vue中会给我们报警告:
意思就是:属性“index”在渲染期间被访问,但未在实例上定义(v-if先进行判断,但是这时候v-for还没有渲染,所以index是找不到的)

了解更多vue3的官网

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐