重新閱讀 vue 文檔收穫

最近有空,心血來潮想着再去把 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;
	} 
},

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章