上一篇文章我们知道了指令的实现原理,接下来我们来研究下Vue提供的一些默认指令的实现原理。

v-text

使用案例
<div v-text="'value'"
实现逻辑
  • 先来看下render函数
const _hoisted_1 = ["textContent"]function render(_ctx, _cache) {with (_ctx) {const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vuereturn (_openBlock(), _createElementBlock("div", {textContent: _toDisplayString('value')}, null, 8 /* PROPS */, _hoisted_1))}
}
})

在创建VNode的时候传递了一个textContentpro

export function patchDOMProp(el: any,key: string,value: any,prevChildren: any,parentComponent: any,parentSuspense: any,unmountChildren: any
) {if (key === 'innerHTML' || key === 'textContent') {// 如果`textContent`直接更新元素的textContentel[key] = value == null ? '' : valuereturn}
}

这个pro直接被用来作为元素的textContent。

总结

v-text设置元素的textContent

v-html

我们通过上面的代码,估计你看到innerHTML应该就理解了v-html的实现逻辑。v-html是渲染函数生成VNode的时候传了一个innerHTMLpro, 这个pro直接被用来作为元素的 innerHTML

  • 验证下确实如此
const _hoisted_1 = ["innerHTML"]function render(_ctx, _cache) {with (_ctx) {const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vuereturn (_openBlock(), _createElementBlock("div", { innerHTML: 'value' }, null, 8 /* PROPS */, _hoisted_1))}
}
总结

v-html设置元素的innerHTML

v-show

使用案例
<div v-show="true">div元素</div>
实现逻辑
  • 先来看下render函数
function render(_ctx, _cache) {with (_ctx) {const { vShow: _vShow, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vuereturn _withDirectives((_openBlock(), _createElementBlock("div", null, "div元素", 512 /* NEED_PATCH */)), [[_vShow, false]])}
}

v-show实现逻辑:绑定了vShow指令在元素上

  • 我们来看下v-show这个内部指令
interface VShowElement extends HTMLElement {// _vod = vue original display_vod: string
}export const vShow: ObjectDirective<VShowElement> = {beforeMount(el, { value }, { transition }) {el._vod = el.style.display === 'none' ? '' : el.style.displaysetDisplay(el, value)},updated(el, { value, oldValue }, { transition }) {setDisplay(el, value)},beforeUnmount(el, { value }) {setDisplay(el, value)}}function setDisplay(el: VShowElement, value: unknown): void {el.style.display = value ? el._vod : 'none'
}

v-show在内部就是切换元素的style.display。如果传入的值为false就将style.display设置为none不显示,如果传入的值为true,则是元素原本设置style.display值。

总结

v-show控制元素的style.display来切换显示和隐藏。

v-if && v-else-if && v-else

使用案例
<!-- 数据 -->
let condition = ref(1);<!-- 模板 -->
<div v-if="condition == 1">状态1</div>
<div v-else-if="condition == 2">状态2</div>
<div v-else>其他状态</div>
实现逻辑
  • 来看下render函数
const _hoisted_1 = { key: 0 }
const _hoisted_2 = { key: 1 }
const _hoisted_3 = { key: 2 }function render(_ctx, _cache) {with (_ctx) {const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vuereturn (condition == 1)? (_openBlock(), _createElementBlock("div", _hoisted_1, "状态1")): (condition == 2)? (_openBlock(), _createElementBlock("div", _hoisted_2, "状态2")): (_openBlock(), _createElementBlock("div", _hoisted_3, "其他状态"))}
}

v-if && v-else-if && v-else实现逻辑:直接进行表达式的判断,然后不同的表达式渲染不同的DOM元素。

重要知识点

问题:v-if && v-else-if && v-else切换时会进行元素复用吗?

答案:不会。因为不同的元素赋予了不同的key, const _hoisted_1 = { key: 0 } const _hoisted_2 = { key: 1 } const _hoisted_3 = { key: 2 } 这样切换条件,会直接卸载旧的元素节点,挂载新的元素节点,不会进行复用。

v-for

使用案例
let items = [{id: 1,name: "张三"
},
{   id:2, name: "李四"
}];<div v-for="(item, index) in items" :key="item.id">{{ item.name }}</div>
实现逻辑
  • 来看下render函数
function render(_ctx, _cache) {with (_ctx) {const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString } = _Vuereturn (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item, index) => {return (_openBlock(), _createElementBlock("div", { key: item.id }, _toDisplayString(item.name), 1 /* TEXT */))}), 128 /* KEYED_FRAGMENT */))}
}

渲染结果是Fragment中包含了每个Item对应的Element

重要知识点

问题:v-for 的遍历的数据只能是数组吗?

答案:不是

  1. 如果是数组,则遍历的是数组的每个元素;
  2. 如果是字符串,则遍历的是字符串的每个字符;
  3. 如果是数字,则遍历的是从 0 到 数据对应的那个值;
  4. 如果是实现了可迭代协议的数据,则是迭代遍历到的所有值;
  5. 如果是对象,则遍历的所有的key锁对应的值;

问题:v-ifv-for同时使用,会有优先使用哪个指令?

