自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

升級 Vue3 大幅提升開發(fā)運行效率

開發(fā) 開發(fā)工具
原計劃 2019 年發(fā)布的 Vue3,又經(jīng)過一年的再次打磨,終于于去年 9 月正式發(fā)布。隨后,不少 UI 組件庫都積極參與適配,去年 12 月,Element-plus(Element-ui 官方升級版)也發(fā)布了 beta 版。

[[395993]]

背景

原計劃 2019 年發(fā)布的 Vue3,又經(jīng)過一年的再次打磨,終于于去年 9 月正式發(fā)布。隨后,不少 UI 組件庫都積極參與適配,去年 12 月,Element-plus(Element-ui 官方升級版)也發(fā)布了 beta 版。

由于項目中用到了 Element-ui 組件,組件庫未適配的情況下,不敢貿(mào)然升級 Vue3。Element-plus 發(fā)布后,又經(jīng)過 1 個月的觀察、測試和調(diào)研,發(fā)現(xiàn) Element-plus 相對成熟(還有少量 bug,后續(xù)會講),便開始嘗試升級 Vue3。

如何升級 Vue3

有兩種方案可以快速升級 Vue3:

  • 一種是使用微前端輪子,我基于 qiankun2,搭建了 Vue3 項目基座,為了保證平穩(wěn)升級,子項目繼續(xù)使用 Vue2,然后不斷的把子項目的頁面遷移到基座項目。
  • 另一種是,直接升級 Vue3,將項目中的 Vue2 依賴庫升級到 Vue3 的最新版(當前最新版是v3.0.11),并且稍微改造 webpack 編譯腳本,使之適配 Vue3。

之所以會有方案一,主要還是擔心 Element-plus 不夠穩(wěn)定,如果有天坑,又無法繞過去,除了向餓了么團隊提交 PR,微前端兜個底也是不錯的應(yīng)急措施。

就這樣微前端方案又運行了 1 個月,部分頁面已完成升級,運行良好,實踐證明 Element-plus 比想象中穩(wěn)定,這增加了我對于方案二的信心??紤]到還有少量業(yè)務(wù)復(fù)雜的頁面,在微前端模式下,子項目的各種數(shù)據(jù)多經(jīng)過一層 qiankun 的 proxy 代理,性能有損耗,影響了頁面更新,于是一次性將剩余的頁面全部遷移到 Vue3 項目中。

實踐證明,除非比較復(fù)雜的項目,或者依賴組件庫沒升級等原因不適合升級外,常規(guī)情況下,升級 Vue3 都是一個不錯的選擇。

為什么要升級 Vue3

為什么要升級 Vue3,這是一個幾乎不需要回答的問題。升級 Vue3 后,代碼結(jié)構(gòu)更加清晰內(nèi)聚,響應(yīng)式數(shù)據(jù)流更加可控,節(jié)省了很多心智成本,從而使得開發(fā)效率大幅提升。Vue3 還帶來了很多新特性,框架層面運行性能更高(性能提升了 1.3 至 2 倍,SSR 性能提升了 2 至 3 倍),Composition API 使得代碼拆分,函數(shù)封裝更容易,復(fù)雜項目也隨之更容易管理。

Vue2 中,相關(guān)的邏輯經(jīng)常分散在 option 的 data、watch、computed、created、mounted 等鉤子中,閱讀一段代碼,經(jīng)常需要上下反復(fù)橫跳,帶來了部分閱讀障礙。鉤子又依賴 Vue 實例,代碼封裝基于天生攜帶鉤子的 Mixin 去做,更加容易和相對方便。

但正因為如此,Mixin 的鉤子容易不自覺的越界,插手到頁面或組件的內(nèi)部變量和方法管理過程中;甚至,多個不同的 Mixin,相互之間就很容易沖突,項目開發(fā)者,在引入 Mixin 和避免沖突之間需要保持微妙的平衡,不但增加心智負擔,還帶來了副產(chǎn)品:本身撲朔迷離的 this 變得更加不確定。因此,大型項目 Mixin 幾乎都是一種反模式。

