The VueJSX
A, JSX
JSX is also written in the Render function, but is easier to understand than the Render function.
import AnchoredHeading from './AnchoredHeading.vue'
new Vue({
el: '#demo'.render: function (h) {
return (
<AnchoredHeading level={1}>
<span>Hello</span> world!
</AnchoredHeading>)}})Copy the code
That’s why there’s a Babel plug-in for using JSX syntax in Vue, which brings us back to a more template-like syntax.
1.1 the Attributes
render () {
<input name="id" />
}
Copy the code
1.2 Props
export default {
name: 'Test'.components: {
MyComponent
},
data () {
return {
name: 'Jesse'
}
},
render () {
const text = 'JSX'
const props = {
attrs: {
name: 'Jesse'.age: 1.sex: 'man'}}return (
<div>
<h3>Hello World</h3>{/ * hello * /}<p>Wellcome to {text}</p>
<my-component {. props} alias={this.name}></my-component>
</div>)}}Copy the code
Pass dynamic values with {}, {… Props} can be extended, like v-bind
receive
const MyComponent = {
name: 'MyComponent'.functional: true,
render (h, ctx) {
console.log(ctx.props)
return (
<div>
Hi~ {ctx.props.name}
<p>Alias: {ctx.props.alias}</p>
</div>)}}Copy the code
Here we receive as a functional component, see functional component
1.3 the Methods
const onClick = () = > {
console.log(111111)}const listeners = {
on: {
go () {
console.log('go')
},
to () {
console.log('to')}}}return (
<div>
<h3 onClick={onClick} {. listeners} >Hello World</h3>
</div>
)
Copy the code
Event passing is similar to Props passing, except that the function prefix is on. The binding can also be expanded, similar to V-ON
In order to differentiate, Vue has made a series of convenient operations on JSX
v-on
——>vOn
v-model
——>vModel
v-on:click.stop.prevent
——>vOn:click_stop_prevent
v-html
——>domPropsInnerHTML
1.4 Interaction between Parent and Child Components
const MyComponent = {
name: 'MyComponent'.functional: true,
render (h, ctx) {
ctx.listeners.back()
ctx.listeners.go()
return (
<div></div>)}}export default {
name: 'Test'.components: {
MyComponent
},
render () {
const onClick = () = > {
console.log(111111)}const listeners = {
on: {
go () {
console.log('go')
},
to () {
console.log('to')}}}return (
<div>
<h3 onClick={onClick}>Hello World</h3>
<my-component onBack={onClick} {. listeners} ></my-component>
</div>)}}Copy the code
Note: In functional components, the this.$emit trigger cannot be used; instead, events are passed in the Listeners property
1.5 cycle
{/* similar to v-if */}
{this.withTitle && <Title />}
{/* similar to v-if + v-else */}
{this.isSubTitle ? <SubTitle /> : <Title />}
{/* similar to v-for */}
{this.options.map(option= > {
<div>{option.title}</div>
})}
Copy the code
Functional components
We can mark the component as functional, which means it is stateless (no responsive data) and has no instance (no this context). A functional component would look like this:
export default {
functional: true.render: function (createElement, context) {
// Fully pass through any attribute, event listener, child node, etc.
return createElement("button", context.data, context.children); }};Copy the code
Note: Prior to 2.3.0, if a functional component wanted to receive a prop, the props option was required. In versions 2.3.0 and above, you can omit the props option, and attributes on all components are automatically resolved implicitly to prop.
When using functional components, the reference will be htmlElements because they are stateless and instance-free.
In version 2.5.0 and above, if you use single-file components, template-based functional components can be declared as follows:
<template functional>
</template>
Copy the code
Everything a component needs is passed through the context parameter, which is an object containing the following fields:
props
: Provides objects for all propchildren
: An array of VNode childrenslots
: a function that returns an object containing all slotsscopedSlots
(2.6.0+) an object that exposes the incoming scope slot. Normal slots are also exposed as functions.data
: passes to the entire componentThe data objectAs acreateElement
The second parameter is passed to the componentparent
: a reference to the parent componentlisteners
(2.3.0+) An object containing all event listeners registered by the parent component for the current component. This is adata.on
An alias for “.injections
(2.3.0+) If usedinject
Option, the object contains the property that should be injected.
Adding functional: After true, we need to update our anchor title component’s render function to add context and update this.$slot.default to context.children, Then update this.level to context.props. Level.
Because functional components are just functions, rendering overhead is also much lower.
They are also useful as packaging components. For example, when you need to do this:
- Programmatically select one of several components to render for you;
- In the
children
,props
,data
Manipulate children before passing them to them.
2.1 Pass attributes and events to child elements or components
In normal components, attributes that are not defined as prop are automatically added to the root element of the component, replacing or intelligently merging existing attributes with the same name.
Functional components, however, require you to explicitly define the behavior:
Vue.component('my-functional-button', {
functional: true.render: function (createElement, context) {
// Fully pass through any attribute, event listener, child node, etc.
return createElement('button', context.data, context.children)
}
})
Copy the code
By passing context.data as the second parameter to createElement, we pass all the attributes and event listeners on the my-functional-button. In fact, it’s so transparent that those events don’t even require the.native modifier.
If you use template-based functional components, you also need to manually add attributes and listeners. Because we have access to its context-independent content, we can use data.attrs to pass any HTML attribute, as well as listeners (aliases of data.on) to pass any event listener.
<template functional>
<button
class="btn btn-primary"
v-bind="data.attrs"
v-on="listeners"
>
<slot/>
</button>
</template>
Copy the code
2.2 slots()
和 children
contrast
You may be wondering why you need both slots() and children. Slot.default is similar to children. In some scenarios, this is true — but what about the following functional component with child nodes?
<my-functional-component>
<p v-slot:foo>
first
</p>
<p>second</p>
</my-functional-component>
Copy the code
For this component, children will give you two paragraph tags, slot.default will only pass the second anonymous paragraph tag, and slot.foo will pass the first named paragraph tag. You have both Children and slots(), so you can choose to make the component aware of a slot mechanism or simply pass children to the other component to handle.