Maison  >  Article  >  interface Web  >  Six façons de communiquer avec les composants Vue

Six façons de communiquer avec les composants Vue

hzc
hzcavant
2020-06-18 09:44:073220parcourir

Dans le processus de développement normal, la communication entre les composants père et fils/frère et sœur sera certainement rencontrée, voici donc un résumé des accessoires de communication de 6 composants Vue / $e$emit / Vuex$attrs / $ listenings

  1. $parent / $enfants avec réf

  2. fournir/injecter

Avant-propos

Six façons de communiquer avec les composants Vue

Comme le montre la figure ci-dessus, les composants A/B, B/C et B/D sont des relations parent-enfant, et C/ D est une relation fraternelle. Alors comment choisir différentes méthodes de communication selon différents scénarios d’utilisation ? Le principe est donc que nous devons comprendre les fonctions et les différences des différentes méthodes de communication.

1. props / $emit

C'est l'une des méthodes que nous utilisons habituellement le plus souvent. Le composant parent A transmet les données au composant enfant B via le paramètre props. Le composant B envoie un événement (portant des données de paramètre) au composant A via $emit. Le composant A écoute l'événement déclenché par $emit et obtient les données envoyées par B à A. Expliquons en détail ses étapes de mise en œuvre :

1 : Le composant parent transmet la valeur au composant enfant

// App.vue 父组件
<template>
    <a-compontent></a-compontent>
</template>
<script>
import aCompontent from &#39;./components/A.vue&#39;;
export default {
    name: &#39;app&#39;,
    compontent: { aCompontent },    
    data () {        
        return {
         dataA: &#39;dataA数据&#39;
       }
    }
}
// aCompontent 子组件
<template>
    <p>{{dataA}} // 在子组件中把父组件传递过来的值显示出来

<script>export default {
    name: &#39;aCompontent&#39;,
    props: {
        dataA: {           
              //这个就是父组件中子标签自定义名字            
              type: String,
            required: true  // 或者false
        }
    }
}
</script>

2 : Le composant enfant transmet la valeur au composant parent (via événements)

// 子组件
<template>
    <p>点击向父组件传递数据</p>
</template>
<script>export default {
    name: &#39;child&#39;,
    methods:{        
        changeTitle() {
              // 自定义事件,会触发父组件的监听事件,并将数据以参数的形式传递
            this.$emit(&#39;sendDataToParent&#39;,&#39;这是子组件向父组件传递的数据&#39;); 
        }
    }
}

// 父组件
<template>
    <child @sendDataToParent="getChildData">

<script>
import child from &#39;./components/child.vue&#39;;
    export default {
    name: &#39;child&#39;,
    methods:{
        getChildData(data) {
            console.log(data); // 这里的得到了子组件的值
        }
    }
}
</script>

2. $emit / $on

Cette méthode utilise une instance comme App.vue comme module Event Center, utilisez-la pour déclencher et écoutez les événements. Si vous le mettez dans App.vue, vous pouvez implémenter la communication dans n'importe quel composant. Cependant, cette méthode n'est pas facile à maintenir lorsque le projet est relativement volumineux.

Par exemple : Supposons qu'il y ait maintenant 4 composants, les composants Home.vue et A/B/C. Ces trois composants AB sont des composants frères. Home.vue est équivalent au composant parent créant une instance Vue vide. Montez l'événement de communication sur l'instance -

D.js
import Vue from 'vue'export default new Vue()
// 我们可以在router-view中监听change事件,也可以在mounted方法中监听
// home.vue<template>  <p>    <child-a></child-a>    <child-b></child-b>    <child-c></child-c>  </p></template>
// A组件
<template>
  <p>将A组件的数据发送给C组件 - {{name}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      name: &#39;Echo&#39;
    }
  },
  components: { Event },
  methods: {    dataA() {
      Event.$emit(&#39;data-a&#39;, this.name);
    }
  }
}
</script>
// B组件
<template>
  <p>将B组件的数据发送给C组件 - {{age}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      age: &#39;18&#39;
    }
  },
  components: { Event },
  methods: {    dataB() {
      Event.$emit(&#39;data-b&#39;, this.age);
    }
  }
}
</script>
// C组件
<template>
  <p>C组件得到的数据 {{name}} {{age}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      name: &#39;&#39;,
      age: &#39;&#39;
    }
  },
  components: { Event },  mounted() {
    // 在模板编译完成后执行
    Event.$on(&#39;data-a&#39;, name => {
      this.name = name;
    })
    Event.$on(&#39;data-b&#39;, age => {
      this.age = age;
    })
  }
}
</script>

Nous pouvons savoir de ce qui précède que l'événement $emit de A/B est surveillé dans l'événement monté du composant C et les paramètres transmis par celui-ci sont obtenus (puisque nous ne savons pas quand l'événement est déclenché, nous écoutons généralement en monté/créé)

3. Vuex

Vuex est un mode de gestion d'état. Il utilise un stockage centralisé pour gérer l'état de tous les composants de l'application et utilise les règles correspondantes pour garantir que l'état change de manière prévisible. Le cœur de l'application Vuex est le magasin (entrepôt, un conteneur). Le magasin contient la majeure partie de l'état de votre application

Cette partie ne sera pas présentée en détail. Le document officiel est vuex très détaillé. vuejs .org/zh/guide/st…

IV. $attrs / $listeners

Comme le montre l'image ci-dessus , il s'agit d'une imbrication de composants à plusieurs niveaux, comment les composants de climatisation communiquent-ils ? Nous pouvons maintenant penser aux solutions suivantes :

  1. Utilisez Vuex pour la gestion des données, mais le problème avec l'utilisation de vuex est que si le projet est relativement petit et qu'il y a moins d'état partagé entre les composants, utilisez vuex c'est comme tuer un poulet avec un couteau.
  2. Utilisez le composant B comme station de transfert. Lorsque le composant A doit transmettre des informations au composant C, B accepte les informations du composant A puis les transmet au composant C à l'aide d'accessoires. Cependant, s'il y en a trop. composants, ce sera Le code est lourd et la maintenance du code est difficile ; si le changement d'état en C doit être transmis à A, le système d'événements doit être utilisé pour le transmettre niveau par niveau.

Dans Vue2.4, afin de résoudre cette exigence, les attrs et les auditeurs ont été introduits, et l'optionheritAttrs a été ajoutée. (Comme le montre l'image ci-dessous)

