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实现一个聊天室功能

    一、Node.js实现聊天室功能的攻略 Node.js可以帮助我们快速搭建一个聊天室的功能,以下是完成这个过程的步骤。 创建一个Node.js项目并初始化 首先,需要在你的电脑上安装 Node.js,然后我们可以在控制台中输入下列命令创建项目。 mkdir node-chatroom cd node-chatroom npm init -y 安装和配置web…

    node js 2023年6月8日
    00
  • zTree 树插件实现全国五级地区点击后加载的示例

    下面我来详细讲解一下“zTree 树插件实现全国五级地区点击后加载的示例”的完整攻略。 1. 安装 zTree 插件 要实现该示例,首先需要安装 zTree 插件。可以在 zTree 的官网上下载最新的版本,也可以直接引用在线的CDN资源。这里我以引用在线CDN资源的方式来进行示例说明。 <!– 引入 zTree 树插件的 css 文件 –>…

    node js 2023年6月8日
    00
  • 利用C/C++编写node.js原生模块的方法教程

    以下是关于“利用C/C++编写node.js原生模块的方法教程”的完整攻略: 什么是Node.js原生模块? Node.js 是一个流行的 JavaScript 运行时环境,允许开发人员使用 JavaScript 编写服务器端应用程序。Node.js 有一个重要的标准模块库,包括文件系统、HTTP 等基本的模块。此外,Node.js还允许开发人员编写自己的模…

    node js 2023年6月8日
    00
  • Javascript核心读书有感之词法结构

    Javascript核心读书有感之词法结构 本攻略旨在讲解《Javascript核心读书有感之词法结构》这本书,帮助读者学习Javascript词法结构的知识点。 什么是词法结构 Javascript的词法结构是指程序代码的表达形式,包括变量、函数、操作符、语句等。Javascript的词法结构定义了程序代码的合法的解析形式,决定了程序是否有效。 变量 变量…

    node js 2023年6月8日
    00
  • Node.js 中判断一个文件是否存在

    要判断一个文件是否存在,可以使用 Node.js 内置的模块 fs 中的文件系统方法 fs.existsSync()。具体步骤如下: 1. 引入 fs 模块 const fs = require(‘fs’); 2. 使用fs.existsSync()方法来判断文件是否存在,如下: const path = ‘somefile.txt’; if (fs.exi…

    node js 2023年6月8日
    00
  • Node.js服务器环境下使用Mock.js拦截AJAX请求的教程

    以下是详细讲解“Node.js服务器环境下使用Mock.js拦截AJAX请求的教程”的完整攻略。 什么是Mock.js? Mock.js是一个生成随机数据的库,可以用于模拟数据接口以方便前端开发测试及数据 mock。Mock.js支持随机生成文本、数字、日期、布尔、数组、对象等数据类型,而且可以根据模板生成指定数据。Mock.js还提供了api,能够与 ax…

    node js 2023年6月8日
    00
  • 解析Vue 2.5的Diff算法

    解析Vue 2.5的Diff算法完整攻略 简介 当我们在页面上创建或修改Vue实例时,Vue会把虚拟DOM和真实DOM作比较,来决定是否需要重新渲染页面。 Vue的Diff算法核心思想是该算法在一次比较中同层级只进行相同类型节点的比较。 Diff算法的具体实现 Vue的Diff算法是一个深度优先遍历的算法,当产生了更新时,它会比较新旧节点,并对差异进行打标记…

    node js 2023年6月8日
    00
  • nodejs require js文件入口,在package.json中指定默认入口main方法

    当我们需要在我们的程序中使用某些 js 文件时,我们可以通过 node.js 提供的 require 函数来实现。当我们需要在某个模块的 js 文件中引入其他模块时,可以通过指定 js 文件入口的方式来实现。而在 node.js 中,可以在 package.json 文件中指定默认的入口文件。 具体实现步骤如下: 1.编写需要被引入的 js 文件,例如 te…

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