更新时间:2021-09-02 10:33:08 来源:极悦 浏览3534次
ant-design-vue开源了一段时间后,收到了一些反馈,尤其是Form组件上线后,很多用户对JSX的使用感到迷惑和不习惯,为此专门介绍下Vue JSX的使用姿势及注意事项。
Form组件的自动收集校验功能需要在JSX下使用,当然如果不需要自动收集校验,你依然可以使用template
Vue推荐在绝大多数情况下使用template来创建你的HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,就需要使用 render 函数,它比 template 更接近编译器。但是复杂的render函数书写异常痛苦,好在官方提供了一个 Babel 插件,可以将更接近于模板语法的JSX转译成JavaScript。
使用过React的同学对JSX肯定不陌生,但是Vue的JSX写法和React的还是有一些区别。
React中父子之间传递的所有数据都是属性,即所有数据均挂载在`props`下(style, className, children, value, onChange等等)。
Vue则不然,仅仅属性就有三种:组件属性props,普通html属性attrs,Dom属性domProps。
接下来我们通过一个示例来详细解释他们的区别:本文代码可在codesandbox查看运行
const ButtonCounter = {
name: "button-counter",
props: ["count"],
methods: {
onClick() {
this.$emit("change", this.count + 1);
}
},
render() {
return (
<button onClick={this.onClick}>You clicked me {this.count} times.</button>
);
}
};
export default {
name: "button-counter-container",
data() {
return {
count: 0
};
},
methods: {
onChange(val) {
this.count = val;
}
},
render() {
const { count, onChange } = this;
return (
<div>
<ButtonCounter
style={{ marginTop: "10px" }}
count={count}
type="button"
onChange={onChange}
/>
<ButtonCounter
style={{ marginTop: "10px" }}
count={count}
type="button"
domPropsInnerHTML={`hello ${this.count}.`}
onChange={onChange}
/>
</div>
);
}
};
组件属性props:指组件声明的属性,即上述示例中声明的props: ['count']。
普通html属性attrs: 指组件未声明的属性,即上述示例中的type="button",该属性默认会直接挂载到组件根节点的上,如果不需要挂载到根节点,可声明 inheritAttrs: false。
Dom属性domProps:指的Dom属性,如上述示例中的innerHTML,它会覆盖组件内部的children, 这类属性我们一般很少使用到。
同样事件属性也分了两种:on nativeOn
答:正则则则...... ?,babel-plugin-transform-vue-jsx插件会通过正则匹配的方式在编译阶段将书写在组件上属性进行“分类”。
onXXX的均被认为是事件,nativeOnXXX是原生事件,domPropsXXX是Dom属性,
class,staticClass,style,key,ref,refInFor,slot,scopedSlots这些被认为是顶级属性,至于我们属性声明的props,以及html属性attrs,不需要加前缀,插件会将其统一分类到attrs属性下,然后在运行阶段根据是否在props声明来决定属性归属(即属于props还是attrs)。
第一、属性分类是编译阶段进行的分类,那么对于动态属性如何划分分类?
在React中所有属性都是顶级属性,直接使用{...props}就可以了,但是在Vue中,你需要明确该属性所属的分类,如一个动态属性value和事件change,你可以使用如下方式(延展属性)传递:
const dynamicProps = {
props: {},
on: {},
}
if(haValue) dynamicProps.props.value = value
if(hasChange) dynamicProps.on.change = onChange
<Dynamic {...dynamicProps} />
当然你可以混合着使用:
<Dynamic {...dynamicProps} style="color: red"/>
先别高兴太早,如果你没有深入使用过Vue JSX,不建议你使用混合方式,因为Vue会对其进行属性合并,至于合并的规则官方也并没有详细的文档,文档中有一处示例,我在这再举一个例子:
const dynamicProps2 = { on: { change: onChange2 } };
<Dynamic
{...{ on: { change: onChange1 } }}
{...dynamicProps2}
onChange={onChange3}
/>
上例中的onChange1、onChange2、onChange3都会触发,而你想要的可能仅仅是onChange3。其它属性的合并规则我就不一一列举了,总之,我不建议你使用混合方式,除非你及你的团队其他小伙伴对其规则了解的足够透彻。
注:理想情况你不应该需要动态属性,在业务开发中也比较少的使用动态属性,但如果你尝试开发一些通用性比较强的组件,就很难逃过动态属性的使用。
第二、如果声明的属性就是onXXX怎么处理?
首先我不建议你这么做,但如果真的需要,你必须明确该属性的分类,如下所示:
<div>
<Dynamic value="获取到value,然而并不能获取到onXXX" onXXX="?" />
<Dynamic {...{ props: { onXXX: "获取到onXXX,但不建议使用" } }} />
</div>
第三、函数式组件的props如何处理?
注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接受 props,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的属性都会被自动解析为 props。
props和attrs之间存在着很微妙的关系,在普通组件中,只要明确声明的属性会被划分到props分类中,剩下的均在attrs中。而对于函数式组件,只要省略了props选项,传参时不管是否明确分类,最终context.props获取到的都是全部属性,如果你需要获取明确的分类情况,可以在context.data下查看。
总之,在函数式组件中,推荐省略props选项。
第四、指令是否还可用?
很不幸的告诉你,大多数指令并不能在JSX中使用,对于原生指令,只有v-show是支持的。
大部分指令在JSX中可以使用表达式来替代,如:条件运算符(?:)替代v-if、array.map替代v-for
对于自定义的指令,可以使用如下方式使用:
const directives = [
{ name: 'my-dir', value: 123, modifiers: { abc: true } }
]
return <div {...{ directives }}/>
以上就是极悦小编介绍的"在Vue中使用JSX的正确姿势",希望对大家有帮助,想了解更多可查看编程入门教程。极悦在线学习教程,针对没有任何Java基础的读者学习,让你从入门到精通,主要介绍了一些Java基础的核心知识,让同学们更好更方便的学习和了解Java编程,感兴趣的同学可以关注一下。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习