Le rôle de $attrs, dans certains cas, il doit être utilisé conjointement avec EnsureAttrs

a 4 composants : App.vue / child1.vue / child2.vue / child3.vue, ces quatre composants sont imbriqués en séquence.

// App.vue
<template>
  <p>
    </p>
<p>App.vue</p>
<hr>
    // 这里我们可以看到,app.vue向下一集的child1组件传递了5个参数,分别是name / age / job / sayHi / title
    <child1></child1>
  
</template>
<script>
const child1 = () => import("./components/child1.vue");
export default {
  name: &#39;app&#39;,
  components: { child1 },  data() {    return {
      name: "Echo",
      age: "18",
      job: "FE",
      say: "this is Hi~"
    };
  }
};
</script>
// child1.vue
<template>
  <p>
    </p>
<p>child1.vue</p>
    <p>name: {{ name }}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <p>可以看到,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数</p>
    <hr>
    <child2></child2>
  
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  // 这个inheritAttrs默认值为true,不定义这个参数值就是true,可手动设置为false
  // inheritAttrs的意义在用,可以在从父组件获得参数的子组件根节点上,将所有的$attrs以dom属性的方式显示
  inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    name: String // name作为props属性绑定
  },  created() {
    // 这里的$attrs就是所有从父组件传递过来的所有参数 然后 除去props中显式定义的参数后剩下的所有参数!!!
    console.log(this.$attrs); //  输出{age: "18", job: "FE", say-Hi: "this is Hi~", title: "App.vue的title"}
  }
};
</script>
// child2.vue
<template>
  <p>
    </p>
<p>child2.vue</p>
    <p>age: {{ age }}</p>
    <p>childCom2: {{ $attrs }}</p>
    <hr>
    <child3></child3>
  
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  },
  // 将inheritAttrs设置为false之后,将关闭自动挂载到组件根元素上的没有在props声明的属性
  inheritAttrs: false,
  props: {
    age: String
  },  created() {
    // 同理和上面一样,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数
    console.log(this.$attrs);
  }
};
</script>
// child3.vue
<template>
  <p>
    </p>
<p>child3.vue</p>
    <p>job: {{job}}</p>
    <p>title: {{title}}</p>
    <p>childCom3: {{ $attrs }}</p>
  
</template>
<script>export default {
  inheritAttrs: true,
  props: {
    job: String,
    title: String
  }
};
</script>

Jetons un coup d'œil à l'effet d'affichage spécifique :

Et comment utiliser $listeners Le document officiel dit : Contient le contenu dans le parent ? portée (sans décorateur .native) écouteur d'événement v-on. Il peut être transmis aux composants internes via v-on="$listeners" - très utile lors de la création de composants de niveau supérieur ! Au sens littéral, il devrait s'agir d'ajouter un événement d'écoute au composant parent qui doit accepter la valeur ? Pas grand chose à dire, le code

est quand même 3 composants imbriqués en séquence

<template>
  <p>
    <child2></child2>
  </p>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  methods: {    reciveRocket() {
      console.log("reciveRocket success");
    }
  }
};
</script>复制代码
<template>
  <p>
    <child3></child3>
  </p>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  },  created() {
    this.$emit(&#39;child2&#39;, &#39;child2-data&#39;);
  }
};
</script>复制代码
// child3.vue
<template>
  <p>
    </p>
<p>child3</p>
  
</template>
<script>
export default {
  methods: {    startUpRocket() {
      this.$emit("upRocket");
      console.log("startUpRocket");
    }
  }
};
</script>复制代码

这里的结果是,当我们点击 child3 组件的 child3 文字,触发 startUpRocket 事件,child1 组件就可以接收到,并触发 reciveRocket 打印结果如下:

> reciveRocket success
> startUpRocket

五. $parent / $children 与 ref

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

这两种方式都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。

我们先来看个用 ref 来访问组件的:

// child1子组件
export default {  
        data() {    
            return {
      title: 'Vue.js'
    };
  },
  methods: {    
      sayHello() {
      console.log('child1!!');
    }
  }
};
// 父组件
<template>
  <child1></child1>
</template>
<script>  
export default {
    methods: {      
        sayHi () {
        const child1 = this.$refs.child1;
        console.log(child1.title);  // Vue.js
        child1.sayHello();  // 弹窗
      }
    }
  }
</script>

六. provide/inject

provide/inject 是 Vue2.2.0 新增 API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。

由于自己对这部分的内容理解不是很深刻,所以感兴趣的可以前往官方文档查看: cn.vuejs.org/v2/api/#pro…

总结

常见使用场景可以分为三类:

  1. 父子通信:props / $emit;$parent / $children;$attrs/$listeners;provide / inject API; ref
  2. 兄弟通信:Vuex
  3. 跨级通信:Vuex;$attrs/$listeners;provide / inject API
    4.接下来我还会在我的裙里用视频讲解的方式给大家讲解【以下图中的内容有兴趣的可以来我的扣扣裙 519293536 免费交流学习,我都会尽力帮大家哦

推荐教程:《JS教程

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer