关于vue3默认把所有onSomething当作v-on事件绑定的思考

2020-06-16 06:59:23易采站长站整理

最近在重新看vue3的rfcs,发现一个细节,原话如下:

props that start with on are handled as v-on bindings, with everything after on being converted to all-lowercase as the event name (more on this below)

也就是说,以后如果你在传递props的时候,以 on 开头的props,如果在组件上没有做props的声明,那么会被当作事件绑定到组件的根节点上。

究其原因,我大致概括了两点:

兼容vue2中的v-on.native
vue3的vnode声明把props拍平了,为了区分事件和其他props,就统一把所有的on开通的props默认作为事件绑定

为此,我开了一个issue来讨论这个问题,issue地址 。我关心的主要有两点:

这是对functional component的严重限制
是否会导致一些令人括困惑的误解

先讲第一点

vue3中可以直接通过 function() {} 来声明函数组件了,这是一个便利性的非常大的提升。在以前,你要声明组件,你必须要:


{
functinal: true,
props: {},
render() {}
}

这最大的提升来自不需要声明props,为什么说这是提升,因为这让我们开发HOC变得更方便了。现在我们可以通过 …rest 的方式把HOC不关心的props直接向下传递了。

但是现在因为这个默认限制,我们不得不在HOC中声明所有可能的他要扩展的组件以 on 开头的props。举个例子,我们有如下组件:


{
props: {
name: String,
onChange: Function
}
}

而我们的HOC的功能是在 name 前面加上 prefix ,对于这个HOC我们需要关心的只是 name 和他自己的props: prefix 。所以他的声明应该如下:


{
props: {
name: String,
prefix: String
}
}

然后在render中他可以这么做:


{
render() {
const {name, prefix, ...rest} = props
return <WrapperedComponent name={`${prefix}-${name}`} {...rest} />
}
}

也就是对于HOC来说,他是不需要关心他扩展的组件其他的props的,但是在这种情况下,如果我们不在HOC中声明,那么在使用的时候传入的 onChange 会自动绑定到root节点,而不是作为props传递下去。

第二点:令人困惑的使用

举个例子,如果我有一个组件:


{
props: {
onChange: Function
},
methods: {
handleInput() {
// do someting
// 并且根据情况触发`onChange`
}
},
render() {
return <input onInput={this.handleInput} />
}
}