0

0

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

青灯夜游

青灯夜游

发布时间:2022-08-29 19:52:05

|

4141人浏览过

|

来源于掘金社区

转载

v-for 和 v-if哪个优先级更高?下面本篇文章就从实际例子和源码讲解v-forv-if的优先级,相信你看完后会茅塞顿开的。

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

结论

1、本身并不建议将v-for和v-if同时使用的。(学习视频分享:vue视频教程

2、vue2里面v-for比v-if的优先级更高。因为vue2在模板编译的时候会先处理v-for再处理v-if,所以生成的渲染函数会先执行循环,然后在循环里面再执行条件判断。

3、这样做带来的问题就是

对于场景1:

  • 每次重新渲染的时候,都要重新遍历整个列表,其实我们只需要列表的一部分,这样做浪费性能。推荐的做法是,通过计算属性先过滤出我们需要的部分,再去渲染,更高效。

    对于场景2:

  • 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

    易可图
    易可图

    电商人都在用的设计平台

    下载

    实际例子

    例如:以下的模板,将会生成下面的渲染函数

    • {{ user.name }}

    生成的渲染函数如下

    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 调用 genElement
    const 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: users
    const 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前端开发编程基础视频

  • 相关专题

    更多
    c++ 根号
    c++ 根号

    本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

    57

    2026.01.23

    c++空格相关教程合集
    c++空格相关教程合集

    本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

    57

    2026.01.23

    yy漫画官方登录入口地址合集
    yy漫画官方登录入口地址合集

    本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

    237

    2026.01.23

    漫蛙最新入口地址汇总2026
    漫蛙最新入口地址汇总2026

    本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

    393

    2026.01.23

    C++ 高级模板编程与元编程
    C++ 高级模板编程与元编程

    本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

    17

    2026.01.23

    php远程文件教程合集
    php远程文件教程合集

    本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

    103

    2026.01.22

    PHP后端开发相关内容汇总
    PHP后端开发相关内容汇总

    本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

    73

    2026.01.22

    php会话教程合集
    php会话教程合集

    本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

    81

    2026.01.22

    宝塔PHP8.4相关教程汇总
    宝塔PHP8.4相关教程汇总

    本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

    70

    2026.01.22

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Vue 教程
    Vue 教程

    共42课时 | 7.1万人学习

    Vue3.x 工具篇--十天技能课堂
    Vue3.x 工具篇--十天技能课堂

    共26课时 | 1.5万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号