Home> Web Front-end> Vue.js> body text

Let's talk about how Vue dynamically renders components through JSX

青灯夜游
Release: 2022-12-05 18:53:43
forward
2842 people have browsed it

How does Vue dynamically render components through JSX? The following article will introduce to you howVuecan efficiently render components dynamically through JSX. I hope it will be helpful to you!

Let's talk about how Vue dynamically renders components through JSX

1. Clear requirements

How to render dynamic components? [Related recommendations:vuejs video tutorial]

There is a set of array structures as follows:

const arr = [ { tag: 'van-field' }, // 输入框 { tag: 'van-cell' }, // 弹出层 { tag: 'van-stepper' } // 步进器 ]
Copy after login

I want to get thetagrendering corresponding by looping arr components.

Lets talk about how Vue dynamically renders components through JSX

Let’s analyze how to write the best way.

2. Analysis

2.1 v-if goes around the world

We can write av-forLoop through the arr array, and then usev-ifto determine the tag and render the corresponding component type.

It is not impossible to write like this, but the scalability is not good. Every time a tag is added, a v-if must be added to the template.

I believe many people wrote like this at first.

But this is not the code that we elegant people should write.

2.2 Dynamically rendering component tags

Can we render real tags based on the tags oftag.

The key is how to render the real component based on the traversed tags within the loop.

  
Copy after login

I would like to invite today’s protagonist JSX to come on stage.

Lets talk about how Vue dynamically renders components through JSX

2.3 JSX dynamic rendering component

Parent component

         
          
          
         const arr = [ { tag: 'van-field' }, // 输入框 { tag: 'van-cell' }, // 弹出层 { tag: 'van-stepper' } // 步进器 ]
Copy after login

Child componentRendTag.vue

Copy after login

We can use JSX'srenderto write JavaScript return components to achieve our dynamic rendering of tags.

renderis equivalent to the template in our vue.

So the rendering effect is as follows: render into a real component according to the tag

Lets talk about how Vue dynamically renders components through JSX

We use ordinary components, which cannot be rendered into what we want like JSX s component.

Herev-modelI recommend reading the pitfalls of using calculated attributes:How to bind multi-loop expressions in actual v-model (including principles)

In fact, these two articles are related to a certain extent, but I have separated the requirements here.

Mainly to facilitate friends’ reading and understanding.

3. How to use JSX in vue

Based on this requirement, we will make up for JSX.

3.1 What is it?

JSX is a syntax extension of Javascript,JSX = Javascript XML, which means writing XML in Javascript. Because of this feature of JSX, it has the flexibility of Javascript sex, and at the same time has the semantics and intuitiveness of html.

Some components with strong activity can be replaced by JSX (such as the above requirements);
It is not necessary to use JSX for the entire project.

3.2 Basic usage

3.2.1 Functional components

We can also embed in components ButtonCounter component.

const ButtonCounter = { name: "button-counter", props: ["count"], methods: { onClick() { this.$emit("changeNum", this.count + 1); } }, render() { return ; } }; export default { name: "HelloWorld", props: { msg: String }, data() { return { count: 0 }; }, methods: { // 改变button按钮数量 changeNum(val) { this.count = val; } }, render() { const { count } = this; // 解构 return ( 
); } };
Copy after login

3.2.2 Common attributes, inline styles, dynamic classes and styles

As you can see, it is basically the same as the template writing method of vue, but you need to pay attention to it. It is curly braces;

requires two pairs of curly braces in the vue template, while inJSXonly needs to writeand a pair of.

export default { name: "HelloWorld", props: { msg: String }, data() { return { count: 0, text: "Hello World!", msgClass: "msg-class", isGreen: true }; }, render() { const { count, text } = this; // 解构 return ( 

动态绑定class

动态绑定style

); } };
Copy after login

Lets talk about how Vue dynamically renders components through JSX

3.2.3 Common instructions

Common instructions for v-html, v-if, v-for, v-model It cannot be used in JSX and needs to be implemented in other ways.

v-html

In JSX, if you want to set theinnerHTMLof the DOM, you need to usedomProps.

Component usage:

 
Copy after login

Component code:

export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: {}, render() { return 
; } };
Copy after login

Rendering DOM result:

Lets talk about how Vue dynamically renders components through JSX

