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