Vue3.2.x中的小技巧及注意事項(xiàng)總結(jié)
前言
vue3在2022年的2月7號(hào)成為了vue默認(rèn)版本,并且隨之而來的還有vue3的新文檔, 并且從實(shí)際使用的角度來說, vue3確實(shí)比vue2使用起來更加的舒服,所以覺得經(jīng)過一段時(shí)間的使用,來分享一下使用過程中的小技巧以及注意事項(xiàng)。
小技巧
關(guān)于減少.value的使用
使用watch來監(jiān)聽Ref數(shù)據(jù)的時(shí)候, 可以做到省略.value的使用, 例如:
const value = ref(1); // 省略() => value.value watch(value, (v) => { // 省略v.value console.log(v); }, { immediate: true }); setTimeout(() => { value.value = 2; }, 1000);
使用vue3.2.25以上版本提供的$ref, 還是跟上面的代碼實(shí)現(xiàn)一樣的功能
該功能是一個(gè)實(shí)驗(yàn)性能, 需要相應(yīng)的配置, 這里以vite為例, 需要在vite.config.ts的vue plugin中添加一個(gè)reactivityTransform屬性, 請(qǐng)看下面的配置。如果用的是其他工程化工具, 可以參考vue的新文檔, 文檔中有詳細(xì)的說明。
plugins: [ vue({ reactivityTransform: true, }) ]
const count = $ref(1); // 增加了() => count watch( () => count, (v) => { console.log(v); }, { immediate: true } ); setTimeout(() => { // 省略了count.value count++; }, 1000);
輸出:
這里需要說明一下使用$ref需要注意的問題, 首先該功能是一個(gè)實(shí)驗(yàn)性性能, 需要相應(yīng)的配置, 并且vue的文檔中指出該方法是一個(gè)編譯器宏使用時(shí)無需引入, 但為了ts和編輯器的無端報(bào)錯(cuò), 個(gè)人還是喜歡顯示的引入, 就像這樣
import { $ref } from 'vue/macros'
接著再說一下$ref的另一個(gè)很嚴(yán)重的問題, 就是丟失響應(yīng)式, 為什么會(huì)丟失響應(yīng)式呢? 其實(shí)這部分官方文檔已經(jīng)做出了說明, 請(qǐng)看下面的代碼
// App.vue import { $ref } from "vue/macros"; import { useApp } from "./App"; let count = $ref(1); useApp(count); setTimeout(() => { console.log("change"); count++; }, 1500); // App.ts import { watch } from "vue"; export const useApp = (count) => { watch( () => count, (c) => { console.log("watch", c); }, { immediate: true } ); };
上面代碼中App.ts里面的watch只會(huì)執(zhí)行一次, 很明顯, count丟失了響應(yīng)性
如何解決這個(gè)問題呢?請(qǐng)看下面的代碼:
// App.vue import { $ref, $$ } from "vue/macros"; // 引入$$ import { useApp } from "./App"; let count = $ref(1); useApp($$(count)); // useApp(count) --> useApp($$(count)) setTimeout(() => { console.log("change"); count++; }, 1500); // App.ts import { watch } from "vue"; export const useApp = (count) => { watch( count, // () => count --> count (c) => { console.log("watch", c); }, { immediate: true } ); };
可以看到, 我們?cè)趥鬟f$ref值的時(shí)候 需要用一個(gè)$$方法包裹一下, 這樣就不會(huì)丟失響應(yīng)性了, 具體更詳細(xì)的使用方法, 還是希望大家仔細(xì)閱讀一下vue的新文檔
關(guān)于減少import導(dǎo)入語句
發(fā)現(xiàn)這個(gè)功能是無意間的,在使用element-plus的時(shí)候, 查看elment-plus官網(wǎng) 指南 快速開始, 其中提到了自動(dòng)導(dǎo)入的功能, 文檔中說的是 首先下載對(duì)應(yīng)的插件
npm install -D unplugin-vue-components unplugin-auto-import
, 然后如果使用的是vite的話, 需要在vite.config中添加幾條配置, 就像下面一樣:
// vite.config.ts import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default { plugins: [ // ... AutoImport({ resolvers: [ElementPlusResolver()], }), Components({ resolvers: [ElementPlusResolver()], }), ], }
因?yàn)楹闷嫒タ戳诉@兩個(gè)包的介紹, 發(fā)現(xiàn)不光可以自動(dòng)導(dǎo)入組件, 還可以自動(dòng)導(dǎo)入方法, 例如心細(xì)的小伙伴已經(jīng)發(fā)現(xiàn), .value那部分的代碼 不管是ref還是$ref我都沒有寫import語句來導(dǎo)入, 這里就用到了這兩個(gè)插件, 我們來看一下如果要自動(dòng)導(dǎo)入vue的方法對(duì)應(yīng)的配置。
// vite.config.ts import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default { plugins: [ // ... AutoImport({ imports: ["vue", "vue/macros"], // 增加這一行代碼 resolvers: [ElementPlusResolver()], }), Components({ resolvers: [ElementPlusResolver()], }), ], }
在這樣的配置下就可以愉快的減少import導(dǎo)入了。
關(guān)于在script setup中聲明組件名字
在script setup的方式剛發(fā)布的時(shí)候, 我就一直在糾結(jié)這個(gè)問題, 因?yàn)轫?xiàng)目中有很多的遞歸組件, 如果沒有name來做標(biāo)識(shí)的話, 勢(shì)必會(huì)產(chǎn)生問題
- 剛開始vue的issues中其他用戶提出的解決方式是在.vue文件中定義兩個(gè)script標(biāo)簽, 其中一個(gè)用來定義組件的name, 而另一個(gè)用來編寫組件邏輯, 例如下面這樣:
這種方式相信對(duì)于一些有強(qiáng)迫癥或者完美主義者來說是完全不能接受的, 包括我 也不能接受, 所以在vue的issues中就有一個(gè)用戶開發(fā)了一個(gè)插件來解決這個(gè)問題。
- unplugin-vue-define-options插件
下載插件
npm i unplugin-vue-define-options -D
我們直接來看一下這個(gè)插件的使用方式:
在vite中使用
// vite.config.ts import DefineOptions from 'unplugin-vue-define-options/vite' import Vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [Vue(), DefineOptions()], })
ts項(xiàng)目需要在tsconfig.json中添加一個(gè)配置
{ "compilerOptions": { "types": ["unplugin-vue-define-options"] } }
使用方式
<script setup lang="ts"> defineOptions({ name: 'App' }) </script>
該插件的功能遠(yuǎn)遠(yuǎn)不止定義組件的name, 還可以定義組件的props、emits、render等,有興趣的小伙伴可以去看一下,感覺可以利用這一特性才做一些騷操作,不過尤大大覺得這種方式不太好。
注意事項(xiàng)
關(guān)于響應(yīng)式的問題
- props不能使用解構(gòu)的方式來使用, 例如下面的例子
// Parent.vue <template> <ChildVue ref="childRef" v-bind="data" /> </template> <script setup lang="ts"> import { reactive } from 'vue'; import ChildVue from "./views/Child.vue"; const data = reactive({ name: 'veloma' }); setTimeout(() => { data.name = 'timer'; }, 1500); </script> // Child.vue <template> <div>{{ data.name }}</div> </template> <script lang="ts" setup> const props = defineProps<{ name: string; }>(); const data = reactive({ ...props }); </script>
上面的例子在子組件中, 通過reactive將props進(jìn)行了解構(gòu), Parent組件中1.5s后更新name, 這時(shí)我們會(huì)發(fā)現(xiàn)Child組件中的模板并不會(huì)產(chǎn)生更新, 那如何來解決這個(gè)問題呢?
首先有兩種解決方式:1.使用3.2.25或以上的版本直接解構(gòu)defineProps, 例如這樣
const { name } = defineProps<{ name: string }>()
2.或者通過computed來解構(gòu), 例如
const data = computed(() => ({ ...props }))
模板循環(huán)中加不加key的問題
關(guān)于這個(gè)問題, 在vue新文檔中有提到這樣一句話
只看這句話的話是沒有任何問題的,但在實(shí)際的使用過程中, 舉個(gè)??:
// Parent.vue <template> <div> <ChildVue v-for="item of list" v-bind="item"></ChildVue> <button @click="onClick">按鈕</button> </div> </template> <script setup lang="ts"> import { ref } from "vue"; import ChildVue from "./views/Child.vue"; const list = ref([{ name: "veloma" }, { name: "timer" }, { name: "lucy" }]); const onClick = () => { console.log('點(diǎn)擊'); const item = { ...list.value[0] }; item.name = "veloma1111"; list.value[0] = item; }; </script> // Child.vue <template> <div>{{ name }}</div> </template> <script lang="ts" setup> import { onMounted } from "vue"; defineProps<{ name: string; }>(); onMounted(() => { console.log("mounted"); }); </script>
我們看上面的代碼會(huì)發(fā)現(xiàn)功能非常的簡(jiǎn)單, 子組件接收一個(gè)name屬性, 父組件循環(huán)渲染子組件, 且子組件中有一個(gè)onMounted鉤子, 我們希望的是, 當(dāng)點(diǎn)擊按鈕的時(shí)候觸發(fā)子組件的onMounted鉤子, 乍一看是沒有任何問題的, 但實(shí)際是不會(huì)觸發(fā)的, 看結(jié)果:
我們發(fā)現(xiàn)click事件確實(shí)觸發(fā)了, 而數(shù)據(jù)也確實(shí)變化了, 頁(yè)面也變化了, 但就是沒有觸發(fā)子組件的onMounted鉤子, 那這是怎么回事呢?實(shí)際上在vue處理這一步的時(shí)候 重用了之前name為veloma的Child組件, 重用不會(huì)產(chǎn)生掛載, 也就不會(huì)觸發(fā)onMounted鉤子, 那要怎么解決呢?其實(shí)很簡(jiǎn)單, 只需要給Child組件一個(gè)key即可.
總結(jié)
到目前為止其實(shí)還有好多公司沒有升級(jí)到vue3, 但是我相信 在不久的將來 甚至就是今年, vue3 + vite + typescript 一定會(huì)覆蓋大部分的公司, 所以建議小伙伴們還是需要仔細(xì)認(rèn)真的多看兩遍vue的新文檔, 系統(tǒng)的了解一下vue3的變化為以后的升級(jí)做好準(zhǔn)備, 加油!
到此這篇關(guān)于Vue3.2.x中的小技巧及注意事項(xiàng)的文章就介紹到這了,更多相關(guān)Vue3.2.x小技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3中?provide?和?inject?用法小結(jié)
父子組件傳遞數(shù)據(jù)時(shí),使用的是props和emit,父?jìng)髯訒r(shí),使用的是?props,如果是父組件傳孫組件時(shí),就需要先傳給子組件,子組件再傳給孫組件,如果多個(gè)子組件或多個(gè)孫組件使用時(shí),就需要傳很多次,會(huì)很麻煩,這篇文章主要介紹了vue3中?provide?和?inject?用法,需要的朋友可以參考下2023-11-11Vue 使用 Mint UI 實(shí)現(xiàn)左滑刪除效果CellSwipe
這篇文章主要介紹了Vue 使用 Mint UI 實(shí)現(xiàn)左滑刪除效果CellSwipe,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04vue 動(dòng)態(tài)改變靜態(tài)圖片以及請(qǐng)求網(wǎng)絡(luò)圖片的實(shí)現(xiàn)方法
下面小編就為大家分享一篇vue 動(dòng)態(tài)改變靜態(tài)圖片以及請(qǐng)求網(wǎng)絡(luò)圖片的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-02-02vue之el-menu-item如何更改導(dǎo)航菜單欄選中的背景顏色
這篇文章主要介紹了vue之el-menu-item如何更改導(dǎo)航菜單欄選中的背景顏色問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05vue報(bào)錯(cuò)之exports is not defined問題的解決
這篇文章主要介紹了vue報(bào)錯(cuò)之exports is not defined問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Vue 實(shí)時(shí)監(jiān)聽窗口變化 windowresize的兩種方法
這篇文章主要介紹了Vue 實(shí)時(shí)監(jiān)聽窗口變化 windowresize的兩種方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11詳解mpvue中小程序自定義導(dǎo)航組件開發(fā)指南
這篇筆記主要記錄一下基于mpvue的小程序中實(shí)現(xiàn)自定義導(dǎo)航的思路及應(yīng)用。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02