在Vue中使用JSX的正确姿式(有福利)

姿式很重要,末尾有福利html

vue-antd-ui开源了一段时间后,收到了一些反馈,尤为是Form组件上线后,不少用户对JSX的使用感到迷惑和不习惯,为此专门介绍下Vue JSX的使用姿式及注意事项。vue

Form组件的自动收集校验功能须要在JSX下使用,固然若是不须要自动收集校验,你依然可使用templatereact

Vue 推荐在绝大多数状况下使用template来建立你的HTML。然而在一些场景中,你真的须要 JavaScript 的彻底编程的能力,就须要使用render函数,它比 template 更接近编译器。可是复杂的render函数书写异常痛苦,好在官方提供了一个Babel 插件,能够将更接近于模板语法的JSX转译成JavaScript。git

使用过React的同窗对JSX确定不陌生,可是Vue的JSX写法和React的仍是有一些区别。github

React中父子之间传递的全部数据都是属性,即全部数据均挂载在props下(style, className, children, value, onChange等等)。编程

Vue则否则,仅仅属性就有三种:组件属性props,普通html属性attrs,Dom属性domPropsbabel

接下来咱们经过一个示例来详细解释他们的区别:markdown

本文代码可在codesandbox查看运行antd

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']dom

普通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)。

在编译阶段经过正则来区分,毕竟不是很严谨,那么根据以上分类规则会有哪些问题呢?

第1、属性分类是编译阶段进行的分类,那么对于动态属性如何划分分类?

在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} /> 复制代码

上例中的onChange一、onChange二、onChange3都会触发,而你想要的可能仅仅是onChange3。其它属性的合并规则我就不一一列举了,总之,我不建议你使用混合方式,除非你及你的团队其余小伙伴对其规则了解的足够透彻。

注:理想状况你不该该须要动态属性,在业务开发中也比较少的使用动态属性,但若是你尝试开发一些通用性比较强的组件,就很难逃过动态属性的使用。

第2、若是声明的属性就是onXXX怎么处理?

首先我不建议你这么作,但若是真的须要,你必须明确该属性的分类,以下所示:

<div>
    <Dynamic value="获取到value,然而并不能获取到onXXX" onXXX="😶" /> <Dynamic {...{ props: { onXXX: "获取到onXXX,但不建议使用" } }} /> </div> 复制代码

第3、函数式组件的props如何处理?

关于函数式组件的相关概念可查看官方文档,文档中有以下一段内容:

注意:在 2.3.0 以前的版本中,若是一个函数式组件想要接受 props,则 props 选项是必须的。在 2.3.0 或以上的版本中,你能够省略 props 选项,全部组件上的属性都会被自动解析为 props。

propsattrs之间存在着很微妙的关系,在普通组件中,只要明确声明的属性会被划分到props分类中,剩下的均在attrs中。而对于函数式组件,只要省略了props选项,传参时不论是否明确分类,最终context.props获取到的都是所有属性,若是你须要获取明确的分类状况,能够在context.data下查看。 总之,在函数式组件中,推荐省略props选项。

第4、指令是否还可用?

很不幸的告诉你,大多数指令并不能在JSX中使用,对于原生指令,只有v-show是支持的。 大部分指令在JSX中可使用表达式来替代,如:条件运算符(?:)替代v-ifarray.map替代v-for 对于自定义的指令,可使用以下方式使用:

const directives = [
  { name: 'my-dir', value: 123, modifiers: { abc: true } }
]

return <div {...{ directives }}/> 复制代码

更多Vue JSX的知识,能够查看官方文档。

总结:

说了那么多,其实只要记住一点,尽可能使用明确分类的方式传递属性,而不是要babel插件帮你分类及合并属性。

最后汇报下vue-antd-ui的进度,目前组件数量48个,相较react版,还有List、TreeSelect、Metion、Carousel没有开发,再过去的一段时间里,咱们更多的去完善组件单元测试,测试覆盖率83%,单测数量610个,接下来测试依然是咱们的主要工做。

质量永远要比数量重要的多。

欢迎star,欢迎pr。

福利环节:

本人参与翻译的React书籍(React Quickly,中文名:快速上手React编程)即将上市,现有样书4本,为了答谢支持vue-antd-ui的用户,使用者可到该issue下按照规范(需截图)回复后私信我地址,邮费自理,先到先得,数量有限,敬请谅解。

相对深刻浅出系列,该书更加适合初学者入门,若是你是Vue开发者,想要快速的学习React及周边技术(Redux、GraphQL、Jest等),我想这本书应该是不二之选。

相关文章
相关标签/搜索