关于 Vue3 这些知识,你可能还不知道

1024程序员节 , 推荐一些前端开发工程师必读书籍本文已经作者 Matt Maribojoc 授权翻译!
Vue 是目前前沿开发中最热门的框架之一 , 到2019年每周的下载率翻了一番 。 2020 年初 Vue3的发布还会增加它的受欢迎程度 。
关于 Vue3 这些知识,你可能还不知道文章插图
Vue3 为开发人员提供了更多的控制 , 它使我们能够精确地控制项目中发生的事情 , 从编写定制的编译和渲染方法到直 Vue reactivity API 。
Vue3 使用 Proxy 来监听数据的变化响应性是 VueJS 的核心 , 数据必须具有依赖性 , 可以观察并进行更新以响应任何更改 , Vue2 使用 Object.defineProperty 创建 getter 和 setter 来实现响应式 。
使用Object.defineProperty有两个主要问题 , 在官方文档中都提到过:Vue 不能检测数组和对象的变化 。
对于对象
Vue 无法检测 property 的添加或移除 。 由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化 , 所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的 。
对于数组
Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时 , 例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时 , 例如: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 })})通过以反应式方法包装所有这些数据 , 所有数据在内部都将变为反应式 。 此状态模式来自Composition API文档 。
reactive() 函数接收一个对象作为参数 , 并返回一个代理对象 , 所有数据在内部都将变为响应式的 。
需要注意的一点是我们声明groceriesLeft变量的方式 。 它是一个计算的属性 , 并在setup()方法中定义 , 不再单独拎出来声明 。
function addGrocery() {state.groceries.push(state.input)state.input = ''}function deleteGrocery(index) {state.groceries.splice(index, 1)}函数声明倒是没啥变化 , 区别一点是由于所有响应数据都存储在state对象中 , 因此我们必须使用状态对象进行访问 , 但这不是Vue3特有的 。
return {state,addGrocery,deleteGrocery }最后 , 我们想从setup()方法返回这些函数 , 这样声明的数据和方法就可在模板内部访问 。
初次引入此方法时 , Vue 社区中存在许多反对 , 因为开发者不希望被迫编写这种新的方式 。 但是 , 这个也可选的 , 就是说我们仍然可以使用 vue2 方式来做 。