Vue3 使用 Proxy 来监听数据的变化
响应性是 VueJS 的核心,数据必须具有依赖性,可以观察并进行更新以响应任何更改,Vue2 使用 Object.defineProperty 创建 getter 和 setter 来实现响应式。
使用Object.defineProperty有两个主要问题,在官方文档中都提到过:Vue 不能检测数组和对象的变化。
对于对象
Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
对于数组
Vue 不能检测以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:vm.items.length = newLength
举个例子:
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是响应性的 vm.items.length = 2 // 不是响应性的
为什么使用 Proxy ?
Vue3 的解决方案是使用基于Proxy的观察者模式来解决 Vue2 响应上的一些限制。
新旧系统之间的主要区别在于,在Vue2中,Object.defineProperty会修改原始数据,而Proxy则不会,Proxy 虚拟化目标数据并设置不同的处理程序(称为target),这些处理程序通过getters和setter拦截数据。
Vue3 意味着我们无需使用vm.$set来让数据动态的响应,同时也解决 vue2 操作数组无法响应的问题。
正如尤雨溪大哥所总结的那样,基于代理可以支持:
- 检测属性
添加/删除 - 检测数组
index/length的变化 - 支持
Map,Set,WeakMap和WeakSet
Composition API
这是到目前为止 Vue3 最大的一个变化,它有助于代码的组织和重用性。
目前,在Vue中我们使用是Options API。Options API按属性组织代码:data,computed,methods等。
这是一个非常直观的方式,但维护一些复杂组件变得非常困难。单个功能的代码通常在相隔数百行的多个地方抛出。
可维护性和可读性成为主要问题。
接着,我们快速了解一下Composition API的工作原理。
import { reactive, computed } from 'vue'
export default {
setup() {
let state = reactive({
input: '',
groceries: [],
groceriesLeft: computed(() => { groceries.length })
})
function addGrocery() {
state.groceries.push(state.input)
state.input = ''
}
function deleteGrocery(index) {
state.groceries.splice(index, 1);
}
return {
state,
addGrocery,
deleteGrocery
}
}
}
我们来分析一下,上面的过程 😉
import { reactive, computed } from 'vue'
Vue Composition API公开了Vue中的许多核心功能,比如reactive和组件方法,所以,我们需要导入它们。
export default { setup() {
setup()方法的引入是 Vue3 中最大的变化之一。从本质上讲,它使我们能够确定传递回模板的内容,无论返回什么,都可以在模板中访问。
我们可以在 setup 里面设置reactive 数据,生命周期,计算属性,定义的方法并返回我们想要的任何东西。
let state = reactive({ input: '', groceries: [], groceriesLeft: computed(() => { groceries.length }) })
浙公网安备 33010602011771号