属性强制行为)"/>
Vue 3 迁移策略笔记—— 第3节:Attribute Coercion Behavior (属性强制行为)
前言
本笔记主要基于官方文档《迁移策略——attribute 强制行为》汇总而来。如有理解出入,请以官方文档为主。建议您以官方文档为主,本文为辅。这样您可以“以自己为主”审视的阅读,从而不被我的观点带偏。
知识储备:
- HTML 属性
- 内容属性与IDL属性的区别
- 布尔属性与枚举属性的区别
如果对上面知识点不了解,可先查看一下文章做初步了解:
- 《IDL 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?》
- 《MDN: Web 开发技术>HTML(超文本标记语言)>HTML 属性参考》
当然,本笔记做了初步说明。
概述
- 删除枚举属性的内部概念,并将枚举属性视为普通的非布尔属性
- 如果属性的绑定值为
false
,Vue 将不再删除该属性。相反的,布尔值false
将被转换成字符串'false'
赋给属性。在 Vue 3.x 中,如果要删除一个属性,需要通过null
、undefined
来进行显式删除。(本条变化,好像适用于布尔属性和枚举属性)
Tip:
这是一个低级别的内部更改,对一般正常开发的影响不大。
布尔属性、枚举属性
在深入理解这些变动前,需要先知道什么是布尔属性、枚举属性及其他相关的知识点。
学习 html
相关知识的时候,我们都知道标签有着许许多多的属性。其实呢!这些属性还做了进一步的分类。常见的有:
- 布尔属性(如:
required
); - 枚举属性(如:
input
标签的type
);
布尔属性
布尔属性有个特点:当声明了这个属性时,其值为 true;而未声明时,其值为 false。
HTML5 定义了布尔值属性允许的取值:如果属性存在,其值必须是一个空字符串(即该属性的值未分配),或者是一个大小写无关的 ASCII 字符串,该字符串与属性名严格相同,前后都没有空格。
——摘自《MDN: Web 开发技术>HTML(超文本标记语言)>HTML 属性参考>布尔值属性》
<div itemscope> This is valid HTML but invalid XML. </div>
<div itemscope=itemscope> This is also valid HTML but invalid XML. </div>
<div itemscope=""> This is valid HTML and also valid XML. </div>
<div itemscope="itemscope"> This is also valid HTML and XML, but perhaps a bit verbose. </div>
上面四种写法是等效的。所以,布尔值属性不能取值为 “true
” 和 “false
”。如果需要表示 false 值,布尔值属性需要整个忽略不写。
枚举属性
枚举属性,顾名思义,就是取值是一个由若干关键词组成的枚举集合。例如 input 元素的 autocomplete 属性,这个属性可取值为 username、email、country、tel、url 等等。
——摘自《IDL 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?》
需要注意的是有些枚举属性只接受两个枚举值:true
和false
。而且,空字符串 或者 不给属性赋值 都等于true
。
下面写法都代表true
<div contenteditable>An editable item</div>
<div contenteditable="">An editable item</div>
<div contenteditable="true">An editable item</div>
下面写法都代表false
<div contenteditable="false">An editable item</div>
<div contenteditable="abcdefg">An editable item</div>
<div>An editable item</div>
其他属性
除开上面两种属性分类,其余的属性可以归类于常规属性了。
内容属性 和 IDL(接口描述语言)属性:
HTML 中,属性还有 内容属性 和 IDL属性 说法。注意,这两种属性,并不是对标签属性的划分。他们只是属性不同地方的不同描述和写法而已。
内容属性 接收的值都是字符串。编写 HTML 时,直接写在标签中的就是内容属性。此外,内容属性还可以通过 JS 的
setAttribute()
来设置。<div contenteditable>An editable item</div>
input.setAttribute('type', 'text'); input.getAttribute('type');
而 IDL属性 是一个 JavaScript 属性(property),是 DOM 提供给 JS 的真正属性。通过
.
运算符来设置,且只接收正确类型的值。如果接收值的类型不正确,会自动转化成正确的类型。input.type = 'password';
关于 HTML 更多详细知识,可查看:
- 《IDL 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?》
- 《MDN: Web 开发技术>HTML(超文本标记语言)>HTML 属性参考》
vue 2.x 对v-bind
属性的处理
- 对于某些属性/元素对,Vue 采用 IDL 属性 形式处理:如
value
of<input>
,<select>
,<progress>
, etc . - 对于 布尔值属性 和 xlinks,Vue 通过判断 是否是
falsy
(undefined
、null
、false
)值来决定添加或是删除属性。 - 对于 枚举属性, Vue 强制转化为字符串。
- 对于其他(普通非布尔)属性,如果传递过来的值是
falsy
值则删除,否则直接添加
以下是官方给出的普通非布尔属性和枚举属性的结果对照例子:
v-bind 表达式 | 普通非布尔属性:foo | 枚举属性:draggable |
---|---|---|
:attr="null" | / | draggable="false" |
:attr="undefined" | / | / |
:attr="true" | foo="true" | draggable="true" |
:attr="false" | / | draggable="false" |
:attr="0" | foo="0" | draggable="true" |
attr="" | foo="" | draggable="true" |
attr="foo" | foo="foo" | draggable="true" |
attr | foo="" | draggable="true" |
从上面的对照表可以看出,两者的表现是不一致。这样会造成使用时的不便。
Vue 3.x 对 v-bind
属性的处理
在 Vue 3.x 中移除了枚举属性的概念,统一将他们视为普通非布尔属性。这样做的好处:
- 消除了普通非布尔属性和枚举属性表现形式的不一致(换而言之,在 Vue 3.x 中,只存在非布尔属性和布尔属性)
- 意味着可以对 枚举属性 使用除
true
和false
以外的值,甚至是未使用的关键字。
此外,对于非布尔属性,如果传递的值是false
,Vue 将不再会删除属性了,而是强制转化为字符串'false'
。
上面那张表格,在 Vue 3.x 中的表现则变成:
v-bind 表达式 | 普通非布尔属性:foo | 枚举属性:draggable |
---|---|---|
:attr="null" | / | / |
:attr="undefined" | / | / |
:attr="true" | foo="true" | draggable="true" |
:attr="false" | foo="false" | draggable="false" |
:attr="0" | foo="0" | draggable="0" |
attr="" | foo="" | draggable="" |
attr="foo" | foo="foo" | draggable="foo" |
attr | foo="" | draggable="" |
可以看到,普通非布尔属性 和 枚举属性 结果是一致的。
删除属性
对于 非布尔属性,false
被强制转化为'false'
,不再删除属性。所以,在 Vue 3.x 中,应该使用undefined
和null
来显式删除属性。
注意,布尔属性 表现并改变,和 Vue 2.x 保持一致。
Attribute | v-bind value 2.x | v-bind value 3.x | HTML output |
---|---|---|---|
Vue 2.x 中的枚举属性,如: contenteditable , draggable and spellcheck . | undefined , false | undefined , null | removed |
true , 'true' , '' , 1 , 'foo' | true , 'true' | "true" | |
null , 'false' | false , 'false' | "false" | |
Vue 2.x 中的普通非布尔属性,如:aria-checked , tabindex , alt , etc. | undefined , null , false | undefined , null | removed |
'false' | false , 'false' | "false" | |
布尔属性:required 、disabled 、readonly | false 、null 、undefined | false 、null 、undefined | removed |
实际代码测试
可以在 Vue 3.x 项目中执行下面代码,然后到浏览器控制台看实际代码渲染的结果。
<div style="width: 500px">非枚举非布尔属性:true:<input type="text" :foo="true" />非枚举非布尔属性:false:<input type="text" :foo="false" />非枚举非布尔属性:undefined:<input type="text" :foo="undefined" />非枚举非布尔属性:null:<input type="text" :foo="null" />非枚举非布尔属性:0:<input type="text" :foo="0" /><hr />枚举属性:true:<input type="text" :spellcheck="true" />枚举属性:false:<input type="text" :spellcheck="false" />枚举属性:undefined:<input type="text" :spellcheck="undefined" />枚举属性:null:<input type="text" :spellcheck="null" />枚举属性:0:<input type="text" :spellcheck="0" /><hr />布尔属性required:true:<input type="text" :required="true" />布尔属性required:false:<input type="text" :required="false" />布尔属性required:undefined:<input type="text" :required="undefined" />布尔属性required:null:<input type="text" :required="null" />布尔属性required:0:<input type="text" :required="0" />
</div>
本系列目录
-
Vue 3 迁移策略笔记—— 第1节:v-for 中的 Ref 数组
-
Vue 3 迁移策略笔记—— 第2节:Async Components 异步组件
-
Vue 3 迁移策略笔记—— 第3节:Attribute Coercion Behavior (属性强制行为)
-
Vue 3 迁移策略笔记——第4节:$attrs 包括class&style
-
Vue 3 迁移策略笔记—— 第5节:移除 $children
-
Vue 3 迁移策略笔记—— 第6节:自定义指令
-
Vue 3 迁移策略笔记—— 第7节:自定义元素交互
-
Vue 3 迁移策略笔记—— 第8节:Data 选项
-
Vue 3 迁移策略笔记—— 第9节:新增 emits 选项
-
Vue 3 迁移策略笔记—— 第10节:事件 API
-
Vue 3 迁移策略笔记—— 第11节:移除过滤器
-
Vue 3 迁移策略笔记—— 第12节:片段
-
Vue 3 迁移策略笔记—— 第13节:函数式组件
-
Vue 3 迁移策略笔记—— 第14节:全局 API
-
Vue 3 迁移策略笔记—— 第15节:全局 API 的 tree shaking
-
Vue 3 迁移策略笔记—— 第16节:Inline Template 属性
-
Vue 3 迁移策略笔记—— 第17节:Key 属性
-
Vue 3 迁移策略笔记—— 第18节:按键修饰符
-
Vue 3 迁移策略笔记—— 第19节:移除 $listeners
-
Vue 3 迁移策略笔记—— 第20节:Props 的默认值函数不能访问this
-
Vue 3 迁移策略笔记—— 第21节:渲染函数 API
-
Vue 3 迁移策略笔记—— 第22节:Slots 的统一
-
Vue 3 迁移策略笔记—— 第23节:Transition Class 的变化
-
Vue 3 迁移策略笔记—— 第24节:Transition Group 不再需要设置根元素
-
Vue 3 迁移策略笔记—— 第25节:v-on.native修饰符被移除
-
Vue 3 迁移策略笔记—— 第26节:在组件上使用 v-model 的变化
-
Vue 3 迁移策略笔记—— 第27节:v-if 和 v-for 的优先级
-
Vue 3 迁移策略笔记—— 第28节:v-bind 合并行为
-
Vue 3 迁移策略笔记—— 第29节:数组的监听
更多推荐
Vue 3 迁移策略笔记—— 第3节:Attribute Coercion Behavior (属性强制行为)
发布评论