vue v-if和v-show的区别、v-if-for优先级的问题、scoped及css样式穿透

本文介绍了Vue中的v-if与v-show的区别,v-if在初次渲染和切换时开销较低,适合不频繁切换,而v-show通过CSS控制显示,适合频繁切换。在v-if和v-for共用时,Vue2中v-for优先级高,Vue3则相反。优化方案包括避免同时使用v-if和v-for,使用计算属性,以及外部v-if内部v-for的结构。另外,scoped属性用于组件样式隔离,通过data-v-xxx实现,但无法阻止父组件修改子组件根节点样式,可以使用>>>或::v-deep解决样式穿透问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue 区分题

v-if 和 v-else

  • v-if值为false时,在该位置创建一个注释节点,用来标识元素在页面中的位置。在值发生改变的时候,通过diff,新旧组件进行patch,创建DOM节点,从而动态显示隐藏。
  • v-show值为false时,通过设置元素的样式,display:none来控制元素是否展示。
-v-ifv-show
本质操作DOM元素进行切换显示设置css样式进行切换显示
首次渲染开销较低较高
切换开销较高较低
适用场合不频繁切换频繁切换
对生命周期的影响会影响不会影响
  • 当v-if指令附属于普通元素时,v-if指令状态变化会使得父组件的dom发生变化,父组件将会更新视图,所以会触发父组件的beforeUpdateupdated钩子函数。
  • 当v-if指令令附属于组件时,v-if指令状态变化对父组件的影响和上一条一致,但是对于本身组件的生命周期的影响是不一样的。
    • v-if从false切换到true时,会触发beforeCreatecreatedbeforeMountmounted钩子。
    • v-if从true切换到false时,会触发beforeDestroydestroyed钩子函数。

v-if 与 v-for优先级,vue2如何优化得到更好的性能?

  • vue2,在一个元素上同时使用v-ifv-for时,v-for优先作用
  • vue3 v-if优先作用

尽量避免在同一个元素上面同时使用v-if和v-for,因为每次渲染都会先循环完整个列表再进行条件判断,带来性能方面的浪费。
①如果要遍历的数组很大,而真正要展示的数据很少时
② 哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。

https://juejin.cn/post/6844904183619944462
待补充:如何理解Vue中的模板编译原理,补充后进行笔记修改

vue2的优化方案
1.可以用计算属性替换
2.外层嵌套template标签,页面渲染不生成DOM节点,在template标签上使用v-if,在内层使用v-for

案例

假设有一个 todoList:

const todoList = [
  {
    id: 0,
    task: '吃饭',
    done: true,
  },
  {
    id: 1,
    task: '睡觉',
    done: false,
  },
  {
    id: 2,
    task: '洗澡',
    done: true,
  },
  // ...,
];

vue2的写法,v-for优先级高于v-if 所以可以用作于同一个元素

<ul>
  <!-- vue2中,v-for优先级高于v-if -->
  <li v-for="item in todoList" v-if="!item.done" :class="{todo: !item.done}" :key="item.id">
    <span>{{item.task}}</span>
  </li>
</ul>

查看生成的渲染函数,就可以知道执行的顺序。

渲染函数render中的_l 方法,它是列表渲染的函数,就是将来会循环输出所有 listdata,然后每循环一次执行的具体的函数会是后面的这个工厂函数。在这个工厂函数里面,return 才是最终的结果。

vue3中,v-if优先级高于v-for,所以像vue2一样用作于同一个元素。在外面套一层用作于循环。

<ul>
  <template v-for="item in list" :key="item.id">
    <li v-if="!item.done" :class="{todo: !item.done}">
      <span>{{item.task}}</span>
    </li>
  </template>
</ul>

参考文章
作者:攻城狮_老李
链接:https://juejin.cn/post/6881581395068747790
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

scoped

一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,这样就可以使得组件之间的样式不互相污染。如果一个项目中的所有style标签全部加上了scoped,相当于实现了组件的私有化,样式的模块化。

原理
scope的本质是分别给 HTML 标签和 CSS 选择器添加 data-v-xxx,来达到样式隔离的效果。
样式穿透问题
使用 scoped 后,父组件的样式将不会渗透到子组件中。
但是父组件可以修改子组件根节点样式。
解决办法
vue2 >>> :>>> 会被编译成当前父组件的date-v-xxx

<style>
    .a >>> .b >>> span{
    color:red;
    }
</style>

// 渲染结果,当有多个时只有最左边的>>>生效
.a[data-v-xxx] .b >>> span{
    color:red;
}

vue3 ::v-deep(.class)

面试题

  • vue样式穿透scoped
  • scoped的原理
  • vue中的scoped style是如何实现作用域样式以及为什么vue不使用css module来实现作用域?
  • css样式隔离了解吗?有哪几种方法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值