<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次 Vue2 遷移 Vue3 的實踐總結

          共 6817字,需瀏覽 14分鐘

           ·

          2022-03-03 17:16

          一、Vue3

          Vue3中文文檔[1]

          • Vue3是什么,與Vue2區(qū)別(What)
          1. Performance:性能更強。
          2. Tree shaking support:可以將無用模塊“剪輯”,僅打包需要的。
          3. Composition API:組合式API
          4. Fragment, Teleport, Suspense:“碎片”,TeleportProtal傳送門,“懸念”
          5. Better TypeScript support:更優(yōu)秀的Ts支持
          6. Custom Renderer API:暴露了自定義渲染API
          • 為什么要大版本迭代 (Why)
          1. 主流瀏覽器對新的JavaScript語言特性的普遍支持。
          2. 當前Vue代碼庫隨著時間的推移而暴露出來的設計和體系架構問題。
          • 他是如何提升的(How)
          1. 響應式系統(tǒng)提升: 使用Proxy提升了響應式的性能和功能
          2. 編譯優(yōu)化: 標記和提升所有的靜態(tài)節(jié)點,diff時只需要對比動態(tài)節(jié)點內容
          3. 事件緩存: 提供了事件緩存對象cacheHandlers,無需重新創(chuàng)建函數(shù)直接調用緩存的事件回調
          4. 打包和體積優(yōu)化: 按需引入,Tree shaking支持(ES Module)

          二、編碼

          全局API

          1. 新增】createApp: 入口文件(main.ts)掛載方式
          import?{?createApp?}?from?"vue";

          import?App?from?"./App.vue";



          //?Vue2

          new?Vue({

          ???render:?(h)?=>?h(App)

          }).$mount("#app");



          //?Vue3

          createApp(App)

          ??.use(**)

          ??.mount("#app");
          1. 【修改】
          2.x 全局 API3.x 實例 API (app)
          Vue.configapp.config
          Vue.config.productionTip
          Vue.config.ignoredElementsapp.config.isCustomElement
          Vue.componentapp.component
          Vue.directiveapp.directive
          Vue.mixinapp.mixin
          Vue.useapp.use
          Vue.prototypeapp.config.globalProperties

          config.ignoredElements替換為config.isCustomElement

          引入此配置選項的目的是支持原生自定義元素,因此重命名可以更好地傳達它的功能,新選項還需要一個比舊的 string/RegExp 方法提供更多靈活性的函數(shù):

          //?Vue2

          Vue.config.ignoredElements?=?[

          ??//?用一個?`RegExp`?忽略所有“ion-”開頭的元素

          ??//?僅在?2.5+?支持

          ??/^ion-/

          ]



          //?Vue3

          const?app?=?Vue.createApp({})

          app.config.isCustomElement?=?tag?=>?tag.startsWith('ion-')

          Vue.prototype 替換為 config.globalProperties

          在Vue 2中,Vue.prototype通常用于添加可在所有組件中訪問的屬性。

          Vue 3中的等效項是config.globalProperties。在實例化應用程序內的組件時,將復制這些屬性

          //?Vue2

          Vue.prototype.$http?=?()?=>?{}



          //?Vue3

          const?app?=?Vue.createApp({})

          app.config.globalProperties.$http?=?()?=>?{}

          生命周期

          2.0生命周期3.0生命周期
          beforeCreate(組件創(chuàng)建之前)setup()
          created(組件創(chuàng)建完成)setup()
          beforeMount(組件掛載之前)onBeforeMount(組件掛載之前)
          mounted(組件掛載完成)onMounted(組件掛載完成)
          beforeUpdate(數(shù)據更新,虛擬DOM打補丁之前)onBeforeUpdate(數(shù)據更新,虛擬DOM打補丁之前)
          updated(數(shù)據更新,虛擬DOM渲染完成)onUpdated(數(shù)據更新,虛擬DOM渲染完成)
          beforeDestroy(組件銷毀之前)onBeforeUnmount(組件銷毀之前)
          destroyed(組件銷毀之后)onUnmounted(組件銷毀之后)
          activated(被 keep-alive 緩存的組件激活時調用)onActivated(被激活時執(zhí)行)
          deactivated(被 keep-alive 緩存的組件停用時調用)onDeactivated(比如從 A 組件,切換到 B 組件,A 組件消失時執(zhí)行)
          errorCaptured(當捕獲一個來自子孫組件的錯誤時被調用)onErrorCaptured(當捕獲一個來自子孫組件的異常時激活鉤子函數(shù))

          新特性

          1. Options API => Composition API
          1. setup()
          import?{toRefs}?from?'vue'

          export?default?{

          ????name:?'demo',

          ????props:{

          ??????name:?String,

          ????},

          ????// setup()作為在組件內使用Composition API的入口點。

          ????//?執(zhí)行時機是在beforeCreate和created之間,不能使用this獲取組件的其他變量,

          ????//?而且不能是異步。setup返回的對象和方法,都可以在模版中使用。

          ????setup(props,?context){

          ??????//?這里需要使用toRefs來進行解構

          ??????//?這里的props與vue2基本一致,當然這里的name也可以直接在template中使用

          ??????const?{?name?}=toRefs(props);

          ??????console.log(name.value);

          ??????

          ??????//?context是一個上下文對象

          ??????//【從原來?2.x?中?this?選擇性地暴露了一些?property(attrs/emit/slots)】

          ??????//?屬性,同vue2的?$attrs

          ??????console.log(context.attrs);

          ??????//?插槽

          ??????console.log(context.slots);

          ??????//?事件,同vue2的?$emit

          ??????console.log(context.emit);

          ??????//?生命周期鉤子

          ??????onMounted(()?=>?{})

          ??}

          }

          注意點:

          • 注意 props 對象是響應式的,watchEffectwatch 會觀察和響應 props 的更新,不要解構 props 對象,那樣會使其失去響應性
          • attrsslots 都是內部組件實例上對應項的代理,可以確保在更新后仍然是最新值。所以可以解構,無需擔心后面訪問到過期的值
          • this setup()中不可用。由于 setup() 在解析 2.x 選項前被調用,setup() 中的 this 將與 2.x 選項中的 this 完全不同。同時在 setup() 和 2.x 選項中使用 this 時將造成混亂
          1. 響應式reactive,ref
          import?{?ref,?reactive,?toRefs?}?from?'vue';



          setup()?{

          ????//?ref

          ????//?ref?對我們的值創(chuàng)建了一個響應式引用

          ????const?counter?=?ref(0);?

          ????

          ????//?reactive

          ????//?接收一個普通對象然后返回該普通對象的響應式代理

          ????const?obj?=?{a:1};

          ????const?objReactive?=?reactive(obj);



          ????const?add?=?()?=>?{

          ??????counter.value++;

          ??????objReactive.a++;

          ????}

          ????

          ????return?{

          ??????counter,??//?return返回會自動解套【在模板中不需要.value】

          ??????objReactive,

          ??????add,

          ????};?//?這里返回的任何內容都可以用于組件的其余部分

          }


          refreactive
          入參基本類型引用類型
          返回值響應式且可變的 ref 對象響應式代理(Proxy)
          訪問方式1.ref 對象擁有一個指向內部值的單一屬性 .value
          2.在dom和setup()的return中會自動解套
          3.ref 作為 reactive 對象的 property 被訪問或修改時,也將自動解套
          直接.訪問即可

          問題 & 注意點: 因為reactive是組合函數(shù)【對象】,所以必須始終保持對這個所返回對象的引用以保持響應性,不能解構該對象或者展開

          例如:

          const { a } = objReactive或者return { ...objReactive }

          解決方法:

          toRefs API

          用來提供解決此約束的辦法——它將響應式對象的每個 property 都轉成了相應的 ref【把對象轉成了ref】。

          import?{?reactive,?toRefs?}?from?'vue';



          setup()?{

          ????//?reactive

          ????//?接收一個普通對象然后返回該普通對象的響應式代理

          ????const?obj?=?{a:1};

          ????const?objReactive?=?reactive(obj);

          ????

          ????//?toRefs

          ????//?將響應式對象轉換為普通對象,其中結果對象的每個?property?都是指向原始對象相應?property?的ref

          ????const?objRef?=?toRefs(objReactive);

          ????

          ????const?{?a?}?=?objRef;

          ????const?addObj?=?()?=>?{

          ??????a.value++;

          ??????console.log(a.value,?objRef,?objReactive,?obj);

          ????}



          ????return?{

          ??????...objRef,

          ??????addObj

          ????};?

          }
          • Hooks方式
          1. counter.js
          import?{?ref?}?from?'vue';



          export?function?useCounter()?{

          ????const?count?=?ref(0);

          ????const?decrement?=?()?=>?{

          ????????count.value--;

          ????}

          ????const?increment?=?()?=>?{

          ????????count.value++;

          ????}

          ????return?{

          ????????count,

          ????????decrement,

          ????????increment

          ????}

          }
          1. 父組件