美食 健康 常识 生活 日常 合同 家居 养生 国学 心理学 中医 植物 营销 动物 汽车 管理 旅游 投资 人工智能 数字化 消费 元宇宙 金融 饮食 史学 经济
  • 会员

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

    结论

    1、本身并不建议将v-for和v-if同时使用的。

    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 调用 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()
    
    });
    优先级比较:v-for 和 v-if哪个更高?
    微信扫码分享

    0

    0

    分享
  • 会员

  • 上一篇: RUBY编程语言中文介绍PDF版

    下一篇: php字符串怎么只保留字母

    还没有评论,赶紧来抢沙发吧!

    有这几种迹象,说明领导已不把你放在眼里了,再拼命干就是犯傻

    职场中,有时候我们会发现自己的努力并没有得到领导的认可,甚至感觉领导已经不把我们放在眼里了。 这种情况不仅会让我们感到失 …

    土鸡蛋的功效与作用(小孩吃土鸡蛋的功效与作用)

    土鸡蛋一种常见的食物,那么土鸡蛋的功效与作用有什么呢? 保护视力 土鸡蛋的蛋黄中的两种抗氧化物质——叶黄素和玉米黄素,能 …

    花胶可以和排骨一起炖吗 花胶能炖排骨吗

    花胶的胶原蛋白含量非常之高,用来炖汤食用,能给身体补充充足的营养物质,对皮肤也好,那么花胶可以和排骨一起炖吗? 花胶可以 …

    海蛎煎怎么做(海蛎煎怎么做好吃)

    1、主料:生蚝适量。辅料:青蒜适量,鸡蛋2个,地瓜粉适量,调料:色拉油适量,食盐适量,醋适量,料酒少许,五香粉适量,胡椒 …

    哺乳期可不可以吃三九感冒灵颗粒(哺乳期可以喝小儿三九感冒灵颗粒吗)

    建议哺乳期最好不要自己随便喝三九感冒灵颗粒类药物,因为三九感冒灵颗粒属于中西结合的复方制剂的药,其中的成分有中药也有西药 …

    怎么能去掉老年斑(怎么能去掉老年斑和斑块)

    1、适当按摩:在老年斑出现的位置让自己坚持进行按摩,坚持按摩可以延缓老年斑的加重,帮助分解色素,慢慢让斑点颜色变浅直到消 …

    椰子鸡汤营养和功效与作用 孕妇吃椰子鸡汤营养和功效与作用

    椰子鸡是广东地区的名菜,主要原料是椰子跟鸡肉,不知道椰子鸡汤食用以后有什么营养功效与作用呢? 椰子鸡汤营养和功效与作用 …

    烧鱼头豆腐汤用冷水还是热水 鱼头豆腐汤加热水还是冷水

    1、用热水。 2、材料:鱼头:1个、南豆腐:2块、香菜:1棵、小葱:1根、姜:3片、食盐:1茶匙、香油:数滴、水:适量、 …

    饼干保质期一般多长时间(饼干保质期是多长时间)

    1、饼干的保质期因配方,操作,原料,包装等不同而保质期不同。袋装一般可以保质期一年,散装的也就3-4个月。具体参照生产厂 …

    太敏感,太自卑,太内向?你可能低估了自己!

    生活中,你是否经常有这样的困扰: 不喜欢社交,一到人多的场合就不知所措 聊天时总是不知道说什么,话废一枚 遇到困难不敢开 …

    炸鸡用的裹粉是什么

    炸鸡用的裹粉是低筋面粉,但是如果只用面粉,炸出来的鸡腿表面没有鳞片,影响口感,可以将面粉和蛋液混合,外面再裹上面包糠。或 …

    百香果青的能吃吗(百香果青的能吃吗?)

    百香果因其富含很好的营养价值和清新口感而受大家欢迎。我们平常在市面上看到的百香果,有的是青颜色的。那么问题来了,百香果青 …

    苦瓜榨汁的功效与作用 苦瓜榨汁有什么功效

    虽然苦瓜的味道比较苦,但是营养却是非常丰富的,很多人都会用苦瓜来榨汁喝,那苦瓜榨汁有什么功效与作用呢? 清热解毒 苦瓜味 …

    粗粮养生知识最新

    黄豆、绿豆、红豆、黑豆、蚕豆、豌豆等豆类,红薯、山药、马铃薯等块茎类。由于粗粮加工简单,因此保存了许多营养成分。下面是小 …

    北京生物和北京科兴中维能混着打吗(北京科兴中维和北京生物哪个好可以混打吗)

    目前全国都在推进新冠疫苗接种,其中北京科兴和北京生物是接种人数最多的两款灭火疫苗,许多小伙伴有这样的疑问,北京科兴中维和 …

    貂皮基本知识大全

    一般淺色的貂皮大衣,一到兩年洗一次,深色的三到四年洗一次。具體清洗時間,還要視個人穿著情況而定。 水貂介紹 ①“水貂” …

    炖乌鸡汤放什么材料好 炖乌鸡汤放什么材料好呢

    说起乌鸡汤,大家都知道它是补虚劳、养身体的上好佳品,在乌鸡汤里面加入其他的配料,味道鲜美,营养丰富。那么炖乌鸡汤放什么材 …

    想要加速让他“喜欢你”?这四招心理学技巧,你必须要知道!

    爱情,是一场无言的交流,一段动人的旋律。 当我们陷入爱情的漩涡中,总希望能够加速对方对自己的喜欢,让他迅速被自己吸引。 …

    鲍鱼排骨汤的功效与作用 苦瓜鲍鱼排骨汤的功效与作用

    鲍鱼和排骨都是营养非常丰富的食材,具有较高的营养价值和食用价值,那么将两种食材一起炖汤的话,鲍鱼排骨汤的功效与作用是什么 …

    PHP的中文含义是什么

    PHP的中文含义是“超文本预处理器”,是一种跨平台的、开源的、服务器端脚本语言,主要适用于Web开发领域。 PHP的优势 …