vue的幾個提效技巧

語言: CN / TW / HK

1.動態元件 <component :is='元件名'></component>

結合v-for迴圈使用

  • 使用環境

如圖,這是一個v-for渲染的列表(只是目前這個版塊才剛開始做,目前只有一個),圓圈內的就是一個元件,也就是要v-for動態元件 在這裡插入圖片描述

  • 實際使用

一開始就是基本的元件引入了

```javascript import ColorIn from '@/components/Magic/ColorIn.vue' import LineIn from "@/components/Magic/LineIn.vue"; import LineIn from "@/components/Magic/Header.vue"; import LineIn from "@/components/Magic/Footer.vue";

export default{ components:{ ColorIn, LineIn, Header, Footer } } ```

接下來就是動態v-for動態元件的使用,componentList:['ColorIn','LineIn','Header','Footer']使用下面的程式碼即可將程式碼依次迴圈

html <component v-for="(item,index) in componentList" :key="index" :is="item"></component>

編譯以後的效果就是

```html

```

2.watch進階使用

立即執行

  • 使用環境

例如場景為頁面一進來就呼叫拉取列表資料getList(),然後監聽路由的$route.query.id然後觸發列表資料的更新

  • 實際使用

為了讓它一開始就執行,我們需要在created()生命週期中執行一次拉取資料的方法

javascript watch:{ '$route.query.id':{ handle(){ this.getList(); }, } }, created(){ this.getList(); },

但是使用immediate即可立即執行,改寫以後的程式碼如下

javascript watch:{ '$route.query.id':{ handle(){ this.getList(); }, immediate:true } },

深度監聽

  • 使用環境

在監聽物件的時候,物件的內部屬性發生變化watch無法監聽到,這種時候就需要使用深度監聽

  • 實際使用

只需要設定deep:true即可開啟深度監聽

