vue中v-if和v-show使用区别源码分析

这里为你详细讲解“vue中v-if和v-show使用区别源码分析”的完整攻略。

1. v-if 和 v-show 的使用区别

在Vue中,v-if和v-show的主要区别在于初始渲染时是否会被渲染出来。

  • v-if:如果表达式的值为false,则元素根本不会被渲染到页面中,只有在表达式的值为true时,元素才会被渲染到页面中。

  • v-show:无论表达式的值是true还是false,都会被渲染到页面中,只是在页面中的display属性值不一样(true时为"display: block;",false时为"display: none;")。

下面我们将采用示例来详细说明两者的区别。

首先,我们在html模板中定义两个按钮“Button 1”和“Button 2”,并分别通过v-if和v-show来控制它们的显示和隐藏:

<template>
  <div>
    <button v-if="showButton1">Button 1</button>
    <button v-show="showButton2">Button 2</button>
  </div>
</template>

接下来,我们在data中定义showButton1和showButton2两个变量,并在methods中定义toggleShow方法来切换变量的值:

<script>
export default {
  data() {
    return {
      showButton1: true,
      showButton2: true
    }
  },
  methods: {
    toggleShow() {
      this.showButton1 = !this.showButton1
      this.showButton2 = !this.showButton2
    }
  }
}
</script>

现在,我们来看一下,当页面初次渲染时,v-if和v-show的表现形式之间的区别:

v-if:

如果showButton1的值为true,则按钮1会显示在页面中;
如果showButton1的值为false,则按钮1不会显示在页面中。

v-show:

如果showButton2的值为true,则显示按钮2,并且按钮2在页面中的样式为"display: block;";
如果showButton2的值为false,则显示按钮2,并且按钮2在页面中的样式为"display: none;"。

接下来,我们在页面中添加一个“Toggle”按钮,并将toggleShow方法绑定到该按钮的click事件,测试它们的表现:

<template>
  <div>
    <button v-if="showButton1">Button 1</button>
    <button v-show="showButton2">Button 2</button>
    <button @click="toggleShow">Toggle</button>
  </div>
</template>

当我们单击“Toggle”按钮时,toggleShow方法将被调用,showButton1和showButton2的值将会被反转。

此时,v-if和v-show的表现形式之间的区别将更明显:

  • v-if:当showButton1的值从true变成false时,按钮1将从页面中消失;当showButton1的值从false变成true时,按钮1将重新出现在页面中。

  • v-show:当showButton2的值从true变成false时,按钮2仍然存在于页面中,只是在页面中的display属性值被修改为"display: none;",按钮不可见;当showButton2的值从false变成true时,按钮2同样存在于页面中,只是display属性值被修改为"display: block;",按钮可见。

2. v-if 和 v-show 的源码分析

接下来,我们来分析一下v-if和v-show的源代码实现。

首先,我们来看一下v-if的实现方式:

// 工具函数
function addVIF(node, directive) {
  const exp = directive.expression
  const parent = node.parent
  const trueBranch = node.clone()
  const falseBranch = new VNode('#comment', '', [], node.text, node.__ownerArray, node.__ukey)

  trueBranch.props = trueBranch.props || {}
  trueBranch.props['v-backup-props'] = node.props

  trueBranch.directives = trueBranch.directives || []
  trueBranch.directives.push({
    value: exp,
    arg: undefined,
    modifiers: {},
    name: 'show'
  })

  if (exp) {
    const branch = new VNode('#branch', '', [trueBranch])
    exp && directive.cb(branch, parent, directive)
  } else {
      const branch = new VNode('#branch', '', [falseBranch])
      directive.cb(branch, parent, directive)
    }
}

Vue.prototype._lifecycleHooks.push('attached', function attached () {
  let i, l
  if (this._isAttached && !this._isDestroyed) {
    for (i = 0, l = this.$children.length; i < l; i++) {
      this.$children[i].$callHook('attached')
    }
  }
})

// 指令注册
Vue.directive('if', {
  "terminal": true,
  "priority": 1000,
  "transclude": 'element',
  "update": function updateFn (value) {
    var _this = this
    if (!value) {
      if (!this._block) {
        this._block = this.build()
        this._start = new VNode('#comment', '', [], '', undefined, this._block.__ukey)
        this._end = new VNode('#comment', '', [], '', undefined, this._block.__ukey)
        replace(this.el, this._block, this._start)
        append(this._block, this._end)
        addVIF(this._block, this)
      }
    } else {
      if (this._block) {
        remove(this._block)
        this._block = null
      }
    }
    this._isBlockDestroyed = !value
    this._fragmentFactory = value
  },
  "build": function build () {
    var Frag = Vue.FragmentFactory.clone(),
        children = Frag.parse(this._raw)
    this.compiled = children
    this.transcluded = true
    return Frag.create(children)
  },
  "unbind": function unbindFn () {
    if (this._absorb) return
    if (this._block && this._isBlockDestroyed !== false) {
      this._block.linker.destroy()

      this._block.__v_trans = null
    }
  }
})

我们来解读一下上面的源代码:

  • 在addVIF函数中,我们可以看到,当v-if表达式的值为false时,工具函数addVIF将创建一个注释型#comment的虚拟节点,用于替换原有的节点。

  • 在Vue.prototype._lifecycleHooks.push('attached', function attached () {})中,我们可以看到在Vue实例的生命周期中添加一个‘attached’的钩子函数。

  • 在Vue.directive('if', {})中,我们可以看到v-if指令的注册,主要包含了“终止”、“优先级”、“转译”、“更新”、“创建”和“解绑”功能。

