参考答案:
不以解决实际业务痛点的更新都是耍流氓,下面我们来列举一下Vue3
之前我们或许会面临的问题
随着功能的增长,复杂组件的代码变得越来越难以维护
缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制
类型推断不够友好
bundle
的时间太久了
而 Vue3
经过长达两三年时间的筹备,做了哪些事情?
我们从结果反推
一句话概述,就是更小更快更友好了
Vue3
移除一些不常用的 API
引入tree-shaking
,可以将无用模块“剪辑”,仅打包需要的,使打包的整体体积变小了
主要体现在编译方面:
下篇文章我们会进一步介绍
vue3
在兼顾vue2
的options API
的同时还推出了composition API
,大大增加了代码的逻辑组织和代码复用能力
这里代码简单演示下:
存在一个获取鼠标位置的函数
1import { toRefs, reactive } from 'vue'; 2function useMouse(){ 3 const state = reactive({x:0,y:0}); 4 const update = e=>{ 5 state.x = e.pageX; 6 state.y = e.pageY; 7 } 8 onMounted(()=>{ 9 window.addEventListener('mousemove',update); 10 }) 11 onUnmounted(()=>{ 12 window.removeEventListener('mousemove',update); 13 }) 14 15 return toRefs(state); 16}
我们只需要调用这个函数,即可获取x
、y
的坐标,完全不用关注实现过程
试想一下,如果很多类似的第三方库,我们只需要调用即可,不必关注实现过程,开发效率大大提高
同时,VUE3
是基于typescipt
编写的,可以享受到自动的类型定义提示
vue3
从很多层面都做了优化,可以分成三个方面:
源码可以从两个层面展开:
vue3
整个源码是通过 monorepo
的方式维护的,根据功能将不同的模块拆分到packages
目录下面不同的子目录中
这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确,开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性
另外一些 package
(比如 reactivity
响应式库)是可以独立于 Vue
使用的,这样用户如果只想使用 Vue3
的响应式能力,可以单独依赖这个响应式库而不用去依赖整个 Vue
Vue3
是基于typeScript
编写的,提供了更好的类型检查,能支持复杂的类型推导
vue3
是从什么哪些方面对性能进行进一步优化呢?
这里讲述数据劫持:
在vue2
中,数据劫持是通过Object.defineProperty
,这个 API 有一些缺陷,并不能检测对象属性的添加和删除
1Object.defineProperty(data, 'a',{ 2 get(){ 3 // track 4 }, 5 set(){ 6 // trigger 7 } 8})
尽管 Vue
为了解决这个问题提供了 set
和delete
实例方法,但是对于用户来说,还是增加了一定的心智负担
同时在面对嵌套层级比较深的情况下,就存在性能问题
1default { 2 data: { 3 a: { 4 b: { 5 c: { 6 d: 1 7 } 8 } 9 } 10 } 11}
相比之下,vue3
是通过proxy
监听整个对象,那么对于删除还是监听当然也能监听到
同时Proxy
并不能监听到内部深层次的对象变化,而 Vue3
的处理方式是在 getter
中去递归响应式,这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归
这里当然说的就是composition API
,其两大显著的优化:
一张图,我们可以很直观地感受到 Composition API
在逻辑组织方面的优势
相同功能的代码编写在一块,而不像options API
那样,各个功能的代码混成一块
在vue2
中,我们是通过mixin
实现功能混合,如果多个mixin
混合,会存在两个非常明显的问题:命名冲突和数据来源不清晰
而通过composition
这种形式,可以将一些复用的代码抽离出来作为一个函数,只要的使用的地方直接进行调用即可
同样是上文的获取鼠标位置的例子
1import { toRefs, reactive, onUnmounted, onMounted } from 'vue'; 2function useMouse(){ 3 const state = reactive({x:0,y:0}); 4 const update = e=>{ 5 state.x = e.pageX; 6 state.y = e.pageY; 7 } 8 onMounted(()=>{ 9 window.addEventListener('mousemove',update); 10 }) 11 onUnmounted(()=>{ 12 window.removeEventListener('mousemove',update); 13 }) 14 15 return toRefs(state); 16}
组件使用
1import useMousePosition from './mouse' 2export default { 3 setup() { 4 const { x, y } = useMousePosition() 5 return { x, y } 6 } 7}
可以看到,整个数据来源清晰了,即使去编写更多的hook
函数,也不会出现命名冲突的问题
最近更新时间:2024-08-10