怎么创建自己的网站,南充网站制作,建设网站专业公司吗,凯胜东营小程序开发文章目录 生命周期多根节点Composition API组合式APIOptions API与composition API对比优化逻辑组织优化逻辑复用 异步组件(Suspense)Suspense组件 响应式原理性能体积优化编译优化diff算法优化静态提升数据劫持#xff08;响应式系统#xff09;优化 生命周期
vue3在组合AP… 文章目录 生命周期多根节点Composition API组合式APIOptions API与composition API对比优化逻辑组织优化逻辑复用 异步组件(Suspense)Suspense组件 响应式原理性能体积优化编译优化diff算法优化静态提升数据劫持响应式系统优化 生命周期
vue3在组合API中使用生命周期钩子时需要先引入而vue2在选项API中可以直接调用钩子 setup是围绕beforeCreate和created生命周期钩子运行的所以不需要显式地去定义 多根节点
vue2中在模板中如果使用多个根节点时会报错而vue3 支持多个根节点
Composition API组合式API
vue2 是选项式API(Options API),一个逻辑灰散乱在文件的不同位置data、props、computed、watch、生命周期等导致代码地可读性变差。 vue3组合式APIComposition PI则很好地解决了这个问题可将同一逻辑的内容写到一起增强了代码的可读性、内聚性其还提供了较为完美的逻辑复用性方案。
Options API与composition API对比
优化逻辑组织
Options API 碎片化使得理解和维护复杂组件变得困难, 选项的分离掩盖了潜在的逻辑问题。此外在处理单个逻辑关注点时我们必须不断地“跳转”相关代码的选项块 Compositon API 将某个逻辑关注点相关的代码全都放在一个函数里这样当需要修改一个功能时就不再需要在文件中跳来跳去
function useCount() {let count ref(10);let double computed(() {return count.value * 2;});const handleConut () {count.value count.value * 2;};console.log(count);return {count,double,handleConut,};
}
组件上使用count
export default defineComponent({setup() {const { count, double, handleConut } useCount();return {count,double,handleConut}},
});优化逻辑复用
在vue2中我们是通过mixin实现功能混合如果多个mixin混合会存在两个非常明显的问题命名冲突和数据来源不清晰
而通过composition这种形式可以将一些复用的代码抽离出来作为一个函数只要的使用的地方直接进行调用即可
在vue2中通过mixin实现功能混合的缺陷 1.命名冲突如果多个 Mixin 中包含了相同的选项会导致命名冲突这可能会导致不可预期的行为。 2.隐式依赖当多个 Mixin 依赖于相同的属性或方法时可能会出现隐式的依赖关系使得代码难以维护和理解。 3.耦合性增强Mixin 可能会导致组件与多个不同的代码片段紧密耦合这会增加代码的复杂度和维护难度。 4.全局污染如果一个 Mixin 修改了全局对象或其他共享资源可能会影响到整个应用程序。 5.不可追踪性当一个组件使用了多个 Mixin 时很难追踪每一个 Mixin 对组件行为的影响。 6.调试困难当出现问题时定位问题所在可能会比较困难特别是当多个 Mixin 交叉影响时。 7.组件复用性过度使用 Mixin 可能会导致组件的复用性降低因为组件的功能散布在多个 Mixin 中。 8.组件难以理解Mixin 可能会导致组件的行为变得复杂特别是当多个 Mixin 互相影响时会使得组件的行为难以理解。 因此在使用 Vue 2 中的 Mixin 时需要谨慎考虑尽量避免上述问题的出现。同时也可以考虑使用其他方式如使用组件复合、插槽slot、高阶组件Higher Order Component等来达到类似的功能复用效果但更加灵活和可控。vue3 的组合式API很好解决了这种问题 在 Vue 3 中提供了 Composition API组合式 API作为一种新的组件组织方式它可以更好地解决了在 Vue 2 中使用 Mixin 可能出现的一些问题 命名冲突问题减少Composition API 使用函数组合的方式可以将相关的逻辑组织在一个函数内部减少了命名冲突的可能性。 1.明确的依赖关系Composition API 允许你在组件内部明确地声明你的依赖关系这使得组件的依赖关系更加清晰。 2.提供了更强大的逻辑封装通过 Composition API可以更灵活地组合和封装逻辑使得代码更易于理解和维护。 3.模块化和可组合性Composition API 鼓励将逻辑以函数的形式封装这使得逻辑可以更容易地进行模块化和复用。 4.代码的可追踪性由于逻辑被封装在函数内部所以在组件内部可以更容易地追踪逻辑的来源和影响。 5.更好的代码隔离Composition API 允许你将逻辑按功能组织在不同的函数中从而实现更好的代码隔离减少了耦合性。 总的来说Composition API 提供了一种更灵活、可组合、可控的方式来组织组件的逻辑相比于 Vue 2 的 Mixin可以更好地解决了命名冲突、依赖关系不清晰等问题使得组件的代码更容易理解、维护和复用。 异步组件(Suspense)
Vue3提供Suspense组件允许程序在等待异步组件加载完成前渲染兜底的内容如loading使用户的体验更加平滑。使用它需要在模板中声明并包括两个名命插槽default和fallback。Suspense确保加载完异步内容时显示默认插槽并将fallback插槽用作加载状态
tempaltesuspensetemplate #defaultList //templatetemplate #fallbackdivLoading.../div/template/suspense
/templateSuspense组件
vue3中增加了一个名为Suspense的内置组件用于在异步组件加载完成前显示占位符避免页面空白或显示错误信息提高用户体验。 注意是一项实验性功能它不一定灰最终成为稳定功能并且在稳定之前相关API也可能会发生变化。
templatedivSuspensetemplate #defaultAsyncComponent //templatetemplate #fallbackdivLoading.../div/template/Suspense/div
/template
script setup langts
import { defineAsyncComponent } from vue
const AsyncComponent defineAsyncComponent(() import(./AsyncComponent.vue))
/script注意事项:
Suspense组件只能包含一个异步组件否则会抛出错误fallback插槽中的内容只能是一个单独的元素否则会抛出错误异步组件必须通过defineAsynsComponent方法定义否则无法使用Suspense组件。为了提高用户体验建议在fallback插槽中显示一个占位符如Loading
响应式原理
Vue2 响应式原理的基础是Object.defineProperty Vue3的响应式原理是Proxy
Object.defineProperty基本用法直接在一个对象上定义新的属性或修改现有的属性并返回对象
// 创建一个空对象
const person {};// 使用 Object.defineProperty 定义属性
Object.defineProperty(person, name, {value: John, // 属性值writable: false, // 不可写enumerable: true, // 可枚举configurable: false // 不可配置
});// 尝试修改属性值会失败因为属性是不可写的
person.name Mike;// 遍历对象的属性
for (let key in person) {console.log(key); // 输出 name因为属性是可枚举的
}// 删除属性会失败因为属性是不可配置的
delete person.name;// 重新定义属性为可配置
Object.defineProperty(person, name, {configurable: true
});// 现在可以成功删除属性
delete person.name;
vue2核心源码
function defineReactive(obj, key, val) {
//创建一个依赖实例每个属性对象一个依赖// 一 key 一个 depconst dep new Dep()// 获取 key 的属性描述符发现它是不可配置对象的话直接 returnconst property Object.getOwnPropertyDescriptor(obj, key)if (property property.configurable false) { return }// 获取 getter 和 setter并获取 val 值以及初始化值const getter property property.getconst setter property property.setif((!getter || setter) arguments.length 2) { val obj[key] }// 递归处理保证对象中所有 key 被观察let childOb observe(val)Object.defineProperty(obj, key, {//属性可枚举enumerable: true,//属性可配置configurable: true,// get 劫持 obj[key] 的 进行依赖收集get: function reactiveGetter() {const value getter ? getter.call(obj) : valif(Dep.target) {// 依赖收集将当前依赖观察者添加到属性的依赖列表中dep.depend()if(childOb) {// 针对嵌套对象依赖收集childOb.dep.depend()// 如果属性值是数组 还需要触发数组响应式if(Array.isArray(value)) {dependArray(value)}}}}//返回属性值return value})// set 派发更新 obj[key]set: function reactiveSetter(newVal) {//在这里实现属性的设置包括触发响应式更新...if(setter) {setter.call(obj, newVal)} else {val newVal}// 新值设置响应式childOb observe(val)// 依赖通知更新dep.notify()}
}
这段代码的主要功能是将对象的属性变成响应式的当属性的值来发生变化时可以自动通通知相关的视图进行更新。它通过Object.defineProperty来定义属性的get和set方法以及属性的特性例如可枚举、可配置等来实现这一功能。同时它还支持嵌套对象和数组的响应式处理。
性能
体积优化
相比于Vue2Vue3整体体积变小了移除了一些不常用的API任何一个函数比方说ref、reavived、computed等仅仅在用到的时候才打包没用到的模块都去掉打包整体体积变小最重要的是Tree shanking
Tree shanking是一种通过清除多余代码方式来优化项目打包体积的技术专业术语叫Dead code elimination
Tree shaking是基于ES6模板语法import与exports主要是借助ES6模块的静态编译思想在编译时就能确定模块的依赖关系以及输入和输出的变量
Tree shaking做了两件事
编译阶段利用ES6 Module判断哪些模块已经加载判断那些模块和变量未被使用或者引用进而删除对应代码
编译优化
diff算法优化
vue3在diff算法中相比vue2增加了静态标记, 其作用是为了会发生变化的地方添加一个flag标记下次发生变化的时候直接找该地方进行比较,提高性能。
静态提升
Vue3对不参与更新的元素会做静态提升只会被创建一次在渲染时直接复用这样就免去了重复的创建节点大型应用会受益于这个改动免去了重复的创建操作优化了运行时候的内存占用 没有做静态提升之前
export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [_createVNode(span, null, 你好),_createVNode(div, null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}
做了静态提升之后
const _hoisted_1 /*#__PURE__*/_createVNode(span, null, 你好, -1 /* HOISTED */)export function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock(_Fragment, null, [_hoisted_1,_createVNode(div, null, _toDisplayString(_ctx.message), 1 /* TEXT */)], 64 /* STABLE_FRAGMENT */))
}// Check the console for the AST
静态内容_hoisted_1被放置在render 函数外每次渲染的时候只要取 _hoisted_1 即可
同时 _hoisted_1 被打上了 PatchFlag 静态标记值为 -1 特殊标志是负整数表示永远不会用于 Diff
数据劫持响应式系统优化
在Vue2 中数据劫持就是通过Object.defineProperty这个API有一些缺陷检测不到对象属性的添加和删除 数组Api方法无法监听到需要对每个属性进行遍历监听如果嵌套对象需要深层监听造成性能问题
Object.defineProperty(data, a,{get(){// track},set(){// trigger}
})
Proxy直接可以劫持整个对象并返回一个新对象我们可以只操作新的对象达到响应式目的
function reactive(obj) {if (typeof obj ! object obj ! null) {return obj}// Proxy相当于在对象外层加拦截const observed new Proxy(obj, {get(target, key, receiver) {const res Reflect.get(target, key, receiver)console.log(获取${key}:${res})return isObject(res) ? reactive(res) : res}set(target, key, value, receiver) {const res Reflect.set(target, key, value, receiver)console.log(设置${key}:${value})return res},deleteProperty(target, key) {const res Reflect.deleteProperty(target, key)console.log(删除${key}:${res})return res}})return observed
}
同时Proxy 并不能监听到内部深层次的对象变化而 Vue3 的处理方式是在 getter 中去递归响应式这样的好处是真正访问到的内部对象才会变成响应式而不是无脑递归 Proxy的作用 在vue中 Proxy主要用于监听对象的变化以便在对象属性发生变化时自动更新相关的视图。这是Vue实现响应式数据绑定的核心机制之一
实现响应式数据的绑定 vue使Proxy对象来监听数据变化当数据发生变化时会自动触发相关视图更新。这使得开发者无需手动去追踪数据变化并更新视图大大简化了前端开发工作监听数据的读取和写入 Proxy可以拦截对象属性的读取和写入操作。这意味着在读取或写入数据时可以执行自定义的逻辑比如在写入时进行数据验证递归监听对象嵌套 Vue中的Proxy不仅可以监听对象本身还可以递归地监听对象内部的所有属性和嵌套对象。这使得整个数据结构都可以实现响应式数组变化的监听 对于数组Proxy 会拦截数组的变化操作如 push、pop、splice 等从而实现数组变化的响应式更新。动态添加属性 使用 Proxy 可以动态地向对象添加属性并且这个新属性也会被监听从而保证了新添加的属性也能实现响应式。防止非预期的属性访问 通过 Proxy 可以限制对象属性的访问防止对某些属性的非法访问或修改。监听对象的删除 Proxy 还可以监听对象属性的删除操作当属性被删除时可以执行相应的逻辑。