現(xiàn)在這些框架問題,都由 Vue3 的 Composition API 解決了。

Vue3 帶來了哪些新特性

我們先看一些立馬能感受到變化的特性。

 

Proxy 代理

這是一個一上手 Vue3 就能感知的變化。即使你在 Vue3 中編寫 Vue2 風(fēng)格的基于 option 的代碼,Proxy 也是默默提供著數(shù)據(jù)響應(yīng)式。

  1. const observe = (data) => { 
  2.   Object.keys(data).forEach((key) => { 
  3.     const initValue = data[key]; 
  4.     let value = initValue; 
  5.     if (typeof initValue === 'object') { 
  6.       observe(initValue); 
  7.       return
  8.     } 
  9.     Object.defineProperty(data, key, { 
  10.       enumerable: true
  11.       configurable: true
  12.       get() { 
  13.         console.log('visit key value ='key, value); 
  14.         return value; 
  15.       }, 
  16.       set(val) { 
  17.         console.log(`[${key}]changed,old value=${value}, new value = ${val}`); 
  18.         if(value !== val) { 
  19.           value = val; 
  20.         } 
  21.       } 
  22.     }); 
  23.   }); 
  24. }; 
  25. const data = {}; 
  26. Array.from(new Array(100), () => "").forEach((item, i) => { 
  27.   data[i] = { value: i * 2 }; 
  28. }); 
  29. console.time(); 
  30. observe(data); 
  31. console.timeEnd(); // default: 0.225ms 
  32. data.a = { b: 1 }; 
  33. data.a.b = 2; 

如上所示,Vue2 的數(shù)據(jù)響應(yīng)式是通過 Object.defineProperty 實現(xiàn),這是一個深度遍歷的過程,無論 data 中包含多少層數(shù)據(jù),都需要全部遍歷一遍。深度遍歷,給對象的每個自身屬性添加 defineProperty,需要不小的性能開銷,同時后面新增到 this 中的屬性不提供響應(yīng)式監(jiān)聽,因此我們需要使用諸如this.$set這種方式去添加新屬性。

Proxy 就沒有這個問題,如下所示。

  1. const observe = (data) => { 
  2.  return new Proxy(data, { 
  3.   get(target, key, receiver) { 
  4.    console.log('visit'key); 
  5.    return Reflect.get(target, key, receiver); 
  6.   }, 
  7.   set(target, key, value, receiver) { 
  8.    console.log(`[${key}]changed, value = ${value}`); 
  9.    Reflect.set(target, key, typeof value === 'object' ? observe(value) : value, receiver); 
  10.   } 
  11.  }); 
  12. }; 
  13. let data = {}; 
  14. Array.from(new Array(100), () => "").forEach((item, i) => { 
  15.   data[i] = { value: i * 2 }; 
  16. }); 
  17. console.time(); 
  18. const proxy = observe(data); 
  19. console.timeEnd(); // default: 0.041ms 
  20. proxy.a = { b: 1 }; // [a]changed, value = [object Object] 
  21. proxy.a.b = 2; // visit a \n [b]changed, value = 2 

Proxy 不但使得 data 獲得了新屬性的響應(yīng)性,整個響應(yīng)式處理過程的效率還提升了數(shù)倍,由此帶來了 Vue3 的大部分性能提升。

Composition API

為了保持對 Vue2 的向下兼容,Vue3 中仍然支持純 Option 配置的書寫方式,這為升級提供了便利,平移 Vue2 的代碼,只需少量改動,便可正常運行。

