Hello audience gentlemen, if you have read the last article, you will know that this series is to introduce some skills in the practice of vue.js, and reasonable use can improve some development efficiency. Today we introduce the special uses of JSX and the new functionality of vue.js — $props.
Tip 1: JSX can be written anywhere
As anyone who has written Vue JSX knows, we usually need to write JSX in render(h) {}. But there are cases where we want to write JSX in other methods, such as the Element component example from the previous article.
const h = this.$createElement this.$notify({ title: 'GitHub', message: H ('div', [h('p', '[GitHub] Subscribed to ElemeFE/ Element notifications'), h('el-button', {}, 'read ')])})Copy the code
Call the Notification service to display a custom piece of content. This code is not written in render, but we could have written JSX, for example:
{ methods: { showNotify() { const h = this.$createElement this.$notify({ title: 'GitHub', message: (<div> <p>[GitHub] Subscribed to ElemeFE/ Element notification</p> <el-button> <div>)})}}Copy the code
Using the babel-plugin-transform-vue-jsx plug-in, this code works fine. $createElement = this.$createElement = this.$createElement = this.$createElement = this. // eslint-disable-line ignores the message if it is useful for eslint:
const h = this.$createElement // eslint-disable-line
Copy the code
In fact, in the latest release babel-plugin-transform-vue-jsx 3.4.0, you no longer need to manually declare the H variable and can now happily write JSX anywhere in the component.
Tip 2: The use posture of $props
A new feature was added in vue.js 2.2 – $props. The documentation is very succinct about what it is but it doesn’t explain what it does, so I’m going to share with you some of the situations where you might need it.
1. Inherit native attributes
When developing a form component, you have to solve the problem of inheriting various properties from the native component. For example, to encapsulate an input component with a native placeholder property, our code might look like this:
<template>
<div>
<label>{{ label }}</label>
<input
@input="$emit('input', $event.target.value)"
:value="value"
:placeholder="placeholder">
</div>
</template>
<script>
export default {
props: ['value', 'placeholder', 'label']
}
</script>
Copy the code
But if you want to support other native attributes, you need to continue writing template content:
<template>
<div>
<label>{{ label }}</label>
<input
@input="$emit('input', $event.target.value)"
:value="value"
:placeholder="placeholder"
:maxlength="maxlength"
:minlength="minlength"
:name="name"
:form="form"
:value="value"
:disabled="disabled"
:readonly="readonly"
:autofocus="autofocus">
</div>
</template>
<script>
export default {
props: ['label', 'placeholder', 'maxlength', 'minlength', 'name', 'form', 'value', 'disabled', 'readonly', 'autofocus']
}
</script>
Copy the code
If you want to set type, or if you want to support textarea as well, the amount of repetitive code can be scary. But it might be easier to write in JSX instead:
export default { props: ['label', 'type', 'placeholder', 'maxlength', 'minlength', 'name', 'form', 'value', 'disabled', 'readonly', 'autofocus'], render(h) { const attrs = { placeholder: this.placeholder, type: this.type // ... } return ( <div> <label>{ this.label }</label> <input { ... { attrs } } /> </div> ) } }Copy the code
In Vue’s vNode, the native attributes are defined in data.attrs, so the input section above is compiled to:
h('input', {
attrs: attrs
})
Copy the code
This completes the passing of the native attribute. Similarly, if you want to set the textarea by type, you just need to add a judgment setting tag.
h(this.type === 'textarea' ? 'textarea' : 'input', { attrs })
Copy the code
So far we still need to define an attrs object, but all the attributes we need are defined in props. Wouldn’t it be nice to get the values directly from props? We can simply write a polyfill to do this. (Actually Vue 2.2 does not require you to introduce polyfill, it is supported by default)
import Vue from 'vue'
Object.defineProperty(Vue.prototype, '$props', {
get () {
var result = {}
for (var key in this.$options.props) {
result[key] = this[key]
}
return result
}
})
Copy the code
$options. Props = vm.$options. Props = vm. Then our code could look like this:
render(h) { return ( <div> <label>{ this.label }</label> <input { ... { attrs: this.$props } } /> </div> ) }Copy the code
If you’ve noticed the Vue documentation that v-bind can pass objects, our code is easier to write using a Vue template:
<template>
<div>
<label>{{ label }}</label>
<input v-bind="$props">
</div>
</template>
Copy the code
2. Inherit attributes of user-defined components
$props does much more than that. If you need to wrap another component based on the input component above, how do we inherit its properties?
For example, wrapping an input component with validation might look like this:
<template> <div> <XInput /> <div v-show="message && show-hit" class="hit">{{ message }}</div> </div> </template> <script> import XInput from './input.vue' export default { components: { XInput }, props: { showHit: Boolean}, data () {return {message: 'error'}}} </script>Copy the code
The key is how to pass the props of XInput. To do this, duplicate the props of Xinput in the props of the current component with v-bind.
<template> <div> <XInput v-bind="$props" /> <div v-show="message && show-hit" class="hit">{{ message }}</div> </div> </template> <script> import XInput from './input.vue' export default { components: { XInput }, props: { showHit: Boolean, ... XInput. Props}, data () {return {message: 'error'}}} </script>Copy the code
You can also implement this with object. assign:
{
props: Object.assign({ showHit: Boolean }, XInput.props)
}
Copy the code
That’s the basic use of $props. If you have any other ideas or uses, feel free to share in the comments. Now that we’re done sharing this series, I’ve put the code for all the examples in the Vue-Tricks repository. See you next time!
Refer to the link
-
vuejs/babel-plugin-transform-vue-jsx
-
Vue.js
-
$props · Issue #4571 · vuejs/vue
-
vuejs/babel-plugin-transform-vue-jsx
-
QingWei-Li/vue-tricks