vue3 “用后感”

11,172 阅读5分钟

vue3的源码已经开放很久了,官网也火速出了新文档。但奈何我的速度总是能和蜗牛相比。正好,最近有做到vue3的项目。那我来写一篇 “用后感” 吧!把项目中学习到的关于vue3的理解分享给大家。

这里做一个简单的归纳,个人认为vue3中值得大家注意的点:

  • 1、数据拦截机制的变更
  • 2、组合API的引入
  • 3、setup函数带来的一系列惊喜
  • 4、响应式API的实际应用

一、数据拦截机制的变更

vue2 通过 Object.defineProperty() 方式来截持数据的变更。而在升级为 vue3 之后,作者不再借助 Object.defineProperty 来劫持数据,而是通过 es6 的新特性 proxy 来劫持数据。因为在 vue2 中,响应式数据需要通过 data() 初始化预先定义好,但是在 vue3 之后,data 中的数据不再进行响应式追踪,而是将它转化为proxy 代理再进行追踪更新。

code view

注意: 在vue3中,它将任何在data()函数中定义的数据,会使用getter或setter遍历所有的property,将其转化成proxy代理。


二、组合API的引入

vue3中最大的改变还是compositionApi的引入,这是vue3中的最核心的部分。

包括以下几方面:

  • a、setup函数

下一节有详细介绍,这里就不赘述了。

  • b、生命周期钩子

vue3抛出了全局的API,通过引入 onX 的形式,使setup函数中支持钩子函数的调用。

  • c、provide/Inject

vue3 中也支持在 setup 函数中使用 provide和inject,只要在对应的位置引入即可:

import { provide } from 'vue';
setup(){
	provide(name, 'hello!');
}

import {inject} from 'vue';
setup(){
	inject('name', [default-value]: string);
}

  • d、getCurrentInstance

支持在setup函数中访问自己的实例

import { getCurrentInstance } from 'vue';
setup() {
	const internalInstance = getCurrentInstance();
}

三、setup函数带来的一系列惊喜

在vue3中,setup函数的引入,这种函数式的开发方式,很好地将代码整合到一起。

  • 在vue2中,data数据需要在使用的时候调用this访问,现在vue3中使用reactive,ref来设置响应式数据。
data() {
    return {
        name: 'aaa',
    };
}

=>

const name = ref('aaa');  
就像简单的定义变量一样,使用ref就可以为变量初始化
  • setup函数取代了methods的函数定义方式

在setup函数中,我们可以选择性地对外暴露我们定义的函数。 在vue2中,我们所定义在methods里的函数,都绑定到了this上。this得有多累啊 (> 3 >),而setup函数却正好解决了这个问题,很好地保护了我们自己定义的私有变量。

methods: {
    function unkouwnFunc() {
        console.log(3333);
    }
},

=>

setup () {
    function unkownFunc() {
        console.log(3333);
    }

    return {
        unkownFunc, // return之后,该函数绑定到了组件实例上,可以在模版中直接使用
    };
}
  • 关于setup函数中使用emit事件
import { SetupContext } from 'vue';
  	
emits: ['eventName'],
setup(props, ctx: SetupContext){
    ctx.emit('event-name', value);
}
    
  • 另外作者为了支持setup函数,向外抛出了全局的生命周期钩子,只在setup函数中使用有效。
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue';

setup() {
    onBeforeMount() {
        your code
    }
    onMounted () {
        your code
    }
    onBeforeUpdate() {
        your code
    }
    onUpdated() {
        your code
    }
    onBeforeUnmount() { 
        your code
    }
    onUnmounted() {
        your code
    }
}

四、响应式API的实际应用

  • Ref Vs Reactive

    ref 是一种基本数据类型的创建方式,返回的是一个 RefImpl 对象。value 指向其绑定的值。如果用它来创建对像的话,会将它的 value 返回一个 reactive 对象。

    reactive 对象的返回的是一个 proxy 代理,他在创建的时候,就会一一遍历每一个属性,并将它创建为 es6 代理方式。

    ref & reactive

    从打印的数据我们可以看出,ref数据创建的对象类型的.value跟reactive的数据结构是一致的。也就是说,在ref创建对象类型的数据时,对自动转化为reactive数据。

  • Ref和reactive API带来的便利

    vue3中的 ref的reactive 非常非常的好用,为什么这么说?因为vue在这里直接给出了他的全局API。不管在任何场景下,我们都可以直接引入,并创建这个响应式的数据。通过导入,导出,实现代码的 集中化管理

    所谓 集中化管理, 在这里指的是代码的运用灵活度提升了,vue2中,使用store来集中管理状态,而现在,我们可以直接真正抛弃store了。因为vue3的响应式API 给我们带来了非常nice的体验。

>> state.js 
    
  store = {
    state: reactive({
      count: 0,
    })
  };

  export default store;
        
=>
    
import store from 'state.js';
setup() {
  // set count
  store.count = 2;
  // get count
}
  • 关于computed和watch的使用问题
computed: {
	aaa() => {
        	return 333
        }
    },
    watch: {
    	bbb(newv, oldv) {
        	console.log(newv, oldv);
        }
    },
}
    

=>
    
import { computed } from 'vue';

const aaa = computed(() => {
  return 333;
})

watch & watchEffect

import {watchEffect, watch} from 'vue';

// watch 实现了$watch全部的功能
// 单个数据源侦听
watch((bbb, (current, prev)) => {
  Your Code
});

// 多个数据源的侦听
watch([aaa, bbb], ([current, prev], [current2, prev2]) => {
  Your Code
})


// watchEffect 只追踪依赖项的变更,在变化时,会执行回调函数
const aaa = ref(0);
watchEffect(() => {
  console.log(aaa.value);
});

watch VS watchEffect

  • 1、惰性侦听

    watchEffect 只具备追踪变更的功能,并且在追踪依赖项的时候就会执行回调函数 watch 相比,会惰性侦听依赖项,在追踪依赖项的时候,不会执行回调函数。

  • 2、支持访问当前和之前的状态
  • 3、更具体地说明什么情况下应该触发对调函数

    应该是watch相对于watchEffect给出了更多的选项。 比如,获取之前和现在的状态,通过状态的变化,我们可以判段是否执行对应的回调。

想看更详细的内容,请戳这里>

END TK U