Posture is important. There’s a bonus at the end

Vue-antd-ui has been open source for a period of time, and some feedback has been received. Especially after the launch of the Form component, many users feel confused and unaccustomed to the use of JSX. Therefore, I would like to introduce the use posture and precautions of Vue JSX.

The Form component’s auto-collect validation function needs to be used under JSX, but if you don’t need auto-collect validation, you can still use Template

Vue recommends using templates to create your HTML in most cases. However, in some scenarios where you really need the full programming power of JavaScript, you need to use the Render function, which is closer to the compiler than template. But the complex render function is a pain to write, and fortunately a Babel plugin is available that translates JSX into JavaScript, which is closer to template syntax.

React JSX is familiar to those of you who have used React. However, there are some differences between Vue JSX and React JSX.

All data passed between a parent and a child in React are properties, that is, all data is mounted under props (style, className, children, Value, onChange, etc.).

Vue, on the other hand, has three properties: component properties props, plain HTML properties attrs, and Dom properties domProps.

Let’s use an example to explain the difference in detail:

The code for this article is available at 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> ); }};Copy the code

Component properties props: Indicates the properties of the component declaration, that is, the props declared in the example above: [‘count’].

The ordinary HTML attribute attrs: __ refers to an undeclared attribute of the component. In the example above, type=”button” is mounted directly to the root node of the component by default. If we don’t need to mount the inheritAttrs: false, we can declare the inheritAttrs: false.

The Dom property domProps: refers to the Dom property, such as innerHTML in the example above, which overrides the children inside the component, and is rarely used.

Similarly, there are two types of event attributes: on nativeOn

So how does a component distinguish between properties?

Answer: The re rule is…… 😶, the babel-plugin-transform-vue-jsx plug-in “sorts” properties written on components at compile time by means of regular matching. All of onXXX are considered events, nativeOnXXX is a native event, and domPropsXXX is a Dom property.

Class, staticClass, style, key, ref, refInFor, slot, scopedSlots these properties and is considered to be top for our props attribute declarations, and HTML attributes attrs, don’t need to add a prefix, The plugin categorizes it under the attrs attribute, and then determines whether the attribute belongs to props or attrs at runtime based on whether the attribute is declared at props.

After all, it is not very strict to distinguish by re at compile stage, so what are the problems according to the classification rules above?

First, attribute classification is carried out in the compilation stage, so how to classify dynamic attributes?

In React, all attributes are top-level attributes. Use {… Props} will do, but in Vue, you need to specify the class to which the property belongs, such as a dynamic property value or an event change, and you can pass it as follows:

const dynamicProps = {
  props: {},
  on: {},}if(haValue) dynamicProps.props.value = value
if(hasChange) dynamicProps.on.change = onChange <Dynamic {... dynamicProps} />Copy the code

Of course you can mix it up:

<Dynamic {... dynamicProps} style="color: red"/>
Copy the code

Don’t get too excited, if you haven’t used Vue JSX in depth, it is not recommended to use the hybrid method, because Vue will merge its attributes. The rules for merging are not well documented, but there is an example in the documentation. Here is another example:

const dynamicProps2 = { on: { change: onChange2 } };
<Dynamic
  {.{ on: { change: onChange1}}} {. dynamicProps2}
  onChange={onChange3}
/>
Copy the code

OnChange1, onChange2, and onChange3 in the previous example all fire, and all you want is onChange3. I won’t go through the rules for merging other attributes, but I don’t recommend using a hybrid approach unless you and the rest of your team understand the rules thoroughly.

Note: You should ideally not need dynamic properties, and they are rarely used in business development, but if you try to develop general-purpose components, you can easily get away with using dynamic properties.

What if the declared attribute is onXXX?

I don’t recommend doing this at first, but if you do, you must specify the classification of this attribute, as follows:

<div>
    <Dynamic value="Get value, but can't get onXXX" onXXX="😶" />
    <Dynamic {.{ props: { onXXX:"Get to theonXXX}}} /> is not recommended.
</div>
Copy the code

Third, how to handle functions for functional components?

For the concept of functional components, see the official documentation, which reads as follows:

Note: Prior to 2.3.0, the props option was required if a functional component wanted to accept props. In versions 2.3.0 and above, you can omit the props option, and properties on all components are automatically resolved to props.

There is a subtle relationship between props and attrs. In a normal component, as long as the properties that are explicitly declared are divided into the props category, the rest is in attrs. For functional components, as long as the props option is omitted, all properties of context.props are retrieved, regardless of whether the categories are explicit. If you want to obtain specific categories, you can view the properties in context.data. In general, in functional components, it is recommended to omit the props option.

Fourth, is the instruction still available?

Unfortunately, most directives are not available in JSX, for native directives, only V-show is supported. Most instructions in JSX can be replaced with expressions, such as conditional operators (? 🙂 Instead of v-if, array.map Instead of V-for For customized commands, you can use the following methods:

const directives = [
  { name: 'my-dir'.value: 123.modifiers: { abc: true}}]return <div {.{ directives}} / >
Copy the code

For more information on Vue JSX, see the official documentation.

Conclusion:

Having said all that, just remember to use explicit categories to pass attributes, rather than asking Babel to sort and merge attributes for you.

Finally, I would like to report the progress of VUE – ANTD-UI. The current number of components is 48. Compared with react version, List, TreeSelect, Metion and Carousel have not been developed. Testing is still our main work.

Quality is always more important than quantity.

Welcome star, welcome PR.

Welfare link:

React Quickly (React Quickly) In order to thank the users who support VUE-ANTD-UI, users can reply to this issue according to the specification (screenshot required) and then send me a private message. Postage will be paid by themselves. First come, first served, the number is limited, please understand.

It’s a better book for beginners to get started, if you’re a Vue developer and want to quickly learn React and its surrounding technologies (Redux, GraphQL, Jest, etc.).