同時考慮到上手難度,Vue3 的頂層代碼風(fēng)格與 Vue2 保持一致,依然是 export 一個對象,對象包含了一系列的配置,其中便有 setup 入口函數(shù)。我們先來看一段代碼,然后逐個解讀。

  1. import { defineComponent, ref, reactive, toRefs, watch, watchEffect, computed, onMounted } from "vue"
  2. export default defineComponent({ 
  3.  setup(props, context) { 
  4.     const selectRef = ref(null) // 作為下拉框的ref引用 
  5.     const state = reactive({ // 響應(yīng)式數(shù)據(jù),類似于Vue2的this 
  6.      num: 0, 
  7.     }); 
  8.     const { init } = toRefs(props); 
  9.     watch(() => state.num, (newVal, oldVal) => { 
  10.      console.log(newVal, oldVal); 
  11.     }); 
  12.     watchEffect(() => { 
  13.      console.log(state.num); 
  14.     }); 
  15.     const num2 = computed(() => state.num + 1); 
  16.     onMounted(() => { 
  17.      state.loaded = true
  18.     }); 
  19.     return { selectRef, state, num2, init, context }; 
  20.   } 
  21. }); 

setup 作為入口函數(shù),包含兩個參數(shù),分別是響應(yīng)式的 props 外部參數(shù),以及 context 對象,context 包含 attrs、emit、expose、props、slots 五個參數(shù),如下所示:

在 Vue3 的設(shè)計里,setup,以及從 vue 對象中解構(gòu)出來的各種生命周期函數(shù),執(zhí)行優(yōu)先級高于 Vue2 中的各種生命周期鉤子,因此

  1. beforeCreate() { 
  2.  console.log('beforeCreate'); 
  3. }, 
  4. created() { 
  5.  console.log('create'); 
  6. }, 
  7. setup() { 
  8.  console.log('setup'); 
  9. }, 

這段代碼的輸出依次是 setup、beforeCreate、created。

ref、reactive

setup 中,第一句const selectRef = ref(null);,這里定義的是一個響應(yīng)式的數(shù)據(jù),可傳遞給 template 或 render,用于下拉框組件或下拉框 dom 綁定引用。為什么使用 ref,不使用 reactive 呢?ref 和 reactive 都可以給數(shù)據(jù)添加響應(yīng)性,ref 一般用于給 js 基本數(shù)據(jù)類型添加響應(yīng)性(當然也支持非基本類型的 object),reactive 只能用于代理非基本數(shù)據(jù)類型。null 是基本數(shù)據(jù)類型,只能使用 ref,那既然如此,為什么不在所有情況都使用 ref 呢?我們來看一段代碼:

  1. const num = ref(0); 
  2. num.value = 1; 
  3. const obj = { a: 1 }; 
  4. const refObj = ref(obj); 
  5. const reactiveObj = reactive(obj); 
  6. refObj.value.a = 2; 
  7. reactiveObj.a = 3; 
  8. console.log(num, refObj, reactiveObj); 

我們注意到,使用 ref api 時,數(shù)據(jù)變成了對象,值就是 value 屬性的值,如果數(shù)據(jù)本身就是對象,依然會多一層 value 結(jié)構(gòu),而 reactive 沒有這些副作用。同時,還有一個有意思的現(xiàn)象是,所有的源數(shù)據(jù),都需要經(jīng)過響應(yīng)式 api 包裹,然后才能使用,這跟前面提到的 Proxy 原理有關(guān),Proxy 代理數(shù)據(jù)時,需要基于返回的代理進行數(shù)據(jù)更新。

toRefs

除了 ref、reactive 外,還有一個常用的響應(yīng)式 api——toRefs。為什么需要它,這是因為響應(yīng)式對象,經(jīng)過解構(gòu)出來的屬性不再具有響應(yīng)性,toRefs 就是為了快速獲得響應(yīng)性的屬性,因此這段代碼const { init } = toRefs(props);,就是為了獲得響應(yīng)式屬性 init,想要保留 props 參數(shù)的響應(yīng)性,建議這么做。

watch、watchEffect

  1. const num = ref(0); 
  2. const state = reactive({ 
  3.  num: 0, 
  4. }); 
  5. const obj = { num: 0 }; 
  6. watch(num, (newVal, oldVal) => { 
  7.  console.log("num", newVal, oldVal); 
  8. }); 
  9. watch(() => state.num, (newVal, oldVal) => { 
  10.  console.log("num", newVal, oldVal); 
  11. }); 
  12. watch(() => obj.num, () => { 
  13.   console.log("這里不會執(zhí)行"); 
  14. }); 
  15. num++; 
  16. state.num++; 
  17. obj.num++; 

