一、Vue3的優點
- 1、diff算法的提升
vue2中的虛擬DOM是全量的對比,也就是不管是寫死的還是動態節點都會一層層比較,浪費時間在靜態節點上。
vue3新增靜態標記(patchflag ),與之前虛擬節點對比,只對比帶有patch flag 的節點,可通過flag信息得知當前節點要對比的具體內容。
例如: 當代碼中包含數據時,會標記為動態。
- 2、靜態提升
vue2不管是否參與更新,都會重新創建再渲染。
vue3對於不參與更新的元素,會做靜態提升,只被創建一次,在渲染時直接復用即可。
- 3、事件偵聽器緩存。
- 4、 ssr渲染
- 5、更好的ts支持
- 6、Composition Api
vue2的組件內部都是options api風格,也就是在data, methods, mounted等來組織代碼,這樣會讓邏輯很分散,每次變動需要反復查找位置。
vue3中使用setup,邏輯都放到里邊。
- 7、更先進的組件
vue2不允許template下寫兩個組件,vue3允許,將為我們創建一個虛擬的Fragment節點。
- 8、自定義渲染api
const { createApp } from 'vue' import App from "./src/App" createApp(App).mount(('#app')
- 9、按需編譯,體積比vue2更小
- 10.支持多根節點組件
二、響應式原理不同:
- vue2實現雙向數據綁定原理,是通過ES5的Object.defineProperty,根據具體的key去讀取和修改。其中的setter方法來實現數據劫持,getter實現數據修改。但是必須要先知道攔截和修改的key,所以vue2對於新增的屬性無能為力,比如無法監聽屬性的新增和刪除,數組索引和長度的變更,解決方法使用Vue.set(object, properName,value)等嵌套對象添加響應式。
function observe(obj, callback) { let newObj = {}; Object.keys(obj).forEach((key) => { Object.defineProperty(newObj, key, { enumerable: true, configurable: true, get() { return obj[key]; }, set(val) { obj[key] = val; callback(key, val); } }) }) return newObj; } let obj = observe({ name: 'alan', age: '1888' }, (key, value) => { console.log(`打印${value}`) });
- 在vue3中使用es5中得更快的proxy,替代了Object.defineProperty。proxy可以理解為在對象外加了一層攔截,任何人要訪問該對象,都要通過這層攔截。且proxy直接對對象攔截而非屬性,並返回一個對象,具有更好的響應式支持。
function obseve2(obj, callback) { return new Proxy(obj, { set(target, key, value) { target[key] = value; callback(key, value); }, get(taget, key) { return taget[key]; } } ) } let obj2 = obseve2({ x: 1, y: 2 }, (key, value) => { console.log('坐標系') })
三、生命周期變化
初始化加載順序:
setup
=> beforeCreate
=> created
=> onBeforeMount
=> onMounted
vue3壓縮后變快,很大程度是因為這些使用都需要引入了。
!!! vue3中的核心api都支持了tree-shaking,這些api都是通過包引入的方式而不是直接在實例化時就注入,只會對使用到的功能或特性進行打包(按需打包),這意味着更多的功能和更小的體積。
四、mixins更改
在vue2 使用mixins來實現相同邏輯的抽離,每個組件只需要引入mixins,就能實現復用。
創建js文件,寫入
export default { data(){ return {} }, methods:{}, computed:{}, filters:{}, created(){}, mounted(){ console.log("我是mixins"); } }
使用方法:
引入js文件,寫入mixins:[ ]
缺點:mixins的聲明周期會和引入mixins的組件的生命周期整合在一起。且minxins的生命周期比組件調用快。組件的data,methods會覆蓋同名data,methods。
1.變量來源不明確(隱式傳入),不利於閱讀,使代碼變得難以維護。
2.多個mixins的生命周期會融合到一起運行,但是同名屬性、同名方法無法融合,可能會導致沖突。
3.mixins和組件可能出現多對多的關系,復雜度較高(即一個組件可以引用多個mixins,一個mixins也可以被多個組件引用)。
vue3中的改進:
自定義hook的作用類似vue2的mixin,封裝可復用的功能函數。
import { ref,computed } from "vue"; export function useCount(){ const num = ref(10); const doubles = computed(() => num.value * 2); return { num, doubles } }
import {useCount} from './useCount' //初始化 const {num,doubles}=useCount();
五、父子傳值的變化
在vue2中使用props傳值。
在vue3中依舊使用,但是傳值寫法有所變化。
vue3 父組件
<page2 :name="ageRef" @clickParent="clickParent"></page2> function clickParent() { console.log('我想點擊父組件') }
子組件
<template> <div> 我是子組件page2啊: <div @click="emitP">{{name}}</div> </div> </template> <script> import { toRefs } from 'vue' export default{ props:{ name: String, }, setup(props,context){ let {name}=toRefs(props); let {slots,emit}=context; function emitP(){ emit('clickParent'); } return{ name, emitP } } } </script>
context:
包含 attrs
, slots
, emit
等數據方法:
attrs
:獲取組件上的屬性slots
:獲取 slot 插槽的節點emit
:emit 方法(子組件向父組件傳遞數據)
setup 函數是 Vue3 中新增的一個生命周期函數,會在 beforeCreate
之前調用。因為此時組件的 data
和 methods
還沒有初始化,因此在 setup 中是不能使用 this
的。所以 Vue 為了避免我們錯誤的使用,它直接將 setup 函數中的 this
修改成了undefined
。並且,我們只能同步使用setup函數,不能用async將其設為異步。
setup 函數接收兩個參數 props
和 context
, 語法為:setup(props,context){}
props
props
里面包含父組件傳遞給子組件的所有數據。在子組件中使用 props
進行接收。
props
是響應式的, 當傳入新的 props
時,會及時被更新。
由於是響應式的, 所以不可以使用 ES6 解構,解構會消除它的響應式。可以使用toRefs
provide,inject 父組件向子組件傳遞方法和數據
api均從vue中引入。
在父組件直接provide(‘別名’,變量或方法);
在子組件直接inject(‘別名’)
六、碎片化節點
在vue2中,template下只允許存在一個根節點,在vue3中可以有多個跟結點。
參考文章:
https://www.cnblogs.com/bingcola/p/15210566.html