<div v-if="items.length > 0" v-for="(item, index) in items" :key="item.id">{{ item.name }}</div>
function render(_ctx, _cache) {with (_ctx) {const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createCommentVNode: _createCommentVNode } = _Vuereturn (items.length > 0)? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(items, (item, index) => {return (_openBlock(), _createElementBlock("div", { key: item.id }, _toDisplayString(item.name), 1 /* TEXT */))}), 128 /* KEYED_FRAGMENT */)): _createCommentVNode("v-if", true)}
}

答案:优先判断v-if指令,如果条件成立,才会进行v-for遍历生成数组元素节点。

其他

还有一些其他常用的指令,例如v-model进行双向绑定,v-on进行事件绑定,v-slot进行插槽的设置。这几个指令由于相对复杂,我们将每个使用一个章节来介绍。本章节就到此为止。

Vue常用的内置指令的底层细节分析相关推荐

  1. 【Vue2.0】—常用的内置指令(九)

    [Vue2.0]-常用的内置指令(九) <body><div id="root"><h1 v-pre>好好学习</h1><h1 ...

  2. Vue.js实战——内置指令(二)

    参考<Vue.js实战>梁灏 Vue内置指令第一部分:Vue.js实战--内置指令(一) 1 方法与事件 1.1 基本用法 直接上代码,这样最实在: <!DOCTYPE html&g ...

  3. Vue复习知识点(理解MVVM模式、Vue实例配置的各选项、Vue的各种内置指令....)

    Vue复习知识点 一.理解MVVM模式 VVM是一种设计模式,它将应用程序分为三个部分:模型(Model).视图(View)和视图模型(ViewModel).它的主要目的是将应用程序的界面逻辑与业务逻 ...

  4. Vue中常用的内置指令及自定义指令

    内置指令 v-bind [单向数据绑定] [格式:v-bind:属性名="data中定义的属性"] [简写::属性名="data中定义的属性"] <div ...

  5. Vue.js实战——内置指令(一)

    参考:<Vue.js实战>梁灏 1. 基本指令 1.1 v-cloak <!DOCTYPE html> <html><head><meta cha ...

  6. Vue.js 学习笔记 第5章 内置指令

    本篇目录: 5.1 基本指令 5.2 条件渲染指令 5.3 列表渲染指令 v-for 5.4 方法与事件 5.5 实战:利用计算属性.指令等知识开发购物车 回顾一下第2.2节,我们己经介绍过指令(Di ...

  7. Vue.js 内置指令

    回顾一下第2.2节,我们己经介绍过指令(Directive)的概念了,Vue.js的指令是带有特殊前缀v-的HTML特性,它绑定一个表达式,并将一些特性应用到DOM上. 其实我们已经用到过很多Vue内 ...

  8. Vue 基础之常用内置指令

    Vue 基础之常用内置指令 描述 指令 内容渲染指令 {{}} 与 v-text 覆盖面积 v-text {{}} 闪现问题 {{}} v-text v-html 属性绑定指令 v-bind 简写 : ...

  9. Vue(二)——常用内置指令

    前言 Vue指令是带有v-前缀的特殊属性,它们作用于HTML元素,表示它们是Vue提供的特殊属性.将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为. 常用的Vue.js内置指令: v-i ...

最新文章

  1. 每日一皮:初看不识画什么,再看已是神之手 ...
  2. How draw a stem -and -leaf amp; box-plot display by R.or Python
  3. r指引到文件夹_R语言中进行文件夹及文件夹内文件操作范例
  4. 使用IDA Pro动态调试SO文件
  5. Application.Goto 方法
  6. mysql注解实体类_jpa实体类生成mysql表及字段注解
  7. [转]基于SQL Server 2008 Service Broker构建企业级消息系统
  8. Cookie、Session、Token
  9. bzoj 3232: 圈地游戏【分数规划+最小割】
  10. python 网页设计_使用Python制作获取网站目录的图形化程序
  11. [菜鸟自学过程] ASP.NET2.0 ClientCallback脚本回调
  12. html如何修改字体黑体,css如何设置黑体样式?
  13. 4_蒙特卡罗算法求圆周率PI
  14. 如何激活win10系统?小白们无需到处问东问西了!
  15. 应用程序无法正常启动(0xc00007b)
  16. 哒螨灵使用注意事项_常用杀虫剂-哒螨灵使用方法
  17. 使用 Learner Lab - 学生
  18. nexmo - 当晚售前打电话
  19. pytest学习:setup、teardown、setup_class、teardown_class的区别
  20. 成都榆熙:拼多多商家如何批量设置产品属性值?

热门文章

  1. Spring Boot 使用 HikariCP 连接池配置详解
  2. 原理这就是索引下推呀
  3. c语言怎样写积分程序,C语言实现定积分求解方法
  4. 一些需要用到的latex语句
  5. AWS - Amazon Simple Email(ASE) 邮件服务
  6. Revit二次开发环境搭建(Revit 2019+Visual Studio 2017)
  7. 你是否有疑问,软件是如何驱动硬件,代码又是如何对计算机进行控制的呢?
  8. 什么是 Android Jetpack?
  9. 低代码平台开发 python_【低筋面粉】低筋面粉的功效_低筋面粉图片_食材百科_美食杰...
  10. 清华应届程序员同时被5家公司录取,晒出工资,网友:羡慕