如上,watch api,它需要接受一個具有返回值的 getter 函數(shù)或者 ref(如() => state.num,ref)。

如果需要監(jiān)聽多個值,如下所示:

  1. const num1 = ref(0); 
  2. const num2 = ref(0); 
  3. watch([num1, num2], ([newNum1, newNum2], [prevNum1, prevNum2]) => { 
  4.   console.log([newNum1, newNum2], [prevNum1, prevNum2]); 
  5. }); 
  6. num1.value = 1; // [1, 0], [0, 0] 
  7. num2.value = 2; // [1, 2], [1, 0] 

可見多個數(shù)據(jù)的每次更新都會觸發(fā) watch。想要監(jiān)聽一個嵌套的對象,跟 Vue2 一樣,依舊需要使用 deep 選項,如下所示:

  1. const state = reactive({ 
  2.   attr: { 
  3.     id: 1, 
  4.   }, 
  5. }); 
  6. watch(() => state, (currState, prevState) => { 
  7.   console.log(currState.attr.id, prevState.attr.id, currState === prevState, currState === state); // 2, 2, truetrue 
  8. }, { deep: true }); 
  9. watch(() => state.attr.id, (currId, prevId) => { 
  10.   console.log(currId, prevId); // 2, 1 
  11. }); 
  12. state.attr.id = 2; 

看到差別了嗎?監(jiān)聽響應(yīng)式對象時,返回的是對象的引用,因此 currState,prevState 指向是同一個最新的 state,如果需要獲取變化前的值,建議返回監(jiān)聽的屬性,如watch(() => state.attr.id),剛好 state.attr.id 是一個基本類型的值,那么 deep 也不需要。

watchEffect 是 Vue3 新增的 api,watchEffect 會自動運行一次,用于自動收集依賴,但不支持獲取變化前的值,除此之外,與 watch 用法一致。那么 watchEffect 適用什么場景呢?這也是我剛上手 Vue3 的困惑之一。我們來看一段代碼:

  1. const rights = { 
  2.   admin: ["read""write"], 
  3.   user: ["read"], 
  4. }; 
  5. const state = reactive({ 
  6.   rights: ""
  7. }) 
  8. const userInfo = reactive({ role: "user" }); 
  9. userInfo.name = "Tom"
  10. userInfo.role = "admin"
  11. watch(() => userInfo.role, (newVal, oldVal) => { 
  12.  state.rights = rights[newVal]; 
  13. }); 
  14. watchEffect(() => { 
  15.  state.rights = rights[userInfo.role]; 
  16. }); 

以上代碼中,watch 中的邏輯只能在 userInfo 變化后執(zhí)行,因此 state.rights 不會提供初始值,相反,watchEffect 中 state.rights 由于自動依賴收集,獲得了一次賦值的機會。

這樣做的好處是什么呢?在實際項目中,userInfo.role 可能是一個全局 store 中的數(shù)據(jù),用戶登錄進來后,就會通過接口獲取初始值,我們并不能確認,用戶進到其中一個頁面時,userInfo.role 的值是否已經(jīng)被接口更新,且 userInfo 變化前的值我們也不關(guān)心,watchEffect 就非常適合這種場景,它會自動進行一次初始化,并且在變化后,及時更新值。

watch 和 watchEffect 的監(jiān)聽會在組件銷毀時自動取消,除此之外,可以通過它們返回的函數(shù)手動取消監(jiān)聽,如下所示:

  1. const stopWatch = watch(selectRef, (newVal, oldVal){}); 
  2. const stopWatchEffect = watchEffect(selectRef, (newVal, oldVal){}); 
  3. setTimeout(stopWatch, 1000); 
  4. setTimeout(stopWatchEffect, 1000); 

watchEffect 更多的用法,請參考官方文檔。

computed

