attribute强制行为
概览
- 废弃内置的
enumerated attributes的概念,将这些属性作为普通非布尔类型的attribute来处理。 - 如果属性值为false,则不再移除这个属性。而是设置为
attr='false'。想要移除属性时,需要设置为null或者undefined。
动机
在2.x版本,对于v-bind绑定的属性值我们采用的是以下策略:
- 对于attribute/element结对出现时,Vue使用相关的IDL attribute(property):类似
<input>,<select>,<progress>标签的value属性 - 对于布尔类型的attribute和xlinks,如果它们的值为
falsy(null || undefined || false)则会移除它们,反之则添加。 - 对于
enumerated attributes(目前包括:contenteditable,draggable和spellcheck),vue试图强制改写它们为字符串(目前对contenteditable做了特殊处理,来接收用户传入合法的contenteditable值而不是转为contenteditable='true') - 对于其他attribute,如果它们的值为
falsy则会移除,反之则按set原值。
在v2.x版本中,我们添加了enumerated attributes的概念,表示只能接收'true'或'false' 的属性,这在技术上是有缺陷的。而且相对于其他非布尔类型的attribute的行为是不同的,这也对用户造成了困惑。下面的table描述了enumerated attributes 的属性与普通非布尔类型attributes的不同点:
| Binding expr. | foo normal | draggable enumerated |
|---|---|---|
: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" |
我们从上面这个table得知,目前的实现是将true强制设置为了'true',但是为false 时会移除attribute。这造成了用法上的不连贯,而且在很普遍的用例中,例如aria-*:aria-selected, aria-hidden等, 要求用户手动将值从boolean类型更改为string类型。
详细设计
- 我们计划移除
enumerated attributes的概念,并且将它们作为普通非布尔类型的HTML attribute对待。
这解决了enumerated attributes和普通非布尔类型的attribute之间的不一致性。这样也就可以去使用其他值,而不仅仅是'true' 和 'false',甚至尚未确定的关键字。
- 对于非布尔类型的HTML attribute,如果值为false时不再移除,而是设置为
'false'。
这解决了值为true和false如何set attribute的不一致性,而且更容易输出aria-* attribute。
下面这个表格描述了新的行为:
| Binding expr. | foo normal | draggable enumerated |
|---|---|---|
: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="" † |
†: changed
对于布尔类型attribute的行为与之前保持一致。
缺点
该提案引入了以下重大更改:
- 对于
enumerated attributes:- 值为
null时才会移除attribute,而不是设置为'false' 'true'和'false'以外的number类型和string类型的值都不在强制转换为'true'
- 值为
- 对于所有非布尔类型的attribute,值为
false时不会移除它,而是会被设置为'false'
最重大的变更是用户不应该再依赖值为false时移除attribute,而是应该使用null或者undefined。但是布尔类型的attribute并不受影戏,这个变更更多影响的是值为'false' 或者不传递值 的enumerated attributes,例如aria-checked。这也可能影响如[foo]的css选择器。
可选的方案
N/A
采取的策略
不太可能为该用例提供一个有帮助的代码模板。我们应该在迁移指引中提供详细的信息,并且在v3.x版本的档案中记录下。
enumerated attributes
移除enumerated attributes的概念和attr='false'可能造成不同的IDL attribute值(这将会反映在真实的值上),描述如下:
| Absent enumerated attr | IDL attr & value |
|---|---|
contenteditable | contentEditable → 'inherit' |
draggable | draggable → false |
spellcheck | spellcheck → true |
为了保证旧行为有效,我们将会将false强制转换为'false',在3.x版本中对于通过v-bind传递给contenteditable 和 spellcheck的值,开发者需要手动将false处理为'false'。
在2.x版本中,对于enumerated attributes所有非法的属性值都会被转换为true 。这通常是无意的,不太可能被大规模依赖。在3.x,true或者'true'需要精确指定。
将false转换为'false'而不是移除attribute
在3.x版本中,移除attribute需要指定值为null或undefined
2.x版本和3.x版本中的行为比较
| Attribute | v-bind value 2.x | v-bind value 3.x | HTML output |
|---|---|---|---|
| 2.x “Enumerated attrs” i.e. contenteditable, draggable and spellcheck. | undefined, false | undefined, null | removed |
true, 'true', '', 1, 'foo' | true, 'true' | "true" | |
null, 'false' | false, 'false' | "false" | |
| Other non-boolean attrs eg. aria-checked, tabindex, alt, etc. | undefined, null, false | undefined, null | removed |
'false' | false, 'false' | "false" |
未解决的问题
N/A