接下来,我们来看一下v-show的实现方式:

Vue.directive('show', {
  bind: function bindFn () {
    var el = this.el,
        transition = el.__v_trans,
        enterClass, leaveClass
    if (!transition) {
      this._isDynamicLiteral = true
      this._setupDynamicLiteral(this.arg)
    }
    if (transition && this.modifiers && this.modifiers.stop) {
      transition.stop = this.modifiers.stop
    }
    if (transition && this.modifiers && this.modifiers.block) {
      enterClass = el.getAttribute(transition.enterClass)
      leaveClass = el.getAttribute(transition.leaveClass)
      if (enterClass !== null && enterClass !== '') {
        el._enterClass = enterClass
      }
      if (leaveClass !== null && leaveClass !== '') {
        el._leaveClass = leaveClass
      }
    }
  },
  update: function updateFn (value) {
    if (value) {
      this.el.style.display = this.originalDisplay
    } else {
      this.originalDisplay = this.el.style.display
      this.el.style.display = 'none'
    }
  },
  unbind: function unbindFn () {
    this.el.style.display = this.originalDisplay || ''
  }
})

我们来解读一下上面的源代码:

  • 在update函数中,我们可以看到当表达式的值为true时,v-show指令将元素的display属性设置为“display:block;”,使元素可见;当表达式的值为false时,v-show指令将元素的display属性设置为“display:none;”,使元素不可见。

  • 在unbind函数中,我们可以看到v-show指令的解绑函数,主要用于恢复原来元素的display属性。

通过以上代码分析,我们可以非常清晰地看到v-if和v-show的实现方式和它们在源码中的区别。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue中v-if和v-show使用区别源码分析 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • 用nodejs实现PHP的print_r函数代码

    当我们使用PHP开发时,经常使用print_r函数来打印复杂数据结构,例如数组、对象等,这样可以方便我们对数据结构的处理和调试。在使用nodejs开发时,我们同样需要类似的函数,那么如何用nodejs实现PHP的print_r函数呢? 下面是完整的攻略。 第一步:安装需要用到的依赖包 我们需要安装两个依赖包:util和string-width。 在终端中执行…

    node js 2023年6月8日
    00
  • node.js发送邮件email的方法详解

    Node.js发送邮件邮箱的方法详解 对于一个Node.js后端应用程序,发送邮件通知是非常常见的功能。Node.js提供了几种不同的方式来实现这个功能,包括使用第三方库、内置的Node.js模块、和调用外部的邮件服务API。 使用第三方库发送邮件 nodemailer 是Node.js的一个流行的第三方库,为我们发送邮件提供了高度定制化和强大易用的API。…

    node js 2023年6月8日
    00
  • node.js实现回调的方法示例

    下面我将详细讲解“node.js实现回调的方法示例”的完整攻略,包含以下内容: 什么是回调函数 Node.js中实现回调的两种方式 示例一:使用普通回调函数实现异步流程控制 示例二:使用Promise对象实现异步流程控制 1. 什么是回调函数 回调函数是指将一个函数作为参数传递给另一个函数,并且这个参数函数将在另一个函数完成后被调用执行的过程。回调函数是实现…

    node js 2023年6月8日
    00
  • Nest.js中使用HTTP五种数据传输方式小结

    下面我将为你详细讲解“Nest.js中使用HTTP五种数据传输方式小结”的完整攻略。本文将介绍Nest.js中常用的五种HTTP数据传输方式,即GET、POST、PUT、DELETE和PATCH。 1. GET 在Nest.js中使用GET方式,可以通过@Get()注解实现。例如,以下代码演示了如何使用GET方法获取“/hello”路由的数据: @Get(‘…

    node js 2023年6月8日
    00
  • node.js使用express-fileupload中间件实现文件上传

    使用 Express 和 Express-fileupload 中间件可以轻松实现基于 Node.js 的文件上传功能。下面是一个详细的攻略。 使用Express-fileupload中间件实现文件上传 步骤一:安装Express和Express-fileupload 在开始使用Express-fileupload中间件之前,需要安装 Express 框架和…

    node js 2023年6月8日
    00
  • ES6新特性:使用export和import实现模块化详解

    下面我将为你详细讲解如何使用 export 和 import 实现 JavaScript 模块化。首先,我们需要了解 ES6 新特性中的模块化规范。 ES6 新特性:模块化规范 ES6 引入了一种新的模块化规范,不再依赖于传统的全局命名空间,而是将功能划分为一个个独立的模块,通过 export 导出模块中的功能,通过 import 引入其他模块的功能。这样可…

    node js 2023年6月8日
    00
  • Angular 13+开发模式慢的原因及构建性能优化解析

    Angular 13+是一款流行的前端开发框架,但在使用过程中,我们可能会遇到页面加载速度慢甚至影响用户体验的问题。本文将介绍Angular 13+调试和优化开发模式的方法,以及如何进行构建性能优化。 1. 开发模式慢的原因 在开发模式下,Angular 13+的开发过程可能会很慢,主要原因是Angular编译器需要在每次修改代码后重新编译显示效果。另外,一…

    node js 2023年6月9日
    00
  • 理解Koa2中的async&await的用法

    首先我们需要明确几个概念: async:用来声明异步函数,在函数前面加上async关键字,表示函数里面可能会有异步操作。 await:用于等待异步任务执行完成,常用于等待异步函数的结果,会暂停代码执行直到异步任务完成。 在Koa2中,我们常用async和await来处理异步代码,下面我们来详细讲解它们的用法。 一、async 在Koa2中使用async关键字…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部