##v- for

Use

mapto implement:

render() { const list = [1,2,3] return( 
{ list.map(item => ) }
) }
Copy after login

v-if

Simple example: use ternary

render() { const bool = false; return 
{bool ? : }
; }
Copy after login

Complex example: Use JS directly

render() { let num = 3 if(num === 1){ return(  ) } if(num === 2){ return(  ) } if(num === 3){ return(  ) } }
Copy after login

v-model

Use directly:

export default { name: "HelloWorld", props: { msg: String }, data() { return { value: "abc" }; }, watch: { value(val) { console.log("this.model内容:" + val); } }, methods: {}, render() { return ( 
); } };
Copy after login

3.2.4 Listening events and event modifiers

Listening events

Listening Events like onChange, onClick, etc. can be used.

需要注意的是,传参数不能使用onClick={this.handleClick(params)},这样子会每次render的时候都会自动执行一次方法。

应该使用bind,或者箭头函数来传参。

组件示例代码:

export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: { handleClick(val) { alert(val); } }, render() { return ( 
); } };
Copy after login

用监听事件来实现v-model:

methods: { input(e) { this.value = e.target.value; } }, render() { return ( 
); }
Copy after login

也可以调整为:

 (this.vaue = e.target.value)} />
Copy after login

还可以使用对象的方式去监听事件:解构事件

export default { name: "HelloWorld", props: { msg: String }, data() { return { value: "" }; }, watch: { value(val) { console.log("this.model的内容:" + val); } }, methods: { handleInput(e) { this.value = e.target.value; }, handleFocus(e) { console.log(e.target); } }, render() { return ( 
); } };
Copy after login

nativeOn仅对于组件,用于监听原生事件,也可以使用对象的方式去监听事件:

{...{nativeOn:{click: this.handleClick}}}
Copy after login

事件修饰符

和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用。

  • .stop : 阻止事件冒泡,在JSX中使用event.stopPropagation()来代替
  • .prevent:阻止默认行为,在JSX中使用event.preventDefault()来代替
  • .self:只当事件是从侦听器绑定的元素本身触发时才触发回调,使用下面的条件判断进行代替
if (event.target !== event.currentTarget){ return }
Copy after login

.enter与keyCode: 在特定键触发时才触发回调

if(event.keyCode === 13) { // 执行逻辑 }
Copy after login

除了上面这些修饰符之外,尤大大对于.once,.capture,.passive,.capture.once做了优化,简化代码:

export default { name: "HelloWorld", props: { msg: String }, methods: { handleClick(e) { console.log("click事件:" + e.target); }, handleInput(e) { console.log("input事件:" + e.target); }, handleMouseDown(e) { console.log("mousedown事件:" + e.target); }, handleMouseUp(e) { console.log("mouseup事件" + e.target); } }, render() { return ( 
点击模块
); } };
Copy after login

3.3 插槽

3.3.1 普通插槽与具名插槽

父传子。

示例:

   
Copy after login

HelloWorld组件代码:this.$slots

export default { name: "HelloWorld", render() { return ( 
{this.$slots.default}
); } };
Copy after login

3.3.2 作用域插槽

子传父。

示例:

  
Copy after login

HelloWorld组件代码:this.$scopedSlots

export default { name: "HelloWorld", render() { return ( 
{this.$scopedSlots.content({ name: "张三", age: 20 })}
); } };
Copy after login

子组件通过{this.$scopedSlots.content({ name: "张三", age: 20 })}指定插槽的名称为content,并将含有name,age属性的对象数据传递给父组件,父组件就可以在插槽内容中使用子组件传递来的数据。

看到v-html用innerHTML;v-for用map;.stop用event.stopPropagation()
你有什么感想?
这不就是我们JavaScript方法的操作吗。
所以JSX就是Javascript + XML。

Lets talk about how Vue dynamically renders components through JSX

后记

我以前一直觉得Vue中没必要用JSX吧,用模板Template足以了。

但经过这个需求,我想JSX在处理动态渲染组件还是蛮占有优势的?。

日后面试官问我JSX在Vue的有什么应用场景,我想我可以把这个需求说一说。

(学习视频分享:web前端开发编程基础视频

The above is the detailed content of Let's talk about how Vue dynamically renders components through JSX. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:juejin.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn