v-if 和 v-for 哪個優先級更高?
來自 eslint-plugin-vue 的兩種提醒
當使用v-for v-if寫在同層的時候,會可能收到來自eslint-plugin-vue的兩種提醒
-
[vue/no-use-v-if-with-v-for] This 'v-if' should be moved to the wrapper element.eslint-plugin-vue
v-if 應該移動外層元素
-
[vue/no-use-v-if-with-v-for] The 'list' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.eslint-plugin-vue
v-for 列表內容的判斷應該通過 computed 返回 filtered 數組代替,不能混合使用 'v-for' 和 'v-if'
//這種寫法是不推薦的
<li v-for="item in list" v-if="item.type==='cat'" :key="item.id">{{item.name}}</li>
寫在同層
為什么會有這兩種提醒呢,這就跟Vue對v-for和v-if的執行時序有關
先來做個測試
<template>
<div id="app"> <!-- <ul v-if="isRenderList"> <li v-for="item in list" :key="item.id">{{item.name}}</li> </ul> --> <ul> <li v-if="isRenderList" v-for="item in list" :key="item.id">{{item.name}}</li> </ul> </div> </template> <script> export default { name: "App", data() { return { isRenderList: true, list: [ { id: 1, type: "cat", name: "喵喵1" }, { id: 2, type: "cat", name: "喵喵2" }, { id: 3, type: "dog", name: "汪汪1" }, { id: 4, type: "dog", name: "汪汪2" }, { id: 5, type: "cat", name: "喵喵1" }, { id: 6, type: "cat", name: "喵喵1" }, { id: 7, type: "cat", name: "喵喵1" }, { id: 8, type: "cat", name: "喵喵1" }, { id: 9, type: "cat", name: "喵喵1" } ] }; }, beforeCreate() { console.log(this.$options.render); } }; </script>
template 中的內容最終都會處理成 render 函數
我們來看 beforeCreate 的時候打印的 render 函數長啥樣的
兩者同級的時候渲染函數如下
// _vm._l 是渲染列表相關的函數
render = function() { var _vm = this var _h = _vm.$createElement var _c = _vm._self._c || _h return _c("div", { attrs: { id: "app" } }, [ _c( "ul", _vm._l(_vm.list, function(item) { return _vm.isRenderList ? _c("li", { key: item.id }, [_vm._v(_vm._s(item.name))]) : _vm._e() }), 0 ) ]) }
可見 v-for 和 v-if 同級的時候,v-for 的優先級更高,在渲染函數中的處理先進行 list 的循環渲染,內層再判斷是否渲染
兩者不同級的時候渲染函數如下:
render = function() {
var _vm = this var _h = _vm.$createElement var _c = _vm._self._c || _h return _c("div", { attrs: { id: "app" } }, [ _vm.isRenderList ? _c( "ul", _vm._l(_vm.list, function(item) { return _c("li", { key: item.id }, [_vm._v(_vm._s(item.name))]) }), 0 ) : _vm._e() ]) }
而當 v-if 與 v-for 不同級的時候會先進行 _vm.isRenderList 判斷再進 _vm._l 渲染
由上面可知
-
Vue 會解析 v-for 再解析 v-if
-
兩者同時出現的時候,內層每一層都會進行判斷,性能欠佳
-
eslint-plugin-vue 給出優化的提示
-
在外層進行 v-if 判斷,然后在內部進行v-for循環
-
如果在內層出現條件判斷,則可以使用計算屬性返回一個篩選過的數組
-
computed: {
catList() { return this.list.filter(item => { return item.type === "cat"; }); } }
本文使用 mdnice 排版
