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

yizhihongxing

这里为你详细讲解“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日

相关文章

  • 详解vue axios中文文档

    详解vue axios中文文档的完整攻略 简介 Vue.js 是一款流行的前端框架,而 axios 是 Vue.js 常用的 HTTP 请求库。许多 Web 开发者喜欢使用 axios 进行数据请求,因为 axios 能够简化这一过程并提供更好的错误处理和调试支持。 虽然 axios 可以随意地在 Vue 组件中使用,但对于初学者来说,文档可能会有些晦涩难懂…

    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
  • 基于Nuxt.js项目的服务端性能优化与错误检测(容错处理)

    下面我会详细讲解“基于Nuxt.js项目的服务端性能优化与错误检测(容错处理)”的完整攻略。 1. 为什么要进行服务端性能优化与错误检测 在一个网站或应用的开发中,服务端的性能和稳定性都是非常重要的因素。特别是在高并发的情况下,服务端的性能问题和错误处理能力的不足,往往会导致用户体验不佳,甚至会对业务造成较大的影响。 基于Nuxt.js的项目,作为一个基于V…

    node js 2023年6月8日
    00
  • 基于vue实现微博三方登录流程解析

    基于Vue实现微博三方登录流程解析 简介 本篇攻略旨在讲解如何在Vue项目中集成微博三方登录功能,这将涉及到与微博开放平台的授权交互过程。本文所讲解的示例基于Vue.js 2.0框架及axios插件。 准备工作 在开始之前,需要先准备好以下工作: 微博开发者账号及应用信息(包括App Key、App Secret、回调地址等) Vue项目基础结构 安装axi…

    node js 2023年6月8日
    00
  • typescript在node.js下使用别名(paths)无效的问题详解

    我来给您讲解一下。 问题现象 在使用Typescript编写Node.js应用程序时,我们有时会使用到Webpack或者tsconfig.json的paths字段设置路径别名,但是在实际使用中会出现别名无法生效的问题。这是因为Node.js默认不支持paths别名设置。 解决方案 解决这个问题的方法有两种: 方案一:使用Babel插件 我们可以使用Babel…

    node js 2023年6月8日
    00
  • JS与SQL方式随机生成高强度密码示例

    生成高强度密码是一个非常常见的需求。本文将详细讲解如何通过JS与SQL方式随机生成高强度密码。 准备工作 在开始生成密码之前,您需要准备以下工作: 安装node.js和MySQL服务,并且已经学习了如何在node.js中进行MySQL的操作。 有一定的JavaScript编程基础。 实现思路 我们将生成高强度密码的过程分为以下3步: 定义密码长度和由哪些字符…

    node js 2023年6月8日
    00
  • nodejs文件操作模块FS(File System)常用函数简明总结

    下面是关于Node.js文件操作模块FS常用函数的简明总结攻略。 FS模块 Node.js中的File System模块,简称FS模块,提供了完整的文件系统访问功能,包括文件读取、创建等常用操作。在使用FS模块时需要先引入: const fs = require(‘fs’); 常用函数 下面我们来看几个常用函数。 fs.writeFile fs.writeF…

    node js 2023年6月8日
    00
  • 详解AngularJS脏检查机制及$timeout的妙用

    详解AngularJS脏检查机制及$timeout的妙用 AngularJS脏检查机制 AngularJS是一款前端JavaScript框架,其最重要的特性之一是脏检查机制,也就是$digest机制。$digest机制可以帮助我们实时监测$scope对象中数据的变化并进行更新。当调用$digest()方法时,AngularJS会检查当前页面上所有的$scop…

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