Maison> interface Web> Voir.js> le corps du texte

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

青灯夜游
Libérer: 2022-12-05 18:53:43
avant
2830 Les gens l'ont consulté

Comment Vue restitue-t-il dynamiquement les composants via JSX ? L'article suivant vous présentera commentVuepeut restituer efficacement des composants de manière dynamique via JSX. J'espère qu'il vous sera utile !

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

1. Exigences claires

Comment rendre des composants dynamiques ? [Recommandations associées :Tutoriel vidéo vuejs]

Il existe un ensemble de structures de tableau comme suit :

const arr = [ { tag: 'van-field' }, // 输入框 { tag: 'van-cell' }, // 弹出层 { tag: 'van-stepper' } // 步进器 ]
Copier après la connexion

Je souhaite obtenir le composant correspondant pour le rendutagen bouclant arr.tag渲染对应的组件。

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

下面我们分析如何写才是最优。

二、进行分析

2.1 v-if走天下

我们可以写一个v-for去循环arr数组,然后通过v-if去判断tag,渲染对应的组件类型。

这样子写不是不可以,只不过扩展性不好,每次加一个标签,模板就要再加一个v-if。

我相信很多人起初都是这样写。

但这不是我们优雅人该写的代码。

2.2 动态渲染组件标签

我们能不能根据tag的标签来渲染出真正的标签。

关键是循环内,怎么根据遍历的tag去渲染出真正的组件。

  
Copier après la connexion

有请今天的主角JSX上场。

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

2.3 JSX动态渲染组件

父组件

         
          
          
         const arr = [ { tag: 'van-field' }, // 输入框 { tag: 'van-cell' }, // 弹出层 { tag: 'van-stepper' } // 步进器 ]
Copier après la connexion

子组件RendTag.vue

Copier après la connexion

我们利用JSX的render可以写JavaScript返回组件,来实现我们动态渲染标签。

render相当于我们vue中的模板。

于是渲染出的效果如下:根据tag渲染成真正的组件

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

我们用普通的组件,无法像JSX一样渲染成我们想要的组件。

这里的v-model用计算属性的坑,我推荐看一遍:实战v-model如何绑定多循环表达式(内含原理)

其实这两篇是有一定的挂钩的,只不过我在这里拆开了需求。

主要也是方便朋友们阅读理解。

三、vue中如何使用JSX

借着该需求,我们恶补一下JSX。

3.1 是什么?

JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javascript 的灵活性,同时又兼具 html 的语义化和直观性。

活度强的部分组件可以用JSX来代替(比如以上需求);
整个工程没有必要都使用JSX。

3.2 基本用法

3.2.1 函数式组件

我们在组件中,也可以嵌入ButtonCounter组件。

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 ( 
); } };
Copier après la connexion

3.2.2 普通属性、行内样式、动态class与style

可以看到,其实和vue的模板写法基本一致,只不过要注意的是花括号;

在vue的模板是要写两对花括号,而在JSX只需要写一对

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

); } };
Copier après la connexion

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

3.2.3 常用指令

v-html、v-if、v-for、v-model常用指令在JSX中无法使用,需要使用其他方式来实现。

v-html

在JSX中,如果要设置DOM的innerHTML,需要用到domProps

组件使用:

 
Copier après la connexion

组件代码:

export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: {}, render() { return 
; } };
Copier après la connexion

渲染DOM结果:

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

v-for

使用map来实现:

render() { const list = [1,2,3] return( 
{ list.map(item => ) }
) }
Copier après la connexion

v-if

简单示例:用三元

render() { const bool = false; return 
{bool ? : }
; }
Copier après la connexion

复杂示例:直接用JS

render() { let num = 3 if(num === 1){ return(  ) } if(num === 2){ return(  ) } if(num === 3){ return(  ) } }
Copier après la connexion

v-model

直接使用:

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

ci-dessous Nous analysons comment écrire de manière optimale.

Deuxièmement, analyser

2.1 v-si voyager autour du monde

Nous pouvons écrire unv-forparcourt le tableau arr, puis utilisev-ifpour déterminer la balise et restituer le type de composant correspondant.

Il n'est pas impossible d'écrire ainsi, mais l'évolutivité n'est pas bonne. Chaque fois qu'une balise est ajoutée, un v-if doit être ajouté au modèle. Je crois que beaucoup de gens ont écrit comme ça au début. Mais ce n’est pas le code que nous, les gens élégants, devrions écrire.

2.2 Rendu dynamique des balises de composants

Pouvons-nous restituer la vraie balise en fonction de la balise de tag. La clé est de savoir comment restituer le composant réel en fonction des balises parcourues dans la boucle.
export default { name: "HelloWorld", props: { msg: String }, data() { return { value: "abc" }; }, watch: { value(val) { console.log("this.model内容:" + val); } }, methods: {}, render() { return ( 
); } };
Copier après la connexion
Le protagoniste d'aujourd'hui, JSX, est invité à comparaître. Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

2.3 Composant de rendu dynamique JSX

