您好,欢迎访问一九零五行业门户网

优先级比较:v-for 和 v-if哪个更高?

v-for 和 v-if哪个优先级更高?下面本篇文章就从实际例子和源码讲解v-for和v-if的优先级,相信你看完后会茅塞顿开的。
结论1、本身并不建议将v-for和v-if同时使用的。(学习视频分享:vue视频教程)
2、vue2里面v-for比v-if的优先级更高。因为vue2在模板编译的时候会先处理v-for再处理v-if,所以生成的渲染函数会先执行循环,然后在循环里面再执行条件判断。
3、这样做带来的问题就是
对于场景1:<li v-for="user in users" v-if="user.show">
每次重新渲染的时候,都要重新遍历整个列表,其实我们只需要列表的一部分,这样做浪费性能。推荐的做法是,通过计算属性先过滤出我们需要的部分,再去渲染,更高效。
对于场景2: <li v-for="user in users" v-if="globalshow">
globalshow这个判断其实如果是false,循环并不需要执行,但是现在跟v-if一起用,不管globalshow是否是true都要执行循环,完全是浪费。推荐的做法是将v-if上移到ul容器。
4、需要注意的是,vue3的breaking change,在vue3中v-if的优先级比v-for高,所以如果同时使用的话,对于场景1,这个时候user还没有,v-if=user.show就会报错
5、一般我们如果有用eslint,也会给我们报错,对应的规则是:vue/no-use-v-if-with-v-for
实际例子例如:以下的模板,将会生成下面的渲染函数
<ul>    <li v-for="user in users" v-if="user.isactive" :key="user.id">        {{ user.name }}    </li></ul>
生成的渲染函数如下
with(this) {    return _c('ul', _l((users), function (user) {        return (user.isactive) ? _c('li', user.name) : _e()    }), 0)}
从上面生成的渲染函数可以看出,会先执行_l遍历user,在里面进行条件判断
源码处理v-if和v-for的源码
src/compiler/index.js
// 模板解析,生成ast树const ast = parse(template.trim(), options)if (options.optimize !== false) {    optimize(ast, options)}const code = generate(ast, options)
根据ast生成代码,假如是上面的模板,生成的ast简化后如下
// 可以看出v-for和v-if都解析出来了 ast = {     'type': 1,     'tag': 'ul',     'attrslist': [],     'attrsmap': {},     'children': [{     'type': 1,     'tag': 'li',     'attrslist': [],     'attrsmap': {         'v-for': 'user in users',         'v-if': 'user.show'     },     // v-if解析出来的属性     'if': 'user.show',     'ifconditions': [{         'exp': 'user.show',         'block': // 指向el自身     }],     // v-for解析出来的属性     'for': 'users',     'alias': 'user',     'iterator1': 'index',     'parent': // 指向其父节点     'children': [         'type': 2,         'expression': '_s(user)'         'text': '{{user}}',         'tokens': [             {'@binding':'user'},         ]      ]     }] }
compiler/codegen/index.js
// generate 调用 genelementconst code = ast ? genelement(ast, state) : '_c(div)'// genelement里面的处理if (el.staticroot && !el.staticprocessed) {return genstatic(el, state)} else if (el.once && !el.onceprocessed) {return genonce(el, state)// 从这可以看出来,先执行genfor,处理v-for指令,在genfor里面会递归调用genelement,继续处理v-if,genfor会将forprocessed设为true,这样下次进来的时候就不会处理for了} else if (el.for && !el.forprocessed) {return genfor(el, state)} else if (el.if && !el.ifprocessed) {return genif(el, state)} else if (el.tag === 'template' && !el.slottarget && !state.pre) {return genchildren(el, state) || 'void 0'} else if (el.tag === 'slot') {return genslot(el, state)} else {// 最后这里处理标签等const children = el.inlinetemplate ? null : genchildren(el, state, true)code = `_c('${el.tag}'${data ? `,${data}` : '' // data}${children ? `,${children}` : '' // children})`}// genfor的代码const exp = el.for // 对应上面ast的 for: usersconst alias = el.alias // alias: user// iterator1 对应v-for的(item,key,index) in items的key// iterator2 对应的是index// 通常我们遍历数组 key就是index// 假如我们遍历的是对象 key就是对象的key,index就是遍历的索引const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''el.forprocessed = true // 下次递归调用genelement的时候就不会重复处理v-for了return `${althelper || '_l'}((${exp}),` +`function(${alias}${iterator1}${iterator2}){`// 这里处理完了v-for,递归调用genelement继续处理v-if`return ${(altgen || genelement)(el, state)}` +'})'
最终会生成类似如下的代码返回出去
_l((users), function(user, index) {    // 如果有v-if 前面就会有个条件判断,如user.isactive    return (user.isactive) ? _c('li', user.name) : _e()});
(学习视频分享:web前端开发、编程基础视频)
以上就是优先级比较:v-for 和 v-if哪个更高?的详细内容。
其它类似信息

推荐信息