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

  • 优先级比较: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字符串怎么只保留字母

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

    2023年植树节是几月几号 2023年植树节是星期几

    植树节是人们按照法律规定宣传保护树木。并且鼓舞大家一起积极的参与到树木的保护中。希望可以通过大量种植绿色植物来帮助改善整 …

    饭店里的小酥肉怎么做的 饭店里的小酥肉怎么做的啊

    1、用料:猪肉500g、油适量、盐一勺、鸡精一勺、酱油一勺、料酒一勺、花椒粉一勺、鸡蛋一个、淀粉两勺、糖半勺、姜两片。 …

    红糖姜水是早上空腹喝吗 红糖生姜水可以早上空腹喝吗

    我们都知道,红糖生姜水是非常好的补血暖身、驱寒的效果,那么红糖姜水是早上空腹喝吗? 红糖姜水是早上空腹喝吗 早上空腹最好 …

    泰式咖哩牛肉的做法(泰式咖喱牛肉的做法)

    1、原料:牛腩300克、土豆200克、青红椒块15克、洋葱块20克、姜片、葱段、精盐、黄酒、味精、白糖、鸡粉、印度咖喱膏 …

    夫妻能不能相伴到老,上天早就注定好了,真的不是迷信!

    夫妻之间的相处关系,是人类社会中永恒的话题。 不同的人们对待婚姻有不同的理解。 有人认为婚姻是两个人在经济利益、家族血统 …

    男人这三件事满足不了你,别和他在一起,他给不了你幸福

    这三种感觉是关系中必要的元素,缺一不可,否则,就难以拥有真正的幸福。 第一种感觉是身心的舒适。 我们都渴望找到一个可以依 …

    最火的虎年新春对联

    新年到来,又到了贴春联的时候了,春节期间悬挂的对联称为春联,代表着生活的繁荣、团圆、幸福与和谐。最火的虎年新春对联有哪些 …

    正宗鱼圆制作方法(鱼圆制作流程)

    1、材料:鲤鱼(或青鱼)1尾(1000克以上,以大鱼为佳),姜汁1克,葱汁1克,味精1克,鸡蛋4只,盐3克,猪油55克, …

    水芹菜有什么功效 水芹菜有什么功效与作用

    水芹菜主要生长在沼泽地或者是湿地,主要是南方的一种蔬菜。在北方比较少见。那么水芹菜有什么功效? 补血的作用 水芹菜当中含 …

    中考化学知识点总结归纳(完整版)

    中考化学知识点总结归纳 金属 金属通常是固体,但不是所有的金属都是固体。 金属通常很活泼,容易与空气中的氧气、酸和某些盐 …

    煮虾用热水还是冷水

    虾的肉质鲜美,吃起来味道非常棒,营养价值也是很高,是人们餐桌上常见的一款食物,关于虾的做法也是多种多样,那么煮虾用热水还 …

    皇帝柑什么时候最好吃()

    皇帝柑是近年来比较受欢迎的一种柑橘类水果,其皮薄汁多,味道微酸偏甜,非常好吃,而且营养丰富,富含维生素C、有机酸、矿物质 …

    桂圆莲子银耳汤的禁忌(桂圆莲子银耳汤的禁忌是什么)

    桂圆莲子银耳汤是一道常见的甜品,还有补脾益胃、润肺生津等多种食疗功效,但并不是所有人都适合吃,那么桂圆莲子银耳汤的禁忌有 …

    红糖发糕面太稀可以吗(红糖发糕的面太稀了怎么办)

    红糖发糕甜甜的非常好吃,而且红糖有补益身体的作用,这道甜品不仅好吃而且还好看,因此深受大家的喜爱,但很多人在自制红糖发糕 …

    苍蝇的养殖方法 苍蝇怎么养殖

    1、养殖苍蝇首先要挑选合适的蝇房,要求室内空气新鲜保持温度在24-30度之间,每天光照10小时以上,要将蛆虫洒在新鲜的粪 …

    双色桂花重阳糕的做法 双色桂花重阳糕的做法大全

    1、先做桂花糕。桂花糕做法:玉米淀粉过筛,加入235克水搅匀。 2、把三花淡奶,椰桨,和糖桂花放在一起搅匀,把鱼胶粉,3 …

    连续一个月吃苹果会怎么样

    第一,皮肤变好。 苹果含有多种维生素,这些天然维生素可以滋养和修复人们的皮肤。 第二,不再便秘。 苹果是一种神奇的水果。 …

    军装肩章级别

    我军军装肩章级别分为三等十级,从高到底分别为:将官级:上将、中将、少将。校官级:大校、上校、中校、少校。尉官级:上尉、中 …

    做冬阴功汤的教程(冬阴功汤制作过程)

    1、食材:虾6只、鱿鱼须1个、花甲10个、番茄1个、蟹味菇60g、柠檬1个、柠檬叶10片、香菜1小把、干良姜4片、干辣椒 …

    热天吃什么水果好(热天吃什么水果好呢)

    夏天是个炎热的季节,其实也是众多水果盛产的季节,在这种热天里选择食用的水果也是一门学问。 柑橘 柑橘果实能润肺理气,新鲜 …