- 开始时间:2019-01-16
- 目标主要版本:(2.x 或 3.x)
- 引用 issue:https://github.com/vuejs/rfcs/pull/2, https://github.com/vuejs/rfcs/pull/3
- 实现的 PR:https://github.com/vuejs/vue/pull/9373
摘要
在指令参数中支持动态值。
基本范例
<div v-bind:[key]="value"></div><div v-on:[event]="handler"></div>
动机
由于指令参数是静态的,因此当前用户不得不使用无参数(argument-less)的对象进行绑定,才能实现动态的 key 值。
<div v-bind="{ [key]: value }"></div><div v-on="{ [event]: handler }"></div>
然而,这还有几个问题:
- 这是一个不太为人知的技术,它依赖于 v-bind/v-on 的基于对象的语法知识和 JavaScript 中计算属性 key 的存在。
- 它产生的代码效率低:分配了一个临时对象,如果同一个元素还有其他静态绑定,就必须动态地迭代混入并混入现有的数据对象中。代码开启了大致是这样: ```javascript return h(‘div’, { on: Object.assign({ click: onClick }, {
[event]: handler
}) })
而对于动态参数,我们可以直接生成:```javascriptreturn h('div', {on: {click: onClick,[event]: handler}})
此外,v-slot 没有一个等价的对象语法,因为它的值是用来声明作用域插槽变量的。因此,如果没有动态参数,v-slot 就无法支持动态插槽名。虽然这是一个非常罕见的例子,但如果仅仅因为这个限制就将整个模版重写成渲染函数,那也太痛苦了。
具体设计
<!-- v-bind with dynamic key --><div v-bind:[key]="value"></div><!-- v-bind shorthand with dynamic key --><div :[key]="value"></div><!-- v-on with dynamic event --><div v-on:[event]="handler"></div><!-- v-on shorthand with dynamic event --><div @[event]="handler"></div><!-- v-slot with dynamic name --><foo><template v-slot:[name]>Hello</template></foo><!-- v-slot shorthand with dynamic name --><!-- pending #3 --><foo><template #[name]>Default slot</template></foo>
Handling ofnullas Special Value
动态参数值期望是一个字符串。然而,如果我们把 null 作为一个特殊的值,明切表示应该删除绑定,那就非常方便了。任何其他非字符串的值都可能是错误的,并会触发一个警告。
null 作为一个特殊值只适用于 v-bind 和 v-slot,但不适用于 v-slot。这是因为 v-slot 不是一个绑定,不能被删除。自定义指令可以自由地决定如何处理非字符串参数,但一般情况下应该遵循惯例。
缺点 / 注意事项
对表达式的约束
理论上,这为任意复杂的 JavaScript 表达式开放了指令参数,但 html 属性名不能包含空格和引号,所以在某些情况下,用户会被这样的东西绊倒:
<div :[key + 'foo']="value"></div>
这样并不能正常工作,一个变通的办法是:
<div :[`${key}foo`]="value"></div>
也就是说,复杂的动态键绑定应该可以在 JavaScript 中通过一个计算属性进行预转换。
自定义指令
允许所有指令的动态参数,意味着自定义指令的实现除了考虑值的变化外,还要考虑潜在的参数变化。
也需要在自定义指令的绑定上下文中增加 binding.oldArgs。
备选方案
N/A
采纳策略
这不是一个破坏性的提案,通过适当的文档更新应该可以直接(straightforward)引入。
没有解决的问题
N/A