computed 的使用如下:

  1. const num = ref(1); 
  2. const num2 = computed(() => num * 2); 
  3. num2.value++; // error 

num2 是一個不可變的 ref 對象,不能直接對它的 value 屬性賦值。

computed 還可以接收一個帶有 get 和 set 函數(shù)的對象,來創(chuàng)建一個可讀寫的 ref 對象,如下所示:

  1. const num3 = computed({ 
  2.  get: () => num.value * 2, 
  3.  set: (val) => { 
  4.   num.value = val; 
  5.  }, 
  6. }); 
  7. num3.value = 100; 
  8. console.log(num.value, num3.value); // 100 200 

自定義 Hooks

Vue3 的 Composition 之所以這樣實現(xiàn),主要原因就是為了便于代碼拆分,降低耦合,我們不妨來實現(xiàn)一個自定義的 hooks。

  1. // page.vue 
  2. import useCount from "./useCount"
  3. export default { 
  4.   setup() { 
  5.     const { num, double, plus } = useCount(1); 
  6.     return { num, double, plus }; 
  7.   }, 
  8. }; 
  9. // useCount.js 
  10. import { ref, computed } from "vue"
  11. export default (value) => { 
  12.   const num = ref(value); 
  13.   const double = computed(() => num.value * 2); 
  14.   const plus = (val) => num.value + val; 
  15.   return { num, double, plus }; 
  16. }; 

useCount.js 就是一個自定義的 hooks,得益于 Vue3 的全局 API,我們可以輕松做到代碼拆分。Vue3 的 setup 聚合了所有的邏輯,容易產(chǎn)生面條代碼,合理使用自定義 hooks,可以有效的減少面條代碼,提升代碼可維護性。并且 Vue3 的 hooks 比 react 更加簡單高效,不會多次執(zhí)行,不受調(diào)用順序影響,不存在閉包陷阱等等,幾乎可以沒有任何心智負擔的使用。

新的生命周期鉤子

看到這里,相信你對 Vue3 的生命周期已經(jīng)有一些了解了,我們不妨來做個梳理。

Vue3 幾乎內(nèi)置了所有的 Vue2 生命周期鉤子,也就是說,剛開始升級項目至 Vue3 時,可以直接使用 Vue2 的鉤子,方便平滑升級,如上圖左下角所示,有兩個鉤子發(fā)生了替換,beforeDestory 被替換成了 beforeUnmount,destoryed 被替換成了 unmounted。完整的鉤子對比如下:

除了 setup 外,Vue3 的其他生命周期鉤子都添加了 on 前綴,更加規(guī)范統(tǒng)一。新的鉤子需要在 setup 中使用,如下所示:

  1. import { onMounted } from "vue"
  2. export default { 
  3.   setup() { 
  4.     onMounted(() => { 
  5.       console.log("onMounted"); 
  6.     }); 
  7.   }, 
  8. }; 

Tree-Shaking

Vue3 一共開放了 113 個 API,我們可以通過如下方式引用:

  1. import { ref, reactive, h, onMounted } from "vue"

通過 ES6 modules 的引入方式,能夠被 AST 靜態(tài)語法分析感知,從而可以只提取用到的代碼片段,最終達到 Tree-Shaking 的效果,這樣就使得 Vue3 最終打包出來的包更小,加載更快。據(jù)尤大去年 4 月在 B 站的直播:基本的 hello world 項目大小為 13.5kb,Composition API 僅有 11.75kb,包含所有的運行態(tài)僅 22.5kb。

Fragment

Vue3 中,F(xiàn)ragment 的引入,解決了組件需要被一個唯一根節(jié)點包裹的難題,帶來的是 dom 層級的減少,以及渲染性能的提升,某些時候,如下所示:

  1. <!-- child.vue --> 
  2. <template> 
  3.  <td>{{ title }}</td> 
  4.   <td>{{ subtitle }}</td><!-- Vue2中template出現(xiàn)了多個根節(jié)點,無法編譯通過 --> 
  5. </template> 
  6. <!-- parent.vue --> 
  7. <template> 
  8.   <table
  9.     <tr> 
  10.       <child /> 
  11.     </tr> 
  12.   </table
  13. </template> 

