最近有空,心血來潮想着再去把 vue 文檔給讀一遍,記一下收穫
1、避免 v-if
和 v-for
用在一起
這裏的問題以前完全沒有注意過,導致經常寫 iview 出現這一類的代碼
<Select>
<Option v-for="(item, index) in menuList" v-if="item.isUsed" :key="index">{{item.name}}<Option>
</Select>
原因:
v-for 的優先級 比 v-if 要高,導致 渲染的時候,先執行了 v-for ,後執行了 v-if ,這是一個完全沒有必要的 開銷
以上還有一個問題:
:key="index"
key 屬性實際上是用來 diff 的時候,看能不能複用 節點的。
在diff 的時候,他會先查看 key 屬性有沒有一樣的,一樣的就拿過來複用,減少開銷。
所以儘量使用類似於 id 之類獨一無二,又不像index 這一類毫無意義的 key
2、slot-scope 和 #default="{}"
相信不少同學對這個是比較陌生的,也有同學是比較瞭解的,
但是在iview 開發文檔中,Table 中 提供了這個屬性,相當好用,不需要再 render 了 iview 更新日誌
所以我特地關注了一下這個, 具名插槽 slot-scope
文檔給出的demo:
<Table :data="tableDate" :columns="columnContract" >
<template slot-scope="{ row }" slot="contractNo">
<MyToolTip :words="row.contractNo" :maxLength="20"></MyToolTip>
</template>
</Table>
vue 淘汰了上面的使用方法,: 新版用法
<Table :data="tableDate" :columns="columnContract">
<!-- 這裏 使用了結構 -->
<template #contractNo="{ row }">
<MyToolTip :words="row.contractNo" :maxLength="20"></MyToolTip>
</template>
</Table>
slot-scope="{ row }" slot="contractNo"
完全可以使用
#contractNo="{ row }"
來代替
#表示 v-slot: 後面的 contractNo 就是 slot name,注意 ,如果是default的話,一定要寫 #default=""
3、監聽生命週期
所以說,人醜多讀書(*/ω\*),我看了這個之後,發現自己以前寫的代碼都是辣雞
場景:有一個頁面,進入之後就設計了一個定時器,每5秒 去請求一次數據,在離開的時候,需要clear 這個定時器
beforeDestroy () {
clearInterval(this.time);
},
看起來完全沒問題,但是 程序化的事件偵聽器
- 它需要在這個組件實例中保存這個
picker
,如果可以的話最好只有生命週期鉤子可以訪問到它。這並不算嚴重的問題,但是它可以被視爲雜物。 - 我們的建立代碼獨立於我們的清理代碼,這使得我們比較難於程序化地清理我們建立的所有東西。
所以可以有更好的
mounted: function () {
在mounted 創建 定時器
var time = new setInterval(fn, 5000)
監聽 beforeDestory 事件,然後清除定時器
this.$once('hook:beforeDestroy', function () {
clearInterval(time)
})
}
至於爲什麼監聽的是 'hook:beforeDestroy' ,這個 hook: 又是哪裏來的,我看了一下 vue 的源碼
function callHook (vm, hook) {
// #7573 disable dep collection when invoking lifecycle hooks
pushTarget();
var handlers = vm.$options[hook];
var info = hook + " hook";
if (handlers) {
for (var i = 0, j = handlers.length; i < j; i++) {
invokeWithErrorHandling(handlers[i], vm, null, vm, info);
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook);
}
popTarget();
}
vue 中, 直接 vm.$emit('hook:' + hook);
4、事件修飾符 .passive
說實話,看到這個我是有點不知所措地,可能以前完全沒有注意到,我竟然不知道這個屬性是什麼意思,
查了之後,發現是 addEventListener 的 第三個參數對象中的一個 具體的可以對應的 文檔
舉個栗子,你在移動端使用原生的滾動的時候,如果addEventListener 監聽了實際上剛剛開始 是有200ms 的停頓的,
因爲他不知道你是否會 preventDefault(),所以會先執行你addEventListener,然後再原生的滾動,即使你放進去的代碼是自定義的空函數 ,依舊會有這樣的一個延遲
而這個屬性就是爲了告訴瀏覽器,我沒有執行preventDefault(),你放心地先滾起來把
注意,passive 和 preventDefault() 放一起會無視 preventDefault() 並向你扔一個錯誤
5、動態+異步 組件
這個其實沒什麼好像,就是單純的記一下 鏈接
<component :is="currentComponent" ></component>
import LoadingComponent from "./components/LoadingComponent.vue";
import ErrorComponent from "./components/ErrorComponent.vue";
------
components: {
'componentA': () => ({
component: import('./components/componentA.vue'),
// 異步組件加載時使用的組件
loading: LoadingComponent,
// 加載失敗時使用的組件
error: ErrorComponent,
// 展示加載時組件的延時時間。默認值是 200 (毫秒)
delay: 200,
// 如果提供了超時時間且組件加載也超時了,
// 則使用加載失敗時使用的組件。默認值是:`Infinity`
timeout: 3000
}),
'componentB': () => ({
component: import('./components/componentB.vue'),
// 異步組件加載時使用的組件
loading: LoadingComponent,
// 加載失敗時使用的組件
error: ErrorComponent,
// 展示加載時組件的延時時間。默認值是 200 (毫秒)
delay: 200,
})
},
computed: {
currentComponent: function () {
return 'component' + this.AB;
}
},