What is the JSX?
JSX is a combination of Javascript and XML. React invented JSX, which uses HTML syntax to create a virtual DOM. JSX treats < as HTML parsing and {as JavaScript parsing.
Why should I use JSX in VUE?
I want to play around with it. I’m kidding. At first, I experienced the JSX syntax in React, and found it was not as uncomfortable as others said, so I decided to try it in VUE. Without further ado, let’s see the difference between the two in code first.
Ps: Most scenes in Vue don’t need to use the render function, or templates are simpler and more intuitive.
Use the template
// item.vue
<template>
<div>
<h1 v-if="id===1">
<slot></slot>
</h1>
<h2 v-if="id===2">
<slot></slot>
</h2>
<h3 v-if="id===3">
<slot></slot>
</h3>
<h4 v-if="id===4">
<slot></slot>
</h4>
</div>
</template>
<script>
export default {
name: "item",
props:{
id:{
type:Number,
default:1
}
}
}
</script>
Copy the code
The item component takes the ID value from the parent component to display different H tags. V-if is “extreme” and has a lot of redundant slots
Use the Render function and JSX
// item.vue
<script>
export default {
name: "item",
props:{
id:{
type:Number,
default:1
}
},
render(){
const hText=`
<h${this.id}>${this.$slots.default[0].text}</h${this.id}>
`
return <div domPropsInnerHTML={hText}></div>
}
}
</script>
Copy the code
Plus the parent component to control the values of props. The parent component does not compare and uses the traditional template format,
// list.vue
<template>
<div>
<h-title :id="id">Hello World</h-title>
<button @click="next"> Next </button> </div> </template> <script> import Title from'./item'
export default {
name: "list".data() {
return {
id:1
}
},
components: {
"h-title":Title
},
methods:{
next(){
++this.id
}
}
}
</script>
Copy the code
After running, the page renders the h1 or H2 or H3 tag, and there is only one slot. Clicking on the value of toggle props also displays a different H tag. The second method is not very straightforward, but it saves a lot of redundant code and makes the page much cleaner.
Without the V-if,v-for, v-Model?
Don’t worry, these instructions are just dark magic and easy to implement with JS.
- v-if
render() {return (
<div>
{this.show?'are you handsome':'you're ugly'}
</div>
)
}
Copy the code
You can only write simple ternary expressions, so you have to use if/else for complex expressions
render() {let ifText
if(this.show){
if<p> </p>}else{
if<p> </p>}return (
<div>
{ifText}
</div>
)
}
Copy the code
- v-for
data() {return{
show:falseAnd the list: [1, 2, 3, 4]}},render() {return (
<div>
{this.list.map((v)=>{
return <p>{v}</p>
})}
</div>
)
}
Copy the code
In JSX, there is no way to write an if/for statement in the middle of the {} statement, only to write an expression, so we use map as a loop, use teradata expression as a judge
-
v-model
Recently, I was helping the company interview and found that v-model many people don’t know what grammar sugar is. Then some people say I can do it with native JS, but they don’t know how to do it in VUE. Well, two points: pass values and listen for events to change values.
<script>
export default {
name: "item".data() {return{
show:false, the list: [1, 2, 3, 4], the text:' ',
}
},
methods:{
input(e){
this.text=e.target.value
}
},
render() {return (
<div>
<input type="text" value={this.text} onInput={this.input}/>
<p>{this.text}</p>
</div>
)
}
}
</script>
Copy the code
How to use custom components?
It’s easy, just import it, don’t declare it in the components property, just write it in JSX for example
<script>
import HelloWolrd from './HelloWorld'
export default {
name: "item".render() {return (
<HelloWolrd/>
)
}
}
</script>
Copy the code
How do events, class,style,ref, etc., bind?
So let’s write it this way
render (h) {
return (
<div
// normal attributes or component props.
id="foo"
// DOM properties are prefixed with `domProps`
domPropsInnerHTML="bar"
// event listeners are prefixed with `on` or `nativeOn`
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
// other special top-level properties
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
// assign the `ref` is used on elements/components with v-for
refInFor
slot="slot">
</div>
)
}
Copy the code
NativeOnClick is used to bind events to custom components, while @click.native is used to bind events to functional components.
Functional components in JSX
Functional components are stateless and have no instances of this. Here’s what the VUE documentation says:
Because a functional component is just a function, the rendering overhead is much lower. However, the lack of persistent instances also means that functional components do not appear in the component tree of Vue DevTools.
I personally understand that because of the loss of state (data), much less responsive processing, life cycle and other processes will increase speed and reduce memory footprint?
Functional components can also be used in template format just like this
<template functional>
</template
Copy the code
What about functional components in JSX? How do I bind this instance to events? How do I get props?
Everything a component needs is passed through context, including:
props
: Provides objects for all propchildren
: An array of VNode childrenslots
: a function that returns the object of all slotsdata
: The data object passed to the component and passed to createElement as the second argument
I just listed some of the properties above. These are non-functional components. For functional components, vue adds the context object, which needs to be passed in as the second argument to render(h,context), This.$slots.default was updated to context.children props, which was hanging on this. This. data becomes context.data
Note that for functional components, features that are not defined as prop are not automatically added to the root element of the component
// Parent component... Omit irrelevant coderender() {return (
<Item data={this.data} class="large"/>)} // item.vue componentexport default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red" >
{context.props.data}
</div>
)
}
}
Copy the code
The code above expects the large class name to be passed to the root element of the Item, but it doesn’t. We need to add something
// Item.vue
export default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red"{... context.data}> {context.props.data} </div> ) } }Copy the code
Notice that the expansion operator adds all the attributes to the root element. This context.data is the attribute you added to the child component in the parent component, and it intelligently merges with the attribute you added to the root element in the child element. Now the.large class name is passed in. This is useful when you bind events from the parent to the child. Here’s a little pit for binding events
By passing context.data as the second parameter to createElement, we pass all the features and event listeners from my-functional-button. In fact, it’s so transparent that those events don’t even require the.native modifier
The above is a passage from vue’s official website. However, I missed one very important sentence after reading it, which is the last sentence. He said that there is no need for the. Native modifier? So let’s look at the code
// Parent component methods:{show(){
alert('hello')}},render() {return (
<Item data={this.data} onNativeClick={this.show} class="large"/ >)}Copy the code
The above code looks fine at first glance, custom components using onNativeClick will not pop up as a result. Native modifiers are not required for functional components. Native modifiers are not required for template, but JSX should change onNativeClick to onClick.
What features of existing projects can be replaced by JSX?
This is actually very similar to the example I gave you at the beginning. In the project, I used it to eliminate v-if/ V-else on a full screen. Since my business is on pad, the requirement is that there are dozens of questions in a test paper, and only one question is required to be displayed on each screen. Click the next question to display the next question.
- Use a num variable to represent the title index currently being displayed
- Num++ every time you click the next button
- Use v-if to say num===1, num===2 to decide which one to display.
This write, template inside a lot of ah, because our topic each topic template may be different, so there is no way to cycle, can only handwritten all. I considered using dynamic components to switch, but didn’t because it wasn’t intuitive.
Now how can WE optimize it with JSX
/ / the parent componentexport default {
name: "list".data() {
return {
data:'I'm a functional component', id: 1, tests: {1: < div > < span > the first topic < / span > < / div >, 2: < div > < section > second problem < / section > < / div >, 3: < div > < p > the third problem is < / p > < / div >}}}, methods:{next(){
++this.id
}
},
render() {return (
<div>
<Item data={this.tests[this.id]} class="large"/ > < button onClick = {this. Next} > next question < / button > < / div >)}}Copy the code
Each of the questions above has a different structure
// Subcomponent, only accepts data display, using functional component <script>export default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red"{... context.data}> {context.props.data} </div> ) } } </script>Copy the code
I did not use any if/else judgment to complete the function, here I think it is more appropriate to use JSX, I do not know what other ideas you have?
The last
To sum up, we usually use Temlate for development because it is intuitive and simple, and various instructions are very convenient to use. You can consider using JSX when you feel that the code written with Template looks redundant, or you want to control the rendering logic such as loop, judgment, etc. Functional components are also recommended to improve performance.
This is the first time to write an article, I hope you take the time to read the big guy feel that which said not too rigorous also need to forgive, put forward suggestions I accept.
The resources
Vue rendering function & JSX
babel-plugin-transform-vue-jsx