前言

本笔记主要基于官方文档《迁移策略——attribute 强制行为》汇总而来。如有理解出入,请以官方文档为主。建议您以官方文档为主,本文为辅。这样您可以“以自己为主”审视的阅读,从而不被我的观点带偏。

知识储备:
  • HTML 属性
  • 内容属性与IDL属性的区别
  • 布尔属性与枚举属性的区别

如果对上面知识点不了解,可先查看一下文章做初步了解:

当然,本笔记做了初步说明。

概述

  • 删除枚举属性的内部概念,并将枚举属性视为普通的非布尔属性
  • 如果属性的绑定值为false,Vue 将不再删除该属性。相反的,布尔值false将被转换成字符串'false' 赋给属性。在 Vue 3.x 中,如果要删除一个属性,需要通过nullundefined来进行显式删除。(本条变化,好像适用于布尔属性和枚举属性)

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 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?

需要注意的是有些枚举属性只接受两个枚举值:truefalse。而且,空字符串 或者 不给属性赋值 都等于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(undefinednullfalse)值来决定添加或是删除属性。
  • 对于 枚举属性, 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"
attrfoo=""draggable="true"

从上面的对照表可以看出,两者的表现是不一致。这样会造成使用时的不便。

Vue 3.x 对 v-bind属性的处理

在 Vue 3.x 中移除了枚举属性的概念,统一将他们视为普通非布尔属性。这样做的好处:

  • 消除了普通非布尔属性枚举属性表现形式的不一致(换而言之,在 Vue 3.x 中,只存在非布尔属性布尔属性
  • 意味着可以对 枚举属性 使用除 truefalse 以外的值,甚至是未使用的关键字。

此外,对于非布尔属性,如果传递的值是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"
attrfoo=""draggable=""

可以看到,普通非布尔属性枚举属性 结果是一致的。

删除属性

对于 非布尔属性false 被强制转化为'false',不再删除属性。所以,在 Vue 3.x 中,应该使用undefinednull来显式删除属性。

注意,布尔属性 表现并改变,和 Vue 2.x 保持一致。

Attributev-bind value 2.xv-bind value 3.xHTML output
Vue 2.x 中的枚举属性,如: contenteditable, draggable and spellcheck.undefined, falseundefined, nullremoved
true, 'true', '', 1, 'foo'true, 'true'"true"
null, 'false'false, 'false'"false"
Vue 2.x 中的普通非布尔属性,如:aria-checked, tabindex, alt, etc.undefined, null, falseundefined, nullremoved
'false'false, 'false'"false"
布尔属性:requireddisabledreadonlyfalsenullundefinedfalsenullundefinedremoved

实际代码测试

可以在 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>

在这里插入图片描述


本系列目录

Logo

前往低代码交流专区

更多推荐