Vue 3 迁移策略笔记—— 第3节:Attribute Coercion Behavior (属性强制行为)
前言本笔记主要基于官方文档《迁移策略——attribute 强制行为》汇总而来。如有理解出入,请以官方文档为主。知识储备:HTML 属性内容属性与IDL属性的区别布尔属性与枚举属性的区别如果对上面知识点不了解,可先查看一下文章做初步了解:《IDL 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?》《MDN: Web 开发技术>HTML(超文本标记语言)>HTML 属性参考》当然,本笔
前言
本笔记主要基于官方文档《迁移策略——attribute 强制行为》汇总而来。如有理解出入,请以官方文档为主。建议您以官方文档为主,本文为辅。这样您可以“以自己为主”审视的阅读,从而不被我的观点带偏。
知识储备:
- HTML 属性
- 内容属性与IDL属性的区别
- 布尔属性与枚举属性的区别
如果对上面知识点不了解,可先查看一下文章做初步了解:
当然,本笔记做了初步说明。
概述
- 删除枚举属性的内部概念,并将枚举属性视为普通的非布尔属性
- 如果属性的绑定值为
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 等等。
需要注意的是有些枚举属性只接受两个枚举值: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 更多详细知识,可查看:
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>
本系列目录
更多推荐
所有评论(0)