在 Vue2 中,這意味著我們沒辦法在 child.vue 的 template 中加入多個 td 節(jié)點,多個 td 可以被 tr 包裹,如果 child.vue 根節(jié)點替換為 tr,那么就會跟 parent.vue 的 tr 沖突。

同樣的代碼,在 Vue3 中就能正確編譯通過,這是因為 Vue3 中,組件的 template 被一層不可見的 Fragment 包裹,組件天生支持多個根節(jié)點的布局。

Teleport

Teleport 是 Vue3 新增的組件,即傳送門,Teleport 能夠在不改變組件內(nèi)部元素父子關(guān)系的情況下,將子元素”傳送“到其他節(jié)點下加載,如下所示:

  1. <template> 
  2.   <div class="container" style="width: 100px; height: 100px; overflow: hidden"
  3.     <div class="dialog" style="width: 500px; height: 400px;"
  4.       ... 
  5.     </div> 
  6.   </div> 
  7. </template> 

dialog 直接掛載在 container 下,超出部分將不可見。加一層 Teleport,我們可以輕松將 dialog 展示出來。

  1. <template> 
  2.   <div class="container" style="width: 100px; height: 100px; overflow: hidden"
  3.     <teleport to="body"
  4.       <div class="dialog" style="width: 500px; height: 400px;"
  5.         ... 
  6.       </div> 
  7.     </teleport> 
  8.   </div> 
  9. </template> 

dialog 依然處于 container 內(nèi)部,僅僅只是被掛載到 body 上,邏輯關(guān)系不變,展示也不會遮擋。

Suspense

Vue2 中,我們經(jīng)常寫這樣的 loading 效果,如下所示:

  1. <template> 
  2.   <div class="container"
  3.     <div v-if="init"
  4.       <list /> 
  5.     </div> 
  6.     <div v-else
  7.       loading~~ 
  8.     </div> 
  9.   </div> 
  10. </template> 

Vue3 中,我們可以通過 Suspense 的兩個插槽實現(xiàn)以上功能,如下所示:

  1. <template> 
  2.   <div class="container"
  3.     <Suspense> 
  4.       <template #default
  5.         <list /> 
  6.       </template> 
  7.       <template #fallback> 
  8.         loading~ 
  9.       </template> 
  10.     </Suspense> 
  11.   </div> 
  12. </template> 
  13. <script> 
  14.   import { defineAsyncComponent } "vue"
  15.   export default { 
  16.     components: { 
  17.       list: defineAsyncComponent(() => import("@/components/list.vue")), 
  18.     }, 
  19.   }; 
  20. </script> 

 

Vue3 知識圖譜

Vue3 還包括了一些其他常用更新,限于篇幅,這里先列出來,下篇再講。

實際上,Vue3 帶來的更新,遠不止這些,為此我梳理了一個 Vue3 的知識圖譜,盡可能囊括一些本文未提到的特性。

如上圖,Vue 不但重寫了 diff 算法,還在編譯階段做了很多優(yōu)化,編譯時優(yōu)化可以通過這個網(wǎng)站看出來:https://vue-next-template-explorer.netlify.app/。

Vue3 的開放生態(tài)

