>[success] # attribute 强制行为 ~~~ 1.删除枚举 attribute 的内部概念,并将这些 attribute 视为普通的非布尔 attribute 2.重大改变:如果值为布尔值,则不再删除 attribute false。相反,它被设置为 attr='false'。 移除 attribute,使用 null 或者 undefined 注意下面关于属性是通过 'v-bind' 绑定 ~~~ >[info] ## 理解 IDL 属性与内容属性、布尔值属性与枚举属性 ~~~ 1.看过上面官方解析比较晕原因是没有分清楚'IDL 属性与内容属性、布尔值属性与枚举属性' ~~~ >[danger] ##### 布尔值属性 ~~~ 1.常见的布尔属性'required, readonly, disabled,checked',它们的特点: 1.1.在于是否声明该属性,声明为true 未声明为false 1.2.声明的格式,其值必须是一个空字符串(即该属性的值未分配),或者是一个大小写无关的 ASCII 字符串,该字符串与属性名严格相同,前后都没有空格 2.通过下面例子可以知道布尔类型属性是否生效不在于你后面赋值而是在于你是否声明 ~~~ * 举个例子: ~~~html <!-- 布尔类型 true --> <input type="text" required> <input type="text" required=false> <input type="text" required='false'> <input type="text" required=true> <input type="text" required='true'> <input type="text" required=required> <input type="text" required='zzzzz'> <!-- 布尔类型false --> <input type="text"> ~~~ >[danger] ##### 枚举类型 ~~~ 1.可以理解成匹配的元素是是一个系列的例如'autocomplete' 它可以对应的值' username、email、country、tel、url ' 容易和枚举搞混的'contenteditable ' 他的枚举可以true 或者 false 2.下面代码以'contenteditable ' 为例当空字符串也代表 'true',而不分配值时,也与空字符串等价都是他枚举 提供的true等同,但是当声明的枚举例如下面'abcdefg' 不存在或者该属性没定义都等同枚举提供的false属性效果 ~~~ ~~~html <!-- 枚举 --> <!-- 枚举生效 --> <div contenteditable>An editable item</div> <div contenteditable="">An editable item</div> <div contenteditable="true">An editable item</div> <div contenteditable=true>An editable item</div> <!-- 枚举不生效 --> <div contenteditable="false">An editable item</div> <div contenteditable="abcdefg">An editable item</div> <div>An editable item</div> ~~~ >[danger] ##### 内容属性IDL属性 ~~~ 1.HTML 中,属性还有 内容属性 和 IDL属性 说法。注意,这两种属性,并不是对标签属性的划分。 他们只是属性不同地方的不同描述和写法而已。 2.内容属性 接收的值都是字符串。编写 HTML 时,直接写在标签中的就是内容属性。此外,内容属性还可以 通过 JS 的 setAttribute() 来设置。 <div contenteditable>An editable item</div> input.setAttribute('type', 'text'); input.getAttribute('type') 3.IDL属性 是一个 JavaScript 属性(property),是 DOM 提供给 JS 的真正属性。通过 . 运算符来 设置,且只接收正确类型的值。如果接收值的类型不正确,会自动转化成正确的类型。 input.type = 'password'; ~~~ >[danger] ##### 参考文章 [IDL 属性与内容属性、布尔值属性与枚举属性傻傻分不清楚?](https://zhuanlan.zhihu.com/p/144954383) >[info] ## Vue2.x 对这三种属性转换 ~~~ 1.对于某些属性/元素对,Vue 采用 IDL 属性 形式处理:如 value of <input>, <select>, <progress>, etc . 2.对于 布尔值属性 和 xlinks,Vue 通过判断 是否是falsy(undefined、 null、false)值来决定添加或是删除属性。 3.对于 枚举属性 (目前 contenteditable,draggable 和 spellcheck), Vue 强制转化为字符串true 和false因为这 三个枚举特殊他们枚举只有true 或者 false 4.对于其他(普通非布尔)属性,如果传递过来的值是 falsy 值则删除,否则直接添加 简单的来说首先明白falsy'https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy',简单的说除了枚举类型中 'contenteditable,draggable 和 spellcheck' 这三个比较特殊当你用v-bind去绑定时候会根据你绑定的值帮你 转换成他们枚举提供的'true' 和'false' 其他的属性通过v-bind 绑定只要是符合falsy 那三种情况就会直接移除 ~~~ >[danger] ##### 举个例子 ~~~html <!-- 布尔类型false --> <input type="text" :required='false'> <input type="text" :required='null'> <input type="text" :required='undefined'> <!-- 枚举 --> <input type="text" :autocomplete='false'> <input type="text" :autocomplete='null'> <input type="text" :autocomplete='undefined'> <!-- 特殊枚举类型 --> <input type="text" :contenteditable='false'> <input type="text" :contenteditable='null'> <input type="text" :contenteditable='undefined'> ~~~ ![](https://img.kancloud.cn/eb/94/eb9426cdd4fed2c9b03db2909e6296ca_418x158.png) >[danger] ##### 官方给的对比图 ~~~ 1.通过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"` | >[danger] ##### 源码中对几个类型值的分类 ![](https://img.kancloud.cn/88/b8/88b8fb1d0fb1006db8d3be4f6f6990e3_719x417.png) [对应源码的位置](https://github1s.com/vuejs/vue/blob/bad3c326a3f8b8e0d3bcf07917dc0adf97c32351/src/platforms/web/util/attrs.js) ![](https://img.kancloud.cn/8f/c6/8fc62588c3054cd793b3aad75e6788c0_835x484.png) >[info] ## Vue3.x ~~~ 1.在2.x 问题就是不同属性通过v-bind 绑定false 会有两种结果,非特殊课枚举属性设置是false该元素直接被删除, 但是特殊枚举属性会被强制设为字符串false,其中这么做还出现了一个弊端实验属性不能体验可以看vue2.x 这个issues'https://github.com/vuejs/vue/issues/9397' 2.vue3.x 将属性从'特殊枚举属性和其他属性'分为了新的'布尔属性和非布尔属性',特殊枚举属性 可以使用除 true 和 false 以外的值,甚至是未使用的关键字,并且'非布尔属性',如果传递的值是false,Vue 将不再会删除 属性了,而是强制转化为字符串'false' 3.布尔属性 表现并改变,和 Vue 2.x 保持一致。 ~~~ >[danger] ##### 举个例子 ~~~ 1.还是一样的例子注意现在只有布尔属性在设置成false会被删除,其他非布尔属性只会转译成字符串false 但是null 和undefined 依旧无论什么属性都会被删除 ~~~ ~~~html <!-- 布尔类型false --> <input type="text" :required='false'> <input type="text" :required='null'> <input type="text" :required='undefined'> <!-- 枚举 --> <input type="text" :autocomplete='false'> <input type="text" :autocomplete='null'> <input type="text" :autocomplete='undefined'> <!-- 特殊枚举类型 --> <input type="text" :contenteditable='false'> <input type="text" :contenteditable='null'> <input type="text" :contenteditable='undefined'> ~~~ ![](https://img.kancloud.cn/ee/c5/eec59e173682481f86c21a8e54b7174e_440x236.png) >[danger] ##### 官方给的对比图 | 绑定表达式 | `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=""`† | >[danger] ##### vue3.x 我要怎么做 ~~~ 1.所以当你属性是动态绑定值的时候并且想删除不能再配置false,而是需要所使用undefined和null来显式删除属性 ~~~ >[info] ## 官网给出的2.x 和3.x 对比图 | Attributes | `v-bind`value2.x | `v-bind`value3.x | HTML 输出 | | --- | --- | --- | --- | | 2.x “枚举attribute” i.e.`contenteditable`,`draggable`and`spellcheck`. | `undefined`,`false` | `undefined`,`null` | *removed* | | `true`,`'true'`,`''`,`1`,`'foo'` | `true`,`'true'` | `"true"` | | `null`,`'false'` | `false`,`'false'` | `"false"` | | 其他非布尔attribute eg.`aria-checked`,`tabindex`,`alt`, etc. | `undefined`,`null`,`false` | `undefined`,`null` | *removed* | | `'false'` | `false`,`'false'` | `"false"` |