<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>

          尤大都說Vue3 + script setup + TS + Volar真香,你說香不香?

          共 11782字,需瀏覽 24分鐘

           ·

          2021-08-20 16:46

          前兩天尤大官宣發(fā)布了Vue3.2,支持了好幾個很不錯的新特性,而且自信放話:<script setup> + TS + Volar = 真香,是時候了

          想看Vue3.2更新的內(nèi)容文檔的讀者可以滑到文章底部點擊「閱讀原文」


          相信你已經(jīng)開始使用或者迫不及待地想嘗試Vue3.2了,其實我群里的小伙伴早已經(jīng)開始使用,而且踩了很多坑了,今天給大家分享一下他的實踐投稿文章,希望大家多多支持!

          正文如下

          目前setup sugar已經(jīng)進行了定稿,而vue3 + setup sugar + TS的寫法看起來很香,所以我大膽嘗試了下,期間發(fā)現(xiàn)一些小問題,分享下我的經(jīng)驗,如有問題,歡迎斧正。

          作者:qiuliang

          鏈接:https://juejin.cn/post/6990682369992704007

          前期準備

          1. 使用vue-cli創(chuàng)建一個 vue3 + TS 的項目

            相關(guān)可去 cli.vuejs.org/zh/guide/[1] 查看

          2. vscode禁用 Vetur,下載Volar

          相關(guān)下載以及說明可去 marketplace.visualstudio.com/items?itemN…[2] 查看

          注意:vue3 不支持 ie 全系(包括 ie11),因為 ie 并不支持 proxy api。若你想使用 vue3 相關(guān)語法,請等待 vue2.7。預(yù)期將在 2021 q3 或者 q4 發(fā)布 vue2.7,詳情見:github.com/vuejs/rfcs/…[3]

          什么是 setup sugar

          在單文件組件(SFC)中引入一個新的 <script> 類型 setup。它向模板公開了所有的頂層綁定。

          未使用setup sugar

          <template>
            <Foo :count="count" @click="inc" />
          </template>
          <script>
          import Foo from './Foo.vue'
          import { ref } from 'vue'

          export default {
            setup() {
              const count = ref(1)
              const inc = () => { count.value++ }

              return {
                Foo,
                count,
                inc
              }
            }
          }
          </script>

          使用了setup sugar

          <template>
            <Foo :count="count" @click="inc" />
          </template>
          <script setup>
          /
          / 導(dǎo)入的組件也可直接可用于模板(指令同理,同樣會被自動注冊)
          import Foo from './
          Foo.vue'
          import { ref } from '
          vue'

          // 書寫組合式 api 就像在正常的 setup 中一般,但是不需要進行手動地進行 return
          const count = ref(0)
          const inc = () => { count.value++ }
          </script>

          你可以在 github.com/vuejs/rfcs/…[4] 以及github.com/vuejs/rfcs/…[5] 看到有關(guān) setup sugarref sugar有關(guān)更多的討論。個人不喜歡ref sugar,個人認為.value的寫法比較好理解,結(jié)合Volar的幫助提示,已經(jīng)沒有多少的心智負擔。

          vue3 組合式寫法是否會產(chǎn)生更多問題

          目前網(wǎng)絡(luò)上很多人反應(yīng)使用組合式 api 反而顯得代碼更加亂了。那么從vue2options apivue3composition api寫法,究竟會獲得什么好處呢?

          1. 邏輯耦合度更高:在options api中如何一個功能我們需要用到 data+method+watch...等更多 api,一段代碼無法合并在一起,我們在閱讀一段邏輯需要進行反復(fù)上下移動進行觀看。而composition api就解決了這個問題。
          2. 功能抽離:得益于函數(shù)式編程,一個功能邏輯我們可以封裝到一個 hook 中,我們直接導(dǎo)入hook,運行方法,即可。

          缺點:從options api切換到composition api最大的問題無異于最大的問題就是沒有強制的代碼分區(qū),如果書寫的人沒有很好的代碼習(xí)慣,那么后續(xù)的人將會看的十分難受。目前我是這么解決的:

          • 自我代碼分區(qū)并且盡量抽離方法(寫好注釋),分區(qū)如下:
            1. 相關(guān)引入
            2. 響應(yīng)式數(shù)據(jù)、props、emit 定義
            3. 生命周期以及 watch 書寫
            4. 方法定義
            5. 方法、屬性暴露
          • 組件抽離:將頁面拆成兩個文件夾,一個為 views,一個為 components。views 和 components 文件夾下有各自的文件。views 文件夾中為頁面入口,掌管數(shù)據(jù),而 components 則為頁面中一些組件抽離。如果是公共組件,再抽離到 components 文件夾下其他位置。
          • hook 抽離:盡可能將邏輯抽離,并不一定要進行復(fù)用。

          setup 衍生出的新的 api

          define 編譯器宏(compiler macros )

          define開頭的 api 都為編譯器宏(compiler macros )api,只能在 <script setup> 中使用。它們不需要被導(dǎo)入,并且在處理 <script setup> 時被編譯掉。

          注意:define類 api 必須直接在 setup 中外層進行使用,你無法將其放在方法中。

          注意:define類 api 雖然不用導(dǎo)入,但是這一點和 TS 兼容不太好,如果不引入會提示 undefined,如果進行了引入,會有 warning 提示。

          注意:define類 api雖然目前都可以使用 TS 類型聲明,但是你無法導(dǎo)入一個 interface 或者 type 進行類型聲明(直接在文件中聲明是可以的),因為這樣會報錯。猜測這一點是和 define編譯器宏有關(guān),可能后期會被修復(fù)。

          1. defineProps:這個 api 很好理解,就是定義 props 相關(guān)信息。

            基礎(chǔ)用法:

          defineProps({
            name: {
              typeString,
              requiredfalse,
              default'Petter',
            },
            userInfoObject,
            tagsArray,
          }) 

          使用 TS 類型聲明:

          const props = defineProps<{ 
              foo: string 
              bar?: number
          }>()

          注:兩個寫法不可以一起進行使用,也就是一個 defineProps 不能既使用 TS 類型聲明,也使用基礎(chǔ)用法。

          1. withDefaults:這個方法并非屬于編譯器宏(compiler macros )api,但是這個 api 由defineProps衍生而出。在 TS 類型聲明下無法進行設(shè)置默認值,這個 api 主要是為了解決這個場景。
          withDefaults(defineProps<{
           size?: number
           labels?: string[]
          }>(), {
           size: 3,
           labels: () => ['default label']
          })
          1. defineEmits:這個 api 也很好理解,就是定義 emits 相關(guān)信息。不過使用和以前有點不一樣。

            基礎(chǔ)使用:

          // 聲明
          const emits = defineEmits(['change''delete'])
          // 使用
          emits('change')

          TS聲明類型:

          // 聲明
          const emit = defineEmits<{ (e: 'change', id: number): void (e: 'update', value: string): void }>()
          // 使用
          emits('change',1)
          1. defineExpose:在傳統(tǒng)的 Vue 組件中,所有暴露在模板上的東西都隱含地暴露在組件實例上,也就是父組件可以通過ref 或者子鏈可以全量獲取到子組件所有的屬性、方法。大多數(shù)時候,這種全量暴露是過度的,而 vue3 setup 中必須進行手動暴露。
          const a = 1
          const b = ref(2)
          defineExpose({ a, b, })

          注意:目前發(fā)現(xiàn)defineExpose暴露出去的屬性以及方法都是 unknown 類型,如果有修正類型的方法,歡迎評論區(qū)補充。

          hook api

          注:useContext API 被棄用,取而代之的是更加細分的 api。

          1. useAttrs:見名知意,這是用來獲取 attrs 數(shù)據(jù),但是這和 vue2 不同,里面包含了 class屬性、方法。

            在 vue2 中封裝組件透傳屬性、方法你可能這么寫:

          <component v-bind='$attrs',v-on='$listeners'></component>

          vue3 里刪除了 $listeners,新寫法:

          <template>
           <component v-bind='attrs'></component>
          </template>
          <srcipt setup lang='ts'>
             const attrs = useAttrs();
          <script>
          1. useCSSModule:CSS Modules 是一種 CSS 的模塊化和組合系統(tǒng)。vue-loader 集成 CSS Modules,可以作為模擬 scoped CSS。允許在單個文件組件的setup中訪問CSS模塊。此 api 本人用的比較少,不過多做介紹。

          2. useSlots: 顧名思義,獲取插槽數(shù)據(jù)。

          3. useCssVars: 此 api 暫時資料比較少。介紹v-bind in styles時提到過。

          詳情請見:github.com/vuejs/rfcs/…[6]

          1. useTransitionState: 此 api 暫時資料比較少。

          2. useSSRContext: 此 api 暫時資料比較少。

          setup 目前存在的限制

          修改選項配置需要單開一個 script

          配置項的缺失,有時候我們需要更改組件選項,在setup中我們目前是無法做到的。我們需要在上方再引入一個 script,在上方寫入對應(yīng)的 export即可。

          <script>
             export default {
                 name: 'YourName',
                 inheritAttrs: false,
                 customOptions: {},
             } 
          </script>
          <script setup>
            /
          / your code
          </
          script>

          注意:Vue 3 SFC 一般會自動從組件的文件名推斷出組件的 name。在大多數(shù)情況下,不需要明確的 name 聲明。唯一需要的情況是當你需要 <keep-alive> 包含或排除或直接檢查組件的選項時,你需要這個名字。

          與 TS 與 ESLint 不是完美融合

          1. @typescript-eslint/no-unused-vars規(guī)則不兼容,此規(guī)則含義為定義了,未進行使用。該規(guī)則其實影響不大,關(guān)閉即可。

          2. 與導(dǎo)入的類型聲明不兼容,當你通過解構(gòu)的方式去導(dǎo)入類型,setup sugar 會進行自動導(dǎo)出。這時候,你就會收到 TS 的一條報錯:此為類型,但被當作值使用。解決辦法:類型導(dǎo)出使用export default導(dǎo)出或者引入時使用import * as xx來進行引入。

            感謝評論區(qū)補充:import type { test } from "./test";如此書寫,也是可以解決的。

            關(guān)于這一點,也許你會想著在上方寫一個 script 進行導(dǎo)入,但是這是不行的。在上方 script 導(dǎo)入的東西,也會被自動導(dǎo)出。詳情見:github.com/vuejs/vue-n…[7]

          必須安裝新的插件

          集成開發(fā)環(huán)境需要為這個新的 <script setup> 模型提供專門的處理,以便提供模板表達式類型檢查 / 道具驗證等。安裝Volar也是為了這個目的。

          vue3 中如何實現(xiàn)國際化

          1. 下載最新的vue-i18n,當前版本"vue-i18n": "^9.1.7"。

          2. src 下創(chuàng)建文件夾locales,創(chuàng)建好對應(yīng)語言文案(這里最好使用 json)。

          import en from "./en.json";
          import zhHans from "./zh-cn.json";
          import zhHant from "./zh-hk.json";
          import { createI18n } from "vue-i18n";
          import { judgeLang } from "@/utils/url";

          const messages = {
             en: en,
             "zh-hans": zhHans,
             "zh-hant": zhHant,
          };

          const i18n = createI18n({
             locale: judgeLang(),
             messages,
          });

          export default i18n;
          1. main.ts中引入i18n
          import { createApp } from "vue";
          import App from "./App.vue";
          import router from "./router";
          import store from "./store";
          import i18n from "@/locales/index";

          createApp(App).use(store).use(router).use(i18n).mount("#app");
          1. 創(chuàng)建一個i18n hook
          import { provide, inject } from "vue";
          import { useI18n } from "vue-i18n";

          export function useProvideI18n(): void {
             const { t } = useI18n();
             // 注入翻譯函數(shù)
             provide("t", t);
          }

          export function useInjectI18n(): (text: string) => string {
            const t = inject("t"as (text: string) => string;
            return t;
          }
          1. app.vue,進行注入。隨后,便可在各處進行接收使用。

          2. 下載 i18n Ally,可查看實時翻譯(強烈推薦)。

          vue-i18n 詳情請見:kazupon.github.io/vue-i18n/zh…[8] i18n Ally 插件詳情請見:github.com/lokalise/i1…[9]

          vue3.2新增有意思的東西

          v-memo(Vue3.2 新增)

          記錄指令下的模板樹。該指令期望一個數(shù)組,如果數(shù)組內(nèi)的值,都沒有發(fā)生更新,那么指令下的模板樹也不會發(fā)生更新。

          <div v-memo="[valueA, valueB]">
            ...
          </div>

          當組件重新渲染時,如果valueAvalueB保持不變,<div>則將跳過此組件及其子組件的所有更新。實際上,即使是 Virtual DOM VNode 創(chuàng)建也將被跳過,因為可以重復(fù)使用子樹的記憶副本。

          官網(wǎng)提到v-memo僅用于性能關(guān)鍵場景中的微優(yōu)化,一般使用到的地方應(yīng)該是渲染大型v-for列表(其中length > 1000)。

          <div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
            <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
            <p>...more child nodes</p>
          </div>

          v-bindin<style>(實驗性語法)

          支持在單文件組件樣式中使用組件狀態(tài)驅(qū)動的CSS變量。其實,關(guān)于這個提案已經(jīng)持續(xù)很久了(換了寫法而已),本質(zhì)上是利用CSS var() 函數(shù)。

          <template>
            <div class="text">hello</div>
          </template>

          <script>
            export default {
              data() {
                return {
                  color'red',
                  font: {
                    size'2em',
                  },
                }
              },
            }
          </script>

          <style>
            .text {
              colorv-bind(color);

              /* 表達式需用引號括起來 */
              font-sizev-bind('font.size');
            }
          </style>

          你可以在這里看見更多有關(guān)信息 github.com/vuejs/rfcs/…[10]

          你可能會遇到的問題

          移動端調(diào)試工具 vConsole 發(fā)生棧溢出

          一般移動端調(diào)試都是使用vConsole輕量好用,但是目前對 Vue3 兼容性不好,使用到一定時間,會出現(xiàn)棧溢出。這里推薦另外一個調(diào)試工具erudaeruda目前使用起來并沒有大的問題,但是這個插件特別大,500 多 kb 是對于移動端是無法忍受的,即便壓縮后也有 100 多 kb。這里我們只要根據(jù)環(huán)境判斷,利用 script 動態(tài)插入就好了。

          export default function debugInit(): void {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "http://cdn.bootcdn.net/ajax/libs/eruda/2.3.3/eruda.js";
            document.getElementsByTagName("head")[0].appendChild(script);
            script.onload = function ({
              window.eruda.init();
            };
          }
          image.png

          慎用無根標簽的組件

          目前 vue3 中我們已經(jīng)不需要強制組件有一個根標簽了,但是有些情況下,表現(xiàn)并不太好。

          例如:transition組件目前和此種寫法偶發(fā)出現(xiàn)問題。

          你在Vue3的使用中,有遇到什么坑或者經(jīng)驗之談嗎?可以在評論區(qū)留下你寶貴的建議哦~

          參考資料

          [1]

          cli.vuejs.org/zh/guide/: https://link.juejin.cn?target=https%3A%2F%2Fcli.vuejs.org%2Fzh%2Fguide%2F

          [2]

          marketplace.visualstudio.com/items?itemN…: https://link.juejin.cn?target=https%3A%2F%2Fmarketplace.visualstudio.com%2Fitems%3FitemName%3Djohnsoncodehk.volar

          [3]

          github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fdiscussions%2F296

          [4]

          github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fpull%2F222

          [5]

          github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fpull%2F227

          [6]

          github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fblob%2Fmaster%2Factive-rfcs%2F0043-sfc-style-variables.md

          [7]

          github.com/vuejs/vue-n…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Fvue-next%2Fissues%2F3238

          [8]

          kazupon.github.io/vue-i18n/zh…: https://link.juejin.cn?target=https%3A%2F%2Fkazupon.github.io%2Fvue-i18n%2Fzh%2Fintroduction.html

          [9]

          github.com/lokalise/i1…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flokalise%2Fi18n-ally%2Fblob%2Fmaster%2FREADME.md

          [10]

          github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fblob%2Fmaster%2Factive-rfcs%2F0043-sfc-style-variables.md


          瀏覽 115
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  国产做爰 高潮 | 中国第一美女毛片 | 久操青青草| 91蜜桃在线观看 | 国产传媒一区二区三区 |