# attribute 强制行为
非兼容
信息
这是一个底层的内部 API 更改,绝大多数开发人员不会受到影响。
# 概览
以下是对变化的总体概述:
- 移除枚举 attribute 的内部概念,并将这些 attribute 视为普通的非布尔 attribute
- 非兼容:如果值为布尔值
false
,则不再移除 attribute。取而代之的是,它将被设置为 attr="false"。若要移除 attribute,应该使用null
或者undefined
。
如需更深入的解释,请继续阅读!
# 2.x 语法
在 2.x,我们有以下策略来强制 v-bind
的值:
对于某些 attribute/元素对,Vue 始终使用相应的 IDL attribute (property):比如
<input>
,<select>
,<progress>
中的value
,等等 (opens new window)。对于“布尔 attribute (opens new window)”和 xlinks (opens new window),如果它们是
falsy
(undefined
,null
或false
(opens new window)) 的,Vue 会移除它们,否则会加上。(见这里 (opens new window)和这里 (opens new window))。对于“枚举 attribute (opens new window)” (目前来说包括
contenteditable
、draggable
和spellcheck
),Vue 会尝试将它们强制 (opens new window)转换为字符串 (目前对contenteditable
做了特殊处理,以修复 vuejs/vue#9397 (opens new window))。对于其他 attribute,我们将移除
falsy
的值 (undefined
,null
,或false
),其他值按原样设置 (见这里 (opens new window))。
下表描述了 Vue 如何强制转换“枚举 attribute”,以及与普通非布尔 attribute 的不同之处:
绑定表达式 | 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" |
从上表可以看出,当前实现将 true
强制转换为了 'true'
,但如果 attribute 为 false
,则将其移除。这也导致了不一致性,并要求用户在非常常见的用例中手动将布尔值强制转换为字符串,例如
aria-*
attribute,例如 aria-selected
、aria-hidden
等等。
# 3.x 语法
我们打算放弃“枚举型 attribute”的内部概念,并将它们视为普通的非布尔型 HTML attribute。
- 这就解决了普通非布尔型 attribute 和“枚举型 attribute”之间的不一致性问题
- 这个改动还使得对于诸如
contenteditable
这样的 attribute,我们可以使用'true'
和'false'
以外的值,甚至是未来新增的关键字。
对于非布尔型 attribute,如果其值为 false
,Vue 将不再移除它们,而是将其强制转换为 'false'
。
- 这就解决了
true
和false
之间的不一致性,并更易于输出aria-*
attribute
下表描述了新的行为:
绑定表达式 | 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="" * |
*:已改变
布尔型 attribute 的强制转换保持不变。
# 迁移策略
# 枚举 attribute
枚举 attribute 如果不存在,可能会和 attr="false"
会产生不同的 IDL attribute 值 (将反映实际状态),描述如下:
不存在的枚举 attr | IDL attr & 值 |
---|---|
contenteditable | contentEditable → 'inherit' |
draggable | draggable → false |
spellcheck | spellcheck → true |
对于“枚举 attribute”,由于我们不再把 null
转换为 'false'
,在 3.x 中,对于 contenteditable
和 spellcheck
,开发者需要将原来解析为 null
的 v-bind
表达式变更为 false
或 'false'
才能保持和 2.x 中的行为一致。
在 2.x 中,枚举 attribute 的无效值将被强制转换为 'true'
。这通常是不符合预期的,所以该行为不太可能被大规模依赖。在 3.x 中,应显式指定 true
或 'true'
。
# 将 false
强制转换为 'false'
而不是移除 attribute
在 3.x 中,应该使用 null
或 undefined
以显式移除 attribute。
# 2.x 和 3.x 行为的比较
Attributes | v-bind 的值 2.x | v-bind 的值 3.x | HTML 输出 |
---|---|---|---|
2.x “枚举 attribute” 即 contenteditable 、draggable 与 spellcheck 。 | undefined | undefined , null | 被移除 |
true , 'true' , '' , 1 ,
'foo' | true , 'true' | "true" | |
null , false , 'false' | false , 'false' | "false" | |
其他非布尔 attribute 如 aria-checked 、tabindex 、alt 等等。 | undefined , null , false | undefined , null | 被移除 |
'false' | false , 'false' | "false" |
ATTR_FALSE_VALUE
ATTR_ENUMERATED_COERCION