vue - 性能优化篇

前言

这篇文章主要对vue中 v-if 与 v-for 同时出现时,如何进行性能优化做一个探讨

思考ing

  • v-if 与 v-for 同级时(同时出现)谁的优先级比较高
  • v-if 与 v-for 同级时(同时出现),怎么优化才能得到更好的性能

优先级

从代码中找答案

vue代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>v-if 与 v-for 谁的优先级高</title>
  </head>
  <body>
    <div id="app">
      <p v-for="item in userList" v-if="isLogin">{{item.name}}</p>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: "#app",
      data: {
        isLogin: true,
        userList: [
          { id: 1, name: "赵云" },
          { id: 2, name: "张飞" },
        ],
      },
    });
    console.log(app.$options.render);
  </script>
</html>

调用$options.render生成代码如下:

(function anonymous() {
  with (this) {
    return _c(
      "div",
      { attrs: { id: "app" } },
      _l(userList, function (item) {
        return isLogin ? _c("p", [_v(_s(item.name))]) : _e();
      }),
      0
    );
  }
});
  1. _l()可以在vue源码中看到是renderList(),用于渲染列表。
  2. 通过上面的代码可以看出,会先进行列表的循环,在循环里面进行if的逻辑判断.
  3. 这里永远都是先执行循环,再进行条件判断决定是否渲染.不管条件成不成立,循环是不可避免的.

从源码中找答案

src\compiler\codegenvue.js里面找到genElement

export function genElement (el: ASTElement, state: CodegenState): string {
  if (el.parent) {
    el.pre = el.pre || el.parent.pre
  }

  if (el.staticRoot && !el.staticProcessed) {
    return genStatic(el, state)
  } else if (el.once && !el.onceProcessed) {
    return genOnce(el, state)
  } 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 {
    // component or element
    let code
    if (el.component) {
      code = genComponent(el.component, el, state)
    } else {
      let data
      if (!el.plain || (el.pre && state.maybeComponent(el))) {
        data = genData(el, state)
      }

      const children = el.inlineTemplate ? null : genChildren(el, state, true)
      code = `_c('${el.tag}'${
        data ? `,${data}` : '' // data
      }${
        children ? `,${children}` : '' // children
      })`
    }
    // module transforms
    for (let i = 0; i < state.transforms.length; i++) {
      code = state.transforms[i](el, code)
    }
    return code
  }
}
  1. if else 里面是可以看出,v-for 优先于v-if 解析,也就是说 如果同时存在,v-for永远都在外面 v-if 永远都在里面

实践结论

  1. v-for 优先于 v-if 被解析
  2. 如果两者同时出现, 优先渲染列表再判断条件,无论如何判断,循环都不可避免,浪费了性能.

性能优化方案

避免上面出现的情况, 推荐的解决方案: 在外层嵌套template,在这一层进行v-if判断,然后在内部进行列表渲染.

我们来看看这么做的效果怎样:
HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>v-if 与 v-for 谁的优先级高</title>
  </head>
  <body>
    <div id="app">
      <template v-if="isLogin">
        <p v-for="item in userList">{{item.name}}</p>
      </template>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: "#app",
      data: {
        isLogin: false,
        userList: [
          { id: 1, name: "" },
          { id: 2, name: "" },
        ],
      },
    });
    console.log(app.$options.render);
  </script>
</html>

生成代码如下:

anonymous() {
with(this){
    return 
    _c(
        'div',
        {
            attrs:{"id":"app"}
        },
        [
        (isLogin)?_l((userList),function(item){return _c('p',[_v(_s(item.name))])}):_e()],2)}
}

上面代码中,会先进行条件判断,如果条件成立,才会进行列表渲染。 如果条件不成立,则不会进行列表渲染 , 通过这种方式,减少了不必要的列表渲染,大大提升了性能

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值