Vue常用的内置指令的底层细节分析
上一篇文章我们知道了指令的实现原理,接下来我们来研究下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的时候传递了一个
textContent
的pro
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的时候传了一个innerHTML
的pro
, 这个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
的遍历的数据只能是数组吗?
答案:不是
- 如果是数组,则遍历的是数组的每个元素;
- 如果是字符串,则遍历的是字符串的每个字符;
- 如果是数字,则遍历的是从 0 到 数据对应的那个值;
- 如果是实现了可迭代协议的数据,则是迭代遍历到的所有值;
- 如果是对象,则遍历的所有的key锁对应的值;
问题:
v-if
和v-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常用的内置指令的底层细节分析相关推荐
- 【Vue2.0】—常用的内置指令(九)
[Vue2.0]-常用的内置指令(九) <body><div id="root"><h1 v-pre>好好学习</h1><h1 ...
- Vue.js实战——内置指令(二)
参考<Vue.js实战>梁灏 Vue内置指令第一部分:Vue.js实战--内置指令(一) 1 方法与事件 1.1 基本用法 直接上代码,这样最实在: <!DOCTYPE html&g ...
- Vue复习知识点(理解MVVM模式、Vue实例配置的各选项、Vue的各种内置指令....)
Vue复习知识点 一.理解MVVM模式 VVM是一种设计模式,它将应用程序分为三个部分:模型(Model).视图(View)和视图模型(ViewModel).它的主要目的是将应用程序的界面逻辑与业务逻 ...
- Vue中常用的内置指令及自定义指令
内置指令 v-bind [单向数据绑定] [格式:v-bind:属性名="data中定义的属性"] [简写::属性名="data中定义的属性"] <div ...
- Vue.js实战——内置指令(一)
参考:<Vue.js实战>梁灏 1. 基本指令 1.1 v-cloak <!DOCTYPE html> <html><head><meta cha ...
- Vue.js 学习笔记 第5章 内置指令
本篇目录: 5.1 基本指令 5.2 条件渲染指令 5.3 列表渲染指令 v-for 5.4 方法与事件 5.5 实战:利用计算属性.指令等知识开发购物车 回顾一下第2.2节,我们己经介绍过指令(Di ...
- Vue.js 内置指令
回顾一下第2.2节,我们己经介绍过指令(Directive)的概念了,Vue.js的指令是带有特殊前缀v-的HTML特性,它绑定一个表达式,并将一些特性应用到DOM上. 其实我们已经用到过很多Vue内 ...
- Vue 基础之常用内置指令
Vue 基础之常用内置指令 描述 指令 内容渲染指令 {{}} 与 v-text 覆盖面积 v-text {{}} 闪现问题 {{}} v-text v-html 属性绑定指令 v-bind 简写 : ...
- Vue(二)——常用内置指令
前言 Vue指令是带有v-前缀的特殊属性,它们作用于HTML元素,表示它们是Vue提供的特殊属性.将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为. 常用的Vue.js内置指令: v-i ...
最新文章
- 每日一皮:初看不识画什么,再看已是神之手 ...
- How draw a stem -and -leaf amp; box-plot display by R.or Python
- r指引到文件夹_R语言中进行文件夹及文件夹内文件操作范例
- 使用IDA Pro动态调试SO文件
- Application.Goto 方法
- mysql注解实体类_jpa实体类生成mysql表及字段注解
- [转]基于SQL Server 2008 Service Broker构建企业级消息系统
- Cookie、Session、Token
- bzoj 3232: 圈地游戏【分数规划+最小割】
- python 网页设计_使用Python制作获取网站目录的图形化程序
- [菜鸟自学过程] ASP.NET2.0 ClientCallback脚本回调
- html如何修改字体黑体,css如何设置黑体样式?
- 4_蒙特卡罗算法求圆周率PI
- 如何激活win10系统?小白们无需到处问东问西了!
- 应用程序无法正常启动(0xc00007b)
- 哒螨灵使用注意事项_常用杀虫剂-哒螨灵使用方法
- 使用 Learner Lab - 学生
- nexmo - 当晚售前打电话
- pytest学习:setup、teardown、setup_class、teardown_class的区别
- 成都榆熙:拼多多商家如何批量设置产品属性值?
热门文章
- Spring Boot 使用 HikariCP 连接池配置详解
- 原理这就是索引下推呀
- c语言怎样写积分程序,C语言实现定积分求解方法
- 一些需要用到的latex语句
- AWS - Amazon Simple Email(ASE) 邮件服务
- Revit二次开发环境搭建(Revit 2019+Visual Studio 2017)
- 你是否有疑问,软件是如何驱动硬件,代码又是如何对计算机进行控制的呢?
- 什么是 Android Jetpack?
- 低代码平台开发 python_【低筋面粉】低筋面粉的功效_低筋面粉图片_食材百科_美食杰...
- 清华应届程序员同时被5家公司录取,晒出工资,网友:羡慕