一、官方解释:
v-if
是“真正”的条件渲染,只会在指令的表达式返回 truthy 值的时候被渲染。因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件内容。因为v-if
是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个<template>
元素当做不可见的包裹元素,并在上面使用v-if
。最终的渲染结果将不包含<template>
元素。相比之下,
v-show
就简单得多——不管初始条件是什么,元素始终会被渲染并保留在 DOM 中,并且只是简单地基于 CSS propertydisplay
进行切换。一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
注意,
v-show
不支持<template>
元素,也不支持v-else
。
二、个人理解:
- 相同点:v-show和v-if都能控制元素的显示和隐藏。
- 不同点:
实现本质方法不同
- v-show本质就是通过设置css中的display设置为none,控制隐藏
- v-if是动态的向DOM树内添加或者删除DOM元素
编译的区别
- v-show其实就是在控制css
- v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
编译的条件
- v-show都会编译,初始值为false,只是将display设为none,但它也编译了
- v-if初始值为false,就不会编译了
性能
- v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。
- 注意点:因为v-show实际是操作display:” “或者none,当css本身有display:none时,v-show无法让显示
- 总结:如果要频繁切换某节点时,使用v-show(无论true或者false初始都会进行渲染,此后通过css来控制显示隐藏,因此切换开销比较小,初始开销较大),如果不需要频繁切换某节点时,使用v-if(因为懒加载,初始为false时,不会渲染,但是因为它是通过添加和删除dom元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)
三、v-if
扩展
用 key
管理可复用的元素
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
那么在上面的代码中切换 loginType
将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input>
不会被替换掉——仅仅是替换了它的 placeholder
。
自己动手试一试,在输入框中输入一些文本,然后按下切换按钮:
这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key
attribute 即可:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
现在,每次切换时,输入框都将被重新渲染。请看:
注意,<label>
元素仍然会被高效地复用,因为它们没有添加 key
attribute。
不推荐同时使用
v-if
和v-for
。当
v-if
与v-for
一起使用时,v-for
具有比v-if
更高的优先级。