Composant parent
export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: { handleClick(val) { alert(val); } }, render() { return ( 
); } };
Copier après la connexion
Copier après la connexion
Composant enfant RendTag.vue
methods: { input(e) { this.value = e.target.value; } }, render() { return ( 
); }
Copier après la connexion
Copier après la connexion
Nous pouvons écrire du JavaScript en utilisant le renderde JSX. le composant pour implémenter notre rendu dynamique des balises. renderest équivalent au modèle dans notre vue. Donc l'effet de rendu est le suivant : rendu dans un composant réel selon la balise Parlons de la façon dont Vue restitue dynamiquement les composants via JSXNous utilisons des composants ordinaires, qui ne peuvent pas être restitués dans les composants que nous voulons comme JSX. Le v-modelutilise ici des attributs calculés. Je recommande de le lire : V-model pratique comment lier des expressions multi-boucles (y compris les principes)En fait, ces deux articles sont quelque peu liés, mais je Les exigences sont décomposées ici. Principalement pour faciliter la lecture et la compréhension des amis.

3. Comment utiliser JSX dans vueAvec cette demande, nous compenserons JSX.

3.1 Qu'est-ce que c'est ?

JSX est une extension de syntaxe de Javascript,JSX = Javascript + XML, c'est-à-dire l'écriture de XML en Javascript. En raison de cette fonctionnalité de JSX, il a la flexibilité de Javascript, tout en. ayant la sémantique et l’intuitivité du HTML.
Certains composants à forte activité peuvent être remplacés par JSX (comme les exigences ci-dessus) ;
Il n'est pas nécessaire d'utiliser JSX pour l'ensemble du projet.

3.2 Utilisation de base

3.2.1 Composants fonctionnelsNous sommes ici Dans le composant, le composant ButtonCounter peut également être intégré.
 (this.vaue = e.target.value)} />
Copier après la connexion
Copier après la connexion

3.2.2 Attributs communs, styles en ligne, classes et styles dynamiquesComme vous pouvez le voir, c'est fondamentalement la même chose que la méthode d'écriture de modèle de vue, mais il convient de noter que les accolades ; Dans le modèle vue, vous devez écrire deux paires d'accolades, mais dansJSXvous n'avez besoin d'écrire que une paire.
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 ( 
); } };
Copier après la connexion
Copier après la connexion
Parlons de la façon dont Vue restitue dynamiquement les composants via JSX< h4 data-id="heading-11">3.2.3 Instructions communes Les instructions communes v-html, v-if, v-for, v-model ne peuvent pas être utilisées dans JSX et doivent être implémentées d'une autre manière . v-htmlDans JSX, si vous souhaitez définir leinnerHTMLdu DOM, vous devez utiliserdomProps. Utilisation du composant :
{...{nativeOn:{click: this.handleClick}}}
Copier après la connexion
Copier après la connexion
Code du composant :
if (event.target !== event.currentTarget){ return }
Copier après la connexion
Copier après la connexion
Résultat DOM rendu :Parlons de la façon dont Vue restitue dynamiquement les composants via JSXv-forUtilisezmappour implémenter :
if(event.keyCode === 13) { // 执行逻辑 }
Copier après la connexion
Copier après la connexion
v-ifExemple simple : utiliser Ternaire
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 ( 
点击模块
); } };
Copier après la connexion
Copier après la connexion
Exemple complexe : utiliser directement JS
   
Copier après la connexion
Copier après la connexion
v-modelUtiliser directement :
export default { name: "HelloWorld", render() { return ( 
{this.$slots.default}
); } };
Copier après la connexion
Copier après la connexion
3.2 . 4 Événements d'écoute et modificateurs d'événementsÉvénements d'écouteJe pense utiliser onChange, onClick, etc. pour écouter les événements.

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

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

组件示例代码:

export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: { handleClick(val) { alert(val); } }, render() { return ( 
); } };
Copier après la connexion
Copier après la connexion

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

methods: { input(e) { this.value = e.target.value; } }, render() { return ( 
); }
Copier après la connexion
Copier après la connexion

也可以调整为:

 (this.vaue = e.target.value)} />
Copier après la connexion
Copier après la connexion

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

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 ( 
); } };
Copier après la connexion
Copier après la connexion

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

{...{nativeOn:{click: this.handleClick}}}
Copier après la connexion
Copier après la connexion

事件修饰符

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

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

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

if(event.keyCode === 13) { // 执行逻辑 }
Copier après la connexion
Copier après la connexion

除了上面这些修饰符之外,尤大大对于.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 ( 
点击模块
); } };
Copier après la connexion
Copier après la connexion

3.3 插槽

3.3.1 普通插槽与具名插槽

父传子。

示例:

   
Copier après la connexion
Copier après la connexion

HelloWorld组件代码:this.$slots

export default { name: "HelloWorld", render() { return ( 
{this.$slots.default}
); } };
Copier après la connexion
Copier après la connexion

3.3.2 作用域插槽

子传父。

示例:

  
Copier après la connexion

HelloWorld组件代码:this.$scopedSlots

export default { name: "HelloWorld", render() { return ( 
{this.$scopedSlots.content({ name: "张三", age: 20 })}
); } };
Copier après la connexion

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

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

Parlons de la façon dont Vue restitue dynamiquement les composants via JSX

后记

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

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

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn