- v-if 与 v-show 的相同点和区别
- 相同点:都可以控制元素的显示和隐藏
- 区别:
- v-if: 控制DOM元素的显示隐藏是将DOM元素整个添加或删除; v-show: 控制DOM 的显示隐藏是为DOM元素添加css的样式display,设置none或者是block,DOM元素是还存在的;
- v-if有更高的切换消耗; v-show有更高的初始渲染消耗;
- 频繁的切换,用v-show;初始渲染后,运行条件很少改变,用v-if;
这个到处都能搜到看到,这个不难理解。
- 对生命周期的影响
v-if和v-show指令可以控制普通元素的隐藏和显示,也可能是用于控制子组件的隐藏和显示。当附属于组件时,指令改变对父组件和子组件本身都会有影响,这时候我们会分开讨论:
- v-if
- 普通元素上
控制普通元素时,不存在子组件和父组件之说;v-if指令状态变化会会使得组件的dom发生变化,组件将会更新视图,所以会触发父组件的beforeUpdate和updated钩子函数
-
子组件上
- 我将我的项目代码部分贴出,navBar是我的子组件,用v-if来控制该子组件的显示和隐藏;
show从true --> false触发生命周期:
- 父组件触发updated钩子
- 子组件触发卸载钩子unMounted
- 我将我的项目代码部分贴出,navBar是我的子组件,用v-if来控制该子组件的显示和隐藏;
show从false --> true触发生命周期:
- 父组件仍然是触发updated钩子
- 子组件触发挂载钩子mounted
-
v-show
-
普通元素上
控制普通元素时,同v-if只会触发beforeUpdate和updated钩子函数
- 子组件上
其他的大家写的都大差不差,不过关于这个v-show就不一样了,有的说 v-show则不会触发组件的生命周期。有的说会触发。那是触发还是不触发,到底什么样的呢?这里本人就着重多描述一些。
这里父组件和子组件是与上图一致的,区别不过在于我将v-if换成v-show
父组件:
子组件:
这时候出现告警:
[Vue warn]: Extraneous non-emits event listeners (clickLeft) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the “emits” option
[Vue warn]: Runtime directive used on component with non-element root node. The directives will not function as intended.
同时,将show变量的值 从true改变为false时,会触发更更新钩子,却不能控制子组件的隐藏;该现象该博客: link描述过,是说子组件一定要有根标签,不然v-show是无法控制组件的隐藏和显示的;
第一种警告是因为:在子组件向父组件发送自定义事件的时候,没有使用“emits”选项声明它。
具体的该博客总结的很清楚:
警告一原因: link
解决该问题的办法说是可以添加跟标签或者通过emits属性声明自定义事件,则可以解决该问题。
或者
这个两个方法确实解决了告警一;但是添加根标签的方法可以同时解决告警一和告警二;
如果仅仅只是通过emits属性声明自定义事件,是可以解决告警一,
因此建议是最好子组件添加根标签。
如果像这个博客说的不理解为什么要加根标签,那也可以在子组件外层包裹一层div:
此时告警一和告警二都被消除,也能控制子组件的显示和隐藏,但是此时就相当于是控制元素的显示与隐藏了,那么只会触发父组件的更新钩子;
-
综上(Vue3):
v-if:
控制普通元素:触发onBeforeUpdate和onUpdated
控制子组件(区分子组件和父组件):
父组件:onBeforeUpdate和onUpdated
子组件:
从true–>false 触发 onBeforeUnmount和onUnmounted;
从false–>true 触发 onBeforeMount和onMounted;
v-show:
控制普通元素:触发onBeforeUpdate和onUpdated
控制子组件(子组件上必须要有跟标签,否则无法控制子组件的显示和隐藏,会出现上述的告警二;区分子组件和父组件):
父组件和子组件(从true–>false 和从false–>true都是):onBeforeUpdate和onUpdated