根據(jù) Monterail 2 月份發(fā)布的第三版 Vue 生態(tài)報告,Vue 的流行度逐年上升,很多非 web 的可視化領(lǐng)域也可以基于 Vue 開發(fā),特別是 Vue3 的渲染 API 的開放,使得基于 Vue 構(gòu)建 Canvas、WebGL、小程序等應(yīng)用更加方便,如下圖所示,60 行代碼實現(xiàn)一個簡單的 Canvas 柱狀圖:

  1. import { createRenderer, h } from "vue"
  2. const renderer = createRenderer({ 
  3.   createElement: (tag) => ({ tag }), 
  4.   patchProp: (el, key, prev, next) => { el[key] = next; }, 
  5.   insert: (child, parent) => { parent.nodeType === 1 && draw(child) }, 
  6. }); 
  7. let canvas 
  8. let ctx; 
  9. const draw = (el, noClear) => { 
  10.   if (!noClear) { 
  11.     ctx.clearRect(0, 0, canvas.width, canvas.height); 
  12.   } 
  13.   // 柱狀圖繪制邏輯 
  14.   if (el.tag == 'chart') { 
  15.     const { data } = el; 
  16.     const barWidth = canvas.width / 10; 
  17.     const gap = 20; 
  18.     const paddingLeft = (data.length * barWidth + (data.length - 1) * gap) / 2; 
  19.     const paddingBottom = 10; 
  20.     // x軸 
  21.     // 柱狀圖 
  22.     data.forEach(({ title, count, color }, index) => { 
  23.       const x = paddingLeft + index * (barWidth + gap); 
  24.       const y = canvas.height - paddingBottom - count
  25.       ctx.fillStyle = color; 
  26.       ctx.fillRect(x, y, barWidth, count); 
  27.     }); 
  28.   } 
  29.   // 遞歸繪制⼦節(jié)點 
  30.   el.childs && el.childs.forEach(child => draw(child, true)); 
  31. }; 
  32. const createCanvasApp = (App) => { 
  33.   const app = renderer.createApp(App); 
  34.   const { mount } = app; 
  35.   app.config.isCustomElement = (tag) => tag === 'chart'
  36.   app.mount = (selector) => { 
  37.     canvas = document.createElement('canvas'); 
  38.     ctx = canvas.getContext('2d'); 
  39.     document.querySelector(selector).appendChild(canvas); 
  40.     mount(canvas); 
  41.   }; 
  42.   return app; 
  43. }; 
  44. createCanvasApp({ 
  45.   setup() { 
  46.     const data = [ 
  47.       { title: '數(shù)據(jù)A'count: 200, color: 'brown' }, 
  48.       { title: '數(shù)據(jù)B'count: 300, color: 'skyblue' }, 
  49.       { title: '數(shù)據(jù)C'count: 50, color: 'gold' }, 
  50.     ]; 
  51.     return () => h("chart", { data }); 
  52.   }, 
  53. }).mount('#app'); 

運行結(jié)果如下圖所示:

  • Vue3 相關(guān)資料
  • Vue3 官方網(wǎng)站
  • Vite 官方網(wǎng)站
  • Vue.js 2021 最新報告
  • Vue Template Explorer
  • 第四屆 Vue Conf(預(yù)計 2021.5.22)
  • ThisDot 線上分享會 PPT(2020.4.16)
  • Vue Function-based API RFC(2020.1.22)
  • State of Vue(2019.6.8)
  • Vue3 最新進展(2018.11.24)
  • 現(xiàn)狀與展望(2017.5.20)

 

 

責任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2021-12-06 10:07:48

開源項目Vue3

2009-06-28 22:55:00

SAN惠普存儲

2024-01-03 18:01:48

Code技巧開發(fā)

2025-01-06 08:57:19

Vue技巧

2024-01-26 18:04:21

編輯器Code主題

2023-12-09 18:02:34

工具Code插件

2023-11-26 09:04:10

Vue性能

2021-12-01 08:11:44

Vue3 插件Vue應(yīng)用

2024-11-06 10:16:22

2024-03-08 08:40:25

2021-11-30 08:19:43

Vue3 插件Vue應(yīng)用

2023-11-28 09:03:59

Vue.jsJavaScript

2025-04-28 10:16:35

VSCode插件開發(fā)

2022-11-30 12:41:03

戴爾

2022-03-21 15:24:27

ThingWorxDPMPTC

2009-07-03 12:59:40

Servlet配置

2022-09-06 12:20:30

Vue3CVCRUD

2017-03-21 09:11:21

Android開發(fā)效率TemplateBui

2020-09-19 21:15:26

Composition

2025-02-17 08:58:06

點贊
收藏

51CTO技術(shù)棧公眾號