Vue JSX 属性透传的问题
参见以下代码:
function createButtons = (h, buttons) => props => {
return (
<span style="display: flex; justify-content: space-between;">
<!-- more -->
{buttons.map((item, index) => (
<mtd-button
{...{ attrs: item }}
key={index}
onClick={() => item.onClick(props)}
disabled={item.__disabled}
>
{item.text}
</mtd-button>
))}
</span>
)
}
createButtons(this.$createElement, [
{
text: "修改",
onClick: this.handleModify,
size: "small",
disabled: (props) => {
return auditStatus.isOffline(props.row.status);
},
},
]);
编译后
renderedButtons.forEach(function (item) {
if (typeof item.disabled === "function") {
item.__disabled = item.disabled(props);
} else if (typeof item.disabled === "boolean") {
item.__disabled = item.disabled;
}
});
return h(
"span",
{
style: "display: flex; justify-content: space-between;",
},
[
renderedButtons.map(function (item, index) {
return h(
"mtd-button",
{
attrs: _objectSpread({}, item, {
disabled: item.__disabled,
}),
key: index,
on: {
click: function click() {
if (typeof item.onClick === "function") {
item.onClick(props);
}
},
},
},
[item.text]
);
}),
]
);
最后,在我们点击修改按钮的时候,控制台报错:
Uncaught SyntaxError: Function statements require a function name
在这里createButtons 中的某一项传递了onClick这个参数,那么在对应的渲染函数里面,最后传递给组件的是什么样的呢?

handleModify 很好理解,就是我们希望绑定的事件,但是在上面的listeners里面,还添加了click事件,其对应的函数为
因此,上面的方式,最后会把 onClick 封装到 attrs里面。
在 Vue 组件挂载会后,首次更新时,Vue 会把相应的属性更新到 DOM 上.
因此,最后会调用 ele.setAttribute(key, value) 来设置组件的属性。这里的key value 都应该是一个DOM String。在这里的场景下, key 是对应的 onClick 字符串,而 value 是一个函数,它被定义为了 Vue 组件上的一个方法。而 Vue 在实例化组件的时候,通过initMethods方法,把对应的 method 通过bind 的方式绑定了vm的上下文。因此,这里的 value,最后是一个Bound function。因此这里会把相应的函数转换为DOM String,具体的转换方法没有找到相应的文档,但是从转换结果来看,是调用了函数的toString方法。而bind返回的函数,它的toString方法,最后会返回一个表示native代码的字符串,也就是
function () { [native code] }
因此,最后输出到html里的就变成了以下内容:
<button onclick="function () { [native code] }">测试</button>
我们知道,在一个元素定义了onclick属性的情况下,点击的时候,会将其属性值当作js脚本来执行。因此,当我们点击按钮的时候,会执行上面的脚本
function () { [native code] }
然而这个脚本是非法的,不说函数体,定义一个函数有函数表达式和函数声明两种方式,而上面的这种方式只能作为匿名函数被调用,在这里被当成了函数声明,因此就报错了。
Vue updateAttrs
el.setAttribute(key, value)
总结: 当出现问题并且不知道导致问题发生的因素时,应先通过二分法快速定位到导致问题的代码,然后通过**控制变量,减少场景的影响因子,在控制变量的时候,更需要注意双边其他因子的一致性,**找到问题出现的原因,待解决问题后,再寻根溯源,找到产生问题的根本因素。
参考: