前端培训 | 前端面试题:你对Vue中v-if和v-show怎么理解?

在Vue中,有两种方法可以有条件地渲染部分应用程序:v-if和v-show。你可能会问:“为什么需要两种方式来控制元素的隐藏和显示,明明他们的功能和使用方式都一样?问的好,这也是我们在学习Vue时遇到的一个问题。在本教程中,我们将了解什么是两种显示内容的不同方式和工作原理。话不多说,直接进入主题吧。

 一、官方介绍

v-if

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的,如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show

v-show是不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

二、不同点

控制手段

v-if是通过控制dom节点是否存在来控制页面是否显示。

v-show则是节点已经存在,通过dom节点的display样式来控制显隐。display none为不显示 block为显示。

编译过程

v-if是真正的条件渲染,有局部编译和渲染的过程,它会确保切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-show的元素总是会被渲染,它只是简单的基于CSS进行切换。

编译条件

v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

性能消耗

v-if 有更高的切换消耗。

v-show 有更高的初始渲染消耗。

应用场景

基于以上区别,我们可以得出结论:元素进入页面后显示或者隐藏状态不会被修改,建议使用v-if。元素需要非常频繁地切换,则使用 v-show 较好。

三、原理分析

下面我们通过Vue2的源码,来看看v-if和v-show的原理。

1. v-if原理

在模板编译的parse阶段,会使用 processIfConditions 函数处理条件渲染指令的内容:

function genElement (el, state) {
  if (el.if && !el.ifProcessed) {
    return genIf(el, state)
  } else {
    let code
    if (el.component) {
      code = genComponent(el.component, el, state)
    } else {
      const data = el.plain ? undefined : genData(el, state)
      const children = el.inlineTemplate ? null : genChildren(el, state, true)
      code = `_c('${el.tag}'${
        data ? `,${data}` : '' // data
      }${
        children ? `,${children}` : '' // children
      })`
    }
    return code
  }
}
function genIf (
  el,
  state,
  altGen,
  altEmpty
) {
  el.ifProcessed = true;
  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
}
function genIfConditions (
  conditions,
  state,
  altGen,
  altEmpty
) {
  if (!conditions.length) {
    return altEmpty || '_e()'
  }
  var condition = conditions.shift();
  if (condition.exp) {
    return ("(" + (condition.exp) + ")?" + (genTernaryExp(condition.block)) + ":" + (genIfConditions(conditions, state, altGen, altEmpty)))
  } else {
    return ("" + (genTernaryExp(condition.block)))
  }
  function genTernaryExp (el) {
    return altGen
      ? altGen(el, state)
      : el.once
        ? genOnce(el, state)
        : genElement(el, state)
  }
}

从代码可以看出,v-if指令特性是一个三元表达式。带有v-if指令的模版会进行判断,如果值为true,则会生成dom树。值为false,会生成一个注释节点占位。

2. v-show原理

v-show 的本质是 Vue 中内置的一个自定义指令,借助于 v-show 我们可以控制目标节点 style 中的 display 属性值。

我们看一下v-show 内置自定义指令源码。

bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    const originalDisplay = el.__vOriginalDisplay =
      el.style.display === 'none' ? '' : el.style.display
    if (value && transition) {
      vnode.data.show = true
      enter(vnode, () => {
        el.style.display = originalDisplay
      })
    } else {
      el.style.display = value ? originalDisplay : 'none'
    }
  },
  update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
    if (value === oldValue) return
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    if (transition) {
      vnode.data.show = true
      if (value) {
        enter(vnode, () => {
          el.style.display = el.__vOriginalDisplay
        })
      } else {
        leave(vnode, () => {
          el.style.display = 'none'
        })
      }
    } else {
      el.style.display = value ? el.__vOriginalDisplay : 'none'
    }
  },
  unbind (
    el: any,
    binding: VNodeDirective,
    vnode: VNodeWithData,
    oldVnode: VNodeWithData,
    isDestroy: boolean
  ) {
    if (!isDestroy) {
      el.style.display = el.__vOriginalDisplay
    }
  }

通过上述代码可以得知,v-show 指令核心代码就是:el.style.display = value ? el.__vOriginalDisplay : 'none'。通过控制元素的display属性来实现元素的显示隐藏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值