Vue中的 v-show 和 v-if
一.v-show 与 v-if 原理分析
大致流程如下,就不细说了。
- 将模板template转为ast结构的JS对象
- 用ast得到的JS对象拼装render和staticRenderFns函数
- render和staticRenderFns函数被调用后生成虚拟VNODE节点,该节点包含创建DOM节点所需信息
- vm.patch函数通过虚拟DOM算法利用VNODE节点创建真实DOM节点
v-show 原理
不管初始条件是什么,元素总是会被渲染。
我们看一下在vue中是如何实现的
代码很好理解,有transition就执行transition,没有就直接设置display属性
export const vShow: ObjectDirective<VShowElement> = {
beforeMount(el, { value }, { transition }) {
el._vod = el.style.display === 'none' ? '' : el.style.display
if (transition && value) {
transition.beforeEnter(el)
} else {
setDisplay(el, value)
}
},
mounted(el, { value }, { transition }) {
if (transition && value) {
transition.enter(el)
}
},
updated(el, { value, oldValue }, { transition }) {
// ...
},
beforeUnmount(el, { value }) {
setDisplay(el, value)
}
}
v-if 原理
-
解析阶段:在编译模板过程中,当遇到带有 v-if 指令的元素时,会将该指令解析成一个对应的 Vue 实例中的 _directive 对象。
-
渲染阶段:当 Vue 实例进行渲染时,会通过指令对象的 bind 方法来初始化指令,并根据条件表达式的值判断是否渲染元素。如果条件为真,则创建并插入元素及其 DOM 结构到父元素中;如果条件为假,则移除元素及其 DOM 结构。
-
更新阶段:当条件表达式的值发生变化时,Vue 实例会通过指令对象的 update 方法来更新元素的显示状态。如果条件从假变为真,则创建并插入元素及其 DOM 结构;如果条件从真变为假,则移除元素及其 DOM 结构。
-
销毁阶段:当 Vue 实例被销毁时,会调用指令对象的 unbind 方法来清理相应的事件监听器、DOM 结构等资源。
当一个页面需要根据用户登录状态来显示不同的内容时,可以使用 v-if 指令。
html部分-----------------------------------------------------
<div>
<h1>Welcome to my website!</h1>
<template v-if="isLoggedin">
<p>Hello, {{ username }}! You are logged in.</p>
<button @click="logout">Logout</button>
</template>
<template v-else>
<p>Please login to access the content.</p>
<button @click="login">Login</button>
</template>
</div>
js部分-------------------------------------------------------
new Vue({
el: '#app',
data() {
return {
isLoggedin: false,
username: ''
};
},
methods: {
login() {
// 模拟登录操作
this.isLoggedin = true;
this.username = 'John';
},
logout() {
// 模拟登出操作
this.isLoggedin = false;
this.username = '';
}
}
});
在上述例子中,根据 isLoggedin 的值,页面会渲染不同的内容。如果用户已登录,则显示欢迎信息和登出按钮;如果用户未登录,则显示登录提示和登录按钮。通过修改 isLoggedin 的值,可以动态地切换显示不同的内容。
这里使用了 v-if 指令将不同的模块包裹在 template 标签中,并通过条件表达式来决定是否渲染对应的模块。当 isLoggedin 为真时,显示已登录的内容;当 isLoggedin 为假时,显示未登录的内容。通过点击登录按钮和登出按钮,可以切换登录状态并更新页面的显示。
总的来说,v-if 指令实现了一种惰性地渲染元素的机制,它会根据条件表达式的值动态地创建或销毁元素及其 DOM 结构。通过控制元素的插入和移除,v-if 指令能够提供更高的灵活性和性能优化,但也会带来一定的渲染开销。因此,在选择 v-if 还是 v-show 时,需要根据具体的需求和性能考虑来决定使用哪种方式。
二、v-show 与 v-if 的共同点
v-show 和 v-if 都是 Vue 框架中用于控制元素显示/隐藏的指令。
- 都可以通过一个布尔类型的条件表达式来判断是否渲染元素。
- 在条件为假时,不会显示元素。
- 在条件为真时,会显示元素。
- 当条件表达式的值发生变化时,都可以更新元素的显示状态。
三、v-show 与 v-if 的区别
- 状态初始化:
- v-show:元素一开始会被渲染到 DOM 中,并且可以通过 CSS 的 display 属性进行显示和隐藏。初始状态下,元素始终存在于 DOM 结构中。
- v-if:元素的渲染是惰性的,仅在条件为 true 时才会被渲染到 DOM 中。初始状态下,元素可能不在 DOM 结构中。
- 条件更新:
- v-show:只根据表达式的值来切换元素的显示和隐藏,当表达式的值为 true 时元素显示,为 false 时元素隐藏。元素的 DOM 结构一直保持存在,只是 CSS 的 display 属性在切换显示状态。
- v-if:根据条件表达式的真假动态创建或销毁元素及其对应的 DOM 结构。当条件为 true 时元素渲染到 DOM 中,为 false 时元素从 DOM 中移除。
- 性能影响:
- v-show:由于元素始终存在于 DOM 中,只是通过修改 CSS 的 display 属性来控制显示和隐藏,所以切换显示状态的性能开销较小。
- v-if:根据条件动态地创建和销毁元素及其 DOM 结构,切换显示状态时会有一定的性能开销。如果需要频繁切换显示状态或对性能要求较高的情况下,可以考虑使用 v-show 替代 v-if。
综上所述,v-show 适用于频繁切换显示状态的元素,而 v-if 适用于在条件变化时动态地创建或销毁元素。根据具体需求和性能考虑,选择适合的指令来控制元素的显示和隐藏。
四、v-show 与 v-if 的使用场景
使用 v-show 的场景:
- 需要频繁切换显示状态的元素:由于 v-show 只是通过修改 display 属性来隐藏或显示元素,因此适用于需要频繁切换显示状态的情况,不会造成大量 DOM 元素的创建和销毁。
- 对性能要求较高的场景:相比于 v-if,v-show 的渲染开销较小,因为元素并不会被频繁地创建和销毁,适用于对性能要求较高的场景。
使用 v-if 的场景:
- 需要条件渲染的复杂组件:如果一个组件的渲染逻辑比较复杂,包含大量的子组件、计算属性等,可以使用 v-if 来根据条件动态地创建或销毁该组件,以减少不必要的渲染开销。
- 需要延迟加载的组件:使用 v-if 可以将组件按需加载,只在需要的时候才进行渲染,可以提升初始加载性能和减少资源占用。
- 需要在 DOM 中完全移除元素的场景:由于 v-if 会在条件为假时将元素从 DOM 中移除,适用于需要完全移除元素的场景,节省DOM空间和资源占用。
综上所述,v-show 适用于频繁切换显示状态的元素和对性能要求较高的场景,而 v-if 适用于需要条件渲染、延迟加载或完全移除元素的场景。根据具体的需求和性能考虑,选择合适的指令来控制元素的显示与隐藏。
五、v-show 与 v-if 的优缺点
v-show
优点:
- 元素始终存在于 DOM 结构中,只是通过修改 CSS 的 display 属性来控制显示和隐藏,因此切换显示状态的性能开销较小。
- 不会重复渲染元素,因为元素始终存在于 DOM 结构中,适用于频繁切换显示状态的元素。
缺点:
- 在元素较多时,可能会对页面性能产生负面影响,因为这些元素仍然存在于 DOM 中。
v-if
优点:
- 根据条件表达式的真假动态创建或销毁元素及其对应的 DOM 结构,因此可以在需要时减少页面中 DOM 元素的数量,提高页面性能。
- 在显示状态切换时避免了重复渲染,因此更适合对性能要求较高的场景。
缺点:
- 在频繁切换显示状态时,会进行创建和销毁元素及其对应的 DOM 结构,这会带来一定的性能开销。
- 如果使用 v-if 控制的元素在页面中出现的次数很多,就需要频繁的创建和销毁大量的 DOM 元素,可能会对页面的性能产生不利影响。
综上所述,v-show 适合需要频繁切换显示状态的元素,而 v-if 适合在条件变化时动态地创建或销毁元素。具体使用哪种方式,还需要根据具体的业务情况和性能需求来进行选择。