javascript data(){ return{ queryList:{ count:0, name:'', } } }, watch:{ queryList:{ handle(newValue,oldValue){ //do something }, deep:true } },

計算屬性之setter

  • 實際使用 我們一般平常使用的都是getter,但其實它還有個setter,當計算屬性的fullName觸發更新的時候,就會觸發setter回撥

javascript data(){ return{ firstName:'', lastName:'', } }, computed:{ fullName:{ get(){ return `${this.firstName} ${this.lastName}`; }, set(newValue){ let names=newValue.split(' '); this.firstName=names[0]; this.lastName=names[1]; } } },

$on('hook:生命週期')來簡化window監聽

  • 實際使用

先來看一下平常的使用方法,

javascript mounted () { window.addEventListener('resize', this.resizeHandler); }, beforeDestroy () { window.removeEventListener('resize', this.resizeHandler); }

改寫以後的程式碼為,相比於上面的寫法,這個寫法的好處在於可以開啟一個事件監聽器的同時,就在beforeDestroy生命週期中掛載一個刪除事件監聽器的事件。比上面的寫法會更加安全,更加有助於避免記憶體洩露並防止事件衝突

javascript mounted () { window.addEventListener('resize', this.resizeHandler); this.$on("hook:beforeDestroy", () => { window.removeEventListener('resize', this.resizeHandler); }) }

子元件@hook:生命週期監聽子元件的生命週期回撥

  • 實際使用

html <child @hook:mounted="listenChildMounted" />

v-pre

  • 使用環境

不需要編譯的html程式碼可以使用v-pre,可以提高效能

  • 實際使用

html <span v-pre>{{message}}</span> //就算data裡面定義了message,渲染完也是{{message}}

v-once

  • 使用環境

只需要渲染一次,適用於渲染完以後就不會更新的內容,降低效能開銷

  • 實際使用

html <span v-once>{{message}}</span> //message的值會編譯後渲染,但是編譯以後再次修改message的值不會觸發更新

  • v-pre與v-once的區別

v-pre相當於不編譯,直接顯示,v-once相當於只編譯一次,後面的更新不編譯了

Vue.set()

  • 使用環境

① 當你利用索引直接設定一個數組項時

② 當你修改陣列的長度時

③ 物件屬性的新增或刪除時

由於Object.defineprototype()方法限制,資料不響應式更新

  • 實際使用

參考 前端進階面試題詳細解答

javascript this.$set(arr,index,item);

$forceUpdate()

  • 使用環境

$set() 也有一定的使用限制,當物件沒有這個屬性的時候,$set() 就會報錯,這種時候,直接修改資料,再使用 $forceUpdate() 強制檢視重新整理即可

  • 實際使用

javascript this.$forceUpdate();

keep-alive

  • 使用環境

當這個頁面沒有資料更新,或者是想儲存狀態,下次進來還是這樣子的時候,例如淘寶檢視列表頁,點進去檢視詳情之後,返回列表頁依舊到上次瀏覽到的地方,都可以使用keep-alive

  • 實際使用 分為配合路由使用,使用max,include,exclude,以及特殊的生命週期activateddeactivated

$route路由資訊

  • $route.query.id

用來拿取路由傳值的資訊,比如路由的字尾?id=1,$route.query.id拿到的值為1

  • $route.meta.flag

用來拿取路由meta中的資訊,路由資訊裡的meta是可以自定義屬性的,我一般導航欄當前選中的nav用來和$route.meta.flag進行匹配,來拿到當前頁面應該啟用哪一個選項卡

  • base路由

比方說百度的所有路由字首要加/baidu,那麼可以設定路由的base為/baidu

javascript export const router = new Router({ base:'/baidu/', }

此外,打包的時候,請修改config/index.jsbuild塊中的assetsPublicPath為 '/baidu/',不然打包以後是找不到資原始檔路徑的

javascript module.exports = { build:{ assetsPublicPath: '/baidu/', } }

  • 全域性路由鉤子

使用場景一般為使用者的登入鑑權

javascript router.beforeEach((to, from, next) => { //一定要呼叫next()才能到下一個頁面 if (path === '/login') { next() }else{ if(token){ next(); }else{ next('/login'); } } })

  • 元件路由鉤子中訪問this

元件路由的鉤子一開始還未初始化,不能訪問到vue例項 beforeRouteEnter (to, from, next) { // 這裡還無法訪問到元件例項,this === undefined next( vm => { // 通過 vm 訪問元件例項 }) }

$route路由資訊不重新整理問題

  • 使用場景

有的時候,你從 /user?id=1 跳轉到 /user?id=2 的時候,由於渲染同樣的 User 元件,導致路由會複用,此時,頁面就會仍然是使用者1的資訊。

解決方案

  • 元件內的路由守衛

javascript beforeRouteUpdate(to, from, next) { // 在當前路由改變,但是該元件被複用時呼叫 // 舉例來說,對於一個帶有動態引數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由於會渲染同樣的 Foo 元件,因此元件例項會被複用。而這個鉤子就會在這個情況下被呼叫。 // 可以訪問元件例項 `this` },

  • <router-view> 繫結 key

javascript <router-view :key="$route.fullpath"></router-view>

  • 使用watch監聽路由

javascript watch:{ '$route':{ hander(){ // do something... }, immediate:true //如果要首次載入就觸發 } }

$emit傳參同時拿到父子元件兩者入參的值

在實際專案開發中,可能會遇到 $emit 的值和父元件的index都要拿的情況,但是按照之前的寫法,只能拿到其中一個的值,要麼子元件,要麼父元件,魚和熊掌不可兼得

  • 子元件入參

javascript this.$emit('uploadSuccess',res);

  • 父元件入參

javascript <Up @uploadSuccess="uploadLogoImage(index,arguments)" />

  • 方法取參

javascript uploadLogoImage(){ console.log(arguments[0]); //index console.log(arguments[1][0]); //res },

樣式穿透

  • 使用環境

一般在修改外掛樣式的時候使用的比較多

  • 實際使用

分為兩種,一般stylus中使用>>>less中使用/deep/sass沒有使用經驗,不予說明

```css

.el-dialog .el-dialog__body{ padding 0 text-align center border-radius 0 0 4px 4px } /deep/.el-dialog .el-dialog__body{ padding 0 text-align center border-radius 0 0 4px 4px } ```

Object.freeze()

  • 使用環境

我們都知道vue是使用Object.defineProperty對資料進行雙向繫結,而對於只做展示使用的長列表,可以使用Object.freeze()進行凍結,使它無法被修改,從而提高效能

  • 實際使用

javascript getList().then(res=>{ this.list=Object.freeze(res.data.result); })

值得注意的是,改變list的值不會更新,但改變引用會觸發更新

元件通訊技巧

  • props
  • $emit
  • $attrs & $listeners
  • provide & inject
  • vuex
  • Observable
  • eventBus
  • $refs
  • slot-scope & v-slot
  • scopedSlots
  • $parent & $children & $root

父子元件引數同時獲取

  • 使用環境,有的時候父元件中,要拿取子元件中 $emit 傳遞的值,並且,要拿到父元件 v-for 當前的 index

子元件入參

javascript this.$emit('uploadSuccess',res);

父元件入參

javascript <Up @uploadSuccess="uploadLogoImage(index,arguments)" />

  • 實際使用

javascript uploadLogoImage(){ console.log(arguments[0]); //index console.log(arguments[1][0]); //res },

mixins混入的使用

  • 使用環境

一般獲取驗證碼,收藏,點贊等公用且邏輯一樣(有些邏輯是根據頁面的不同而不同的不建議使用混入)等場景都可以使用混入

  • 實際使用

這裡我直接封裝了一個vue新開視窗的混入方法,引入了以後,混入中的所有data,methods,以及生命週期都會共享

```javascript //openWindow.js export default { methods:{ openUrl(url){ const link= this.$router.resolve({path: url}); window.open(link.href,'_blank'); }, } }

//其他頁面使用 import openWindow from "../../mixins/openWindow";

export default{ mixins:[openWindow], } ```

  • 注意點(使用的頁面統稱為元件)

① 混入比元件優先執行

② 當混入中的屬性或者方法與元件中的屬性或者方法名稱相同時,以元件中的值為準(結合上一條規則,因為混入先執行,所以元件會將混入覆蓋)

③ 比方說A頁面和B頁面都使用了同一個混入,A頁面與B頁面的狀態同樣是獨立的

qs

  • 使用場景,get傳輸的時候都是路由拼接方式(?a=1&b=2),而不是json方式

  • 實際使用

```javascript //安裝依賴 npm install qs --save

//頁面中或者直接api.js中直接序列化使用 import qs from 'qs' qs.stringify(params)

//axios攔截器中直接使用 import qs from 'qs' axios.interceptors.request.use( config => { if (config.method === 'get') { config.data = qs.stringify(config.data) } ) ```

v-for繫結key不建議使用index

  • 主要原因

有的時候v-for列表可能存有刪除,交換位置等操作,這種時候index的順序變換會導致同一條資料,在此刻的index置換,所以,不建議v-for的key繫結index

  • 解決方案

建議使用另外的並且值唯一的變數,例如後臺給你的id,反正只要是唯一,不會重複即可

v-for不建議配合v-if

  • 主要原因

v-for的優先順序比v-if高,也就是說,假設總計50條資料,即使經過v-if以後,只剩下25條顯示,但是v-for早就迴圈了一遍50條資料,解決辦法就是用一個計算屬性先將資料過濾了以後,v-for迴圈過濾了之後的資料

  • 解決方案

使用 computed 計算屬性,對列表進行過濾,只剩下過濾之後需要的資料

document.body.contentEditable

  • 操作方法

開啟控制檯,輸入document.body.contentEditable=true,然後敲回車,網頁可以像word一樣編輯,很方便對於頁面的佈局抗壓能力做測試

「其他文章」