概要
在指令参数中支持动态值
基础示例
<div v-bind:[key]="value"></div>
<div v-on:[event]="handler"></div>
起因
由于指令参数是静态的,因此用户不得不求助于无参对象去使用动态key
<div v-bind="{ [key]:value }"></div>
<div v-on="{ [event]:handler }"></div>
然而,这有一些issue
- 这是一种鲜为人知的技术,依赖于对v-bind/v-on语法的了解,以及javascript中计算属性key的存在。
- 它生产代码的效率更低: 创建一个临时对象,如果同一元素上有静态绑定,那么必须动态的迭代该对象,将其混入现有的数据对象中,代码如下:
return h('div', {
on: Object.assign({
click: onClick
}, {
[event]: handler
})
})
用动态参数,我们可以直接生成
return h('div', {
on: {
click: onClick,
[event]: handler
}
})
此外,由于v-slot
的值是用于声明插槽作用域变量,所以没有相同的对象语法。因此如果没有动态指令参数,v-slot
的语法将不能提供动态的插槽名。尽管这可能是一个非常少的用例,但是仅仅因为这个限制,就必须将整个模板重写为render函数,这会很痛苦。
细节设计
<!-- 动态key v-bind -->
<div v-bind:[key]="value"></div>
<!-- 动态key v-bind缩写 -->
<div :[key]="value"></div>
<!-- 动态key v-on -->
<div v-on:[event]="handler"></div>
<!-- 动态key v-on缩写 -->
<div @[event]="handler"></div>
<!-- 动态key v-slot -->
<foo>
<template v-slot:[name]>
Hello
</template>
</foo>
<!-- 动态key v-slot缩写 -->
<!-- pending #3 -->
<foo>
<template #[name]>
Default slot
</template>
</foo>
将null
当做特殊值处理
动态参数值预期是string,然而如果我们允许null
的时候就是删除绑定,那会很方便。其余的非string类型的值都可能会导致错误以及会有警告。
null
仅对于v-bind
和v-on
而言是特殊值,对v-slot
不生效。这是因为v-slot
并不是绑定,也不能被删除,自定义指令可以自由决定如何处理非字符串参数,但在应用时应该遵循约定。
缺点/注意事项
表达式约束
从理论上讲,这为任意复杂的javascript表达式打开了指令参数,但是html属性名不能包含空格和引号,用户可能会像下面这样踩坑:
<div :[ key + 'foo' ]="value"></div>
并不能符合预期的使用,解决方案是:
<div :[`${key}foo`]="value"></div>
也就是说,复杂的动态键绑定,可以通过计算属性在javascript中进行预转换。
更新::
可以检测这种用法,并在解析器里提供适当地警告(通过检测缺少右括号的参数)
自定义指令
允许所有指令使用动态参数意味着自定义指令实现 现在除了值更改外,还需要考虑潜在的参数更改。
这还需要增加 binding.oldArgs
到自定义指令绑定上下文
选择
N/A
采用策略
这是非破坏性的,可以直接扎起文档里引入更新
未解决的问题
N/A