Heim  >  Artikel  >  Web-Frontend  >  Einführung in 8 Möglichkeiten zur Kommunikation mit Vue-Komponenten (Sammlung)

Einführung in 8 Möglichkeiten zur Kommunikation mit Vue-Komponenten (Sammlung)

青灯夜游
青灯夜游nach vorne
2020-07-09 15:20:043980Durchsuche

Einführung in 8 Möglichkeiten zur Kommunikation mit Vue-Komponenten (Sammlung)

vue ist ein Framework für datengesteuerte Ansichtsaktualisierungen, daher ist die Datenkommunikation zwischen Komponenten für Vue sehr wichtig. Wie erfolgt also die Datenkommunikation zwischen Komponenten? Zunächst müssen wir wissen, welche Art von Beziehung zwischen den Komponenten in Vue besteht, damit wir ihre Kommunikationsmethoden leichter verstehen können.

Erklärung der Beziehungen in der Vue-Komponente:

Einführung in 8 Möglichkeiten zur Kommunikation mit Vue-Komponenten (Sammlung)

Wie in der Abbildung oben gezeigt, A und B, A und C, B und D, die Beziehung zwischen den Komponenten C und E ist eine Vater-Sohn-Beziehung; die Beziehung zwischen B und C ist die Beziehung zwischen A und D, und A und E ist die Beziehung zwischen D und E; ist ein Cousin (kein unmittelbarer Verwandter). Für die oben genannten Beziehungen ist die Klasse:

  1. Kommunikation zwischen Eltern- und Kinderkomponenten

  2. Kommunikation zwischen nicht übergeordneten und untergeordneten Komponenten (Geschwisterkomponenten, generationsgetrennte Komponenten usw.)

1. props / $emit

Die übergeordnete Komponente übergibt Daten über Requisiten an die untergeordnete Komponente, und $emit untergeordnete Komponenten können mit übergeordneten Komponenten kommunizieren.

1. Übergeordnete Komponente übergibt Wert an untergeordnete Komponente

Wie die übergeordnete Komponente Daten an die untergeordnete Komponente übergibt: So erhalten Sie die section.vue der übergeordneten Komponente im untergeordneten Element Komponente Article.vue Daten in Artikeln

// section父组件
<template>
 <p class="section">
 <com-article :articles="articleList"></com-article>
 </p>
</template>
<script>
import comArticle from &#39;./test/article.vue&#39;
export default {
 name: &#39;HelloWorld&#39;,
 components: { comArticle },
 data() {
 return {
 articleList: [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;,&#39;four&#39;,&#39;fives&#39;]
 }
 }
}
</script>
// 子组件 article.vue
<template>
 <p>
 <span v-for="(item, index) in articles" :key="index">{{item}}</span>
 </p>
</template>
<script>
export default {
 props: [&#39;articles&#39;]
}
</script>

Zusammenfassung: prop kann nur von der Komponente der oberen Ebene an die Komponente der unteren Ebene (Eltern-Kind-Komponente) übergeben werden, bei der es sich um sogenannte Einwegdaten handelt fließen. Darüber hinaus ist prop schreibgeschützt und kann nicht geändert werden. Alle Änderungen sind ungültig und es wird eine Warnung ausgegeben.

2. Die untergeordnete Komponente übergibt den Wert an die übergeordnete Komponente

Mein eigenes Verständnis von $emit ist folgendes: $emit bindet ein benutzerdefiniertes Ereignis, When Diese Anweisung wird ausgeführt, der Parameter arg wird an die übergeordnete Komponente übergeben und die übergeordnete Komponente lauscht und empfängt die Parameter über v-on. Erklären Sie anhand eines Beispiels, wie die untergeordnete Komponente Daten an die übergeordnete Komponente übergibt. Klicken Sie basierend auf dem vorherigen Beispiel auf das von der Seite gerenderte Artikelelement, und der im Array in der übergeordneten Komponente angezeigte Index

// 父组件中
<template>
 <p class="section">
 <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
 <p>{{currentIndex}}</p>
 </p>
</template>
<script>
import comArticle from &#39;./test/article.vue&#39;
export default {
 name: &#39;HelloWorld&#39;,
 components: { comArticle },
 data() {
 return {
 currentIndex: -1,
 articleList: [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;,&#39;four&#39;,&#39;fives&#39;]
 }
 },
 methods: {
 onEmitIndex(idx) {
 this.currentIndex = idx
 }
 }
}
</script>
<template>
 <p>
 <p v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</p>
 </p>
</template>
<script>
export default {
 props: [&#39;articles&#39;],
 methods: {
 emitIndex(index) {
 this.$emit(&#39;onEmitIndex&#39;, index)
 }
 }
}
</script>
// 父组件中
<template>
 <p class="hello_world">
 <p>{{msg}}</p>
 <com-a></com-a>
 <button @click="changeA">点击改变子组件值</button>
 </p>
</template>
<script>
import ComA from &#39;./test/comA.vue&#39;
export default {
 name: &#39;HelloWorld&#39;,
 components: { ComA },
 data() {
 return {
 msg: &#39;Welcome&#39;
 }
 },
 methods: {
 changeA() {
 // 获取到子组件A
 this.$children[0].messageA = &#39;this is new value&#39;
 }
 }
}
</script>
// 子组件中
<template>
 <p class="com_a">
 <span>{{messageA}}</span>
 <p>获取父组件的值为: {{parentVal}}</p>
 </p>
</template>
<script>
export default {
 data() {
 return {
 messageA: &#39;this is old&#39;
 }
 },
 computed:{
 parentVal(){
 return this.$parent.msg;
 }
 }
}
</script>

sollte auf Randbedingungen achten, z. B. die Übernahme von $parent #app Was Sie erhalten, ist eine Instanz von new Vue(). Wenn Sie $parent für diese Instanz verwenden, erhalten Sie undefiniert, und wenn Sie $children für die unterste untergeordnete Komponente verwenden, ist es ein leeres Array. Beachten Sie auch, dass die Werte von $parent und $children unterschiedlich sind. Der Wert von $children ist ein Array, während $parent ein Objekt ist.
Zusammenfassung
Die beiden oben genannten Methoden werden für die Kommunikation zwischen Parent und verwendet Untergeordnete Komponenten und Requisiten werden häufiger für die Kommunikation zwischen übergeordneten und untergeordneten Komponenten verwendet.

3. Provide/Inject

Konzept:

Provide/Inject ist eine neue API in vue2.2.0, einfach Mit anderen Worten: Variablen werden über „prove“ in der übergeordneten Komponente bereitgestellt und dann über „inject“ in die untergeordnete Komponente eingefügt.
Hinweis: Unabhängig davon, wie tief die Unterkomponente hier verschachtelt ist, können die Daten in Provide injiziert werden, solange inject aufgerufen wird, und es ist nicht auf die Rückgabe von Daten aus dem Props-Attribut der aktuellen übergeordneten Komponente beschränkt

Überprüfen Sie anhand eines Beispiels

Verifizieren Sie als Nächstes anhand eines Beispiels die obige Beschreibung: Angenommen, es gibt drei Komponenten: A.vue, B.vue, C.vue, wobei C eine Unterkomponente von ist B, und B ist eine Unterkomponente von A.

// A.vue
<template>
 <p>
	<comB></comB>
 </p>
</template>
<script>
 import comB from &#39;../components/test/comB.vue&#39;
 export default {
 name: "A",
 provide: {
 for: "demo"
 },
 components:{
 comB
 }
 }
</script>
// B.vue
<template>
 <p>
 {{demo}}
 <comC></comC>
 </p>
</template>
<script>
 import comC from &#39;../components/test/comC.vue&#39;
 export default {
 name: "B",
 inject: [&#39;for&#39;],
 data() {
 return {
 demo: this.for
 }
 },
 components: {
 comC
 }
 }
</script>
// C.vue
<template>
 <p>
 {{demo}}
 </p>
</template>
<script>
 export default {
 name: "C",
 inject: [&#39;for&#39;],
 data() {
 return {
 demo: this.for
 }
 }
 }
</script>

4. ref / refs

ref: Bei Verwendung auf einem normalen DOM-Element, Die Referenz verweist auf das DOM-Element. Bei Verwendung in der Unterkomponente zeigt die Referenz auf die Komponenteninstanz. Sie können die Methode der Komponente direkt aufrufen oder über die Instanz auf Daten zugreifen.

// 子组件 A.vue
export default {
 data () {
 return {
 name: &#39;Vue.js&#39;
 }
 },
 methods: {
 sayHello () {
 console.log(&#39;hello&#39;)
 }
 }
}
// 父组件 app.vue
<template>
 <component-a ref="comA"></component-a>
</template>
<script>
 export default {
 mounted () {
 const comA = this.$refs.comA;
 console.log(comA.name); // Vue.js
 comA.sayHello(); // hello
 }
 }
</script>

5 , eventBus

eventBus wird auch Eventbus genannt. Es kann als Kommunikationsbrückenkonzept in Vue verwendet werden. Es ist so, als ob sich alle Komponenten das gleiche Ereigniszentrum teilen und sich beim Zentrum registrieren können, Ereignisse senden oder empfangen, sodass Komponenten andere Komponenten benachrichtigen können.

EventBus kann auch zu Unannehmlichkeiten führen, die schwer zu warten sind.

Wie kann man EventBus speziell für die Datenkommunikation zwischen Komponenten verwenden? die folgenden Schritte

1. Initialisierung

Zuerst müssen Sie einen Ereignisbus erstellen und ihn exportieren, damit andere Module ihn verwenden oder überwachen können.

// event-bus.js
import Vue from &#39;vue&#39;
export const EventBus = new Vue()

2. Ereignisse senden

Angenommen, Sie haben zwei Komponenten: AdditionNum und ShowNum. Diese beiden Komponenten können Geschwisterkomponenten oder Eltern-Kind-Komponenten sein. Beispiel:

<template>
 <p>
 <show-num-com></show-num-com>
 <addition-num-com></addition-num-com>
 </p>
</template>
<script>
import showNumCom from &#39;./showNum.vue&#39;
import additionNumCom from &#39;./additionNum.vue&#39;
export default {
 components: { showNumCom, additionNumCom }
}
</script>
// addtionNum.vue 中发送事件
<template>
 <p>
 <button @click="additionHandle">+加法器</button> 
 </p>
</template>
<script>
import {EventBus} from &#39;./event-bus.js&#39;
console.log(EventBus)
export default {
 data(){
 return{
 num:1
 }
 },
 methods:{
 additionHandle(){
 EventBus.$emit(&#39;addition&#39;, {
 num:this.num++
 })
 }
 }
}
</script>

3. Empfangen Sie das Ereignis

// showNum.vue 中接收事件
<template>
 <p>计算和: {{count}}</p>
</template>
<script>
import { EventBus } from &#39;./event-bus.js&#39;
export default {
 data() {
 return {
 count: 0
 }
 },
 mounted() {
 EventBus.$on(&#39;addition&#39;, param => {
 this.count = this.count + param.num;
 })
 }
}
</script>

Klicken Sie auf diese Weise in der Komponente „additionNum.vue“ in „showNum“ auf die Schaltfläche „Hinzufügen“. Die übergebene Zahl wird verwendet, um das Summierungsergebnis anzuzeigen.

4. Entfernen Sie den Ereignis-Listener

Wenn Sie den Ereignis-Listener entfernen möchten, können Sie wie folgt vorgehen :

import { eventBus } from &#39;event-bus.js&#39;
EventBus.$off(&#39;addition&#39;, {})

6. Vuex

1. Einführung in Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. Vuex 解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上

2、Vuex各个模块

state:用于数据的存储,是store中的唯一数据源
getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

3、Vuex实例应用

// 父组件
<template>
 <p id="app">
 <ChildA/>
 <ChildB/>
 </p>
</template>
<script>
 import ChildA from &#39;./components/ChildA&#39; // 导入A组件
 import ChildB from &#39;./components/ChildB&#39; // 导入B组件
 export default {
 name: &#39;App&#39;,
 components: {ChildA, ChildB} // 注册A、B组件
 }
</script>
// 子组件childA
<template>
 <p id="childA">
 <h1>我是A组件</h1>
 <button @click="transform">点我让B组件接收到数据</button>
 <p>因为你点了B,所以我的信息发生了变化:{{BMessage}}</p>
 </p>
</template>
<script>
 export default {
 data() {
 return {
 AMessage: &#39;Hello,B组件,我是A组件&#39;
 }
 },
 computed: {
 BMessage() {
 // 这里存储从store里获取的B组件的数据
 return this.$store.state.BMsg
 }
 },
 methods: {
 transform() {
 // 触发receiveAMsg,将A组件的数据存放到store里去
 this.$store.commit(&#39;receiveAMsg&#39;, {
 AMsg: this.AMessage
 })
 }
 }
 }
</script>
// 子组件 childB
<template>
 <p id="childB">
 <h1>我是B组件</h1>
 <button @click="transform">点我让A组件接收到数据</button>
 <p>因为你点了A,所以我的信息发生了变化:{{AMessage}}</p>
 </p>
</template>
<script>
 export default {
 data() {
 return {
 BMessage: &#39;Hello,A组件,我是B组件&#39;
 }
 },
 computed: {
 AMessage() {
 // 这里存储从store里获取的A组件的数据
 return this.$store.state.AMsg
 }
 },
 methods: {
 transform() {
 // 触发receiveBMsg,将B组件的数据存放到store里去
 this.$store.commit(&#39;receiveBMsg&#39;, {
 BMsg: this.BMessage
 })
 }
 }
 }
</script>
vuex的store,js
import Vue from &#39;vue&#39;
import Vuex from &#39;vuex&#39;
Vue.use(Vuex)
const state = {
 // 初始化A和B组件的数据,等待获取
 AMsg: &#39;&#39;,
 BMsg: &#39;&#39;
}
const mutations = {
 receiveAMsg(state, payload) {
 // 将A组件的数据存放于state
 state.AMsg = payload.AMsg
 },
 receiveBMsg(state, payload) {
 // 将B组件的数据存放于state
 state.BMsg = payload.BMsg
 }
}
export default new Vuex.Store({
 state,
 mutations
})

 七、localStorage / sessionStorage

这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。 通过window.localStorage.getItem(key)获取数据 通过window.localStorage.setItem(key,value)存储数据

注意用JSON.parse() / JSON.stringify() 做数据格式转换 localStorage / sessionStorage可以结合vuex, 实现数据的持久保存,同时使用vuex解决数据和状态混乱问题.

 八 $attrs与 $listeners

现在我们来讨论一种情况, 我们一开始给出的组件关系图中A组件与D组件是隔代关系, 那它们之前进行通信有哪些方式呢?

  1. 使用props绑定来进行一级一级的信息传递, 如果D组件中状态改变需要传递数据给A, 使用事件系统一级级往上传递

  2. 使用eventBus,这种情况下还是比较适合使用, 但是碰到多人合作开发时, 代码维护性较低, 可读性也低

  3. 使用Vuex来进行数据管理, 但是如果仅仅是传递数据, 而不做中间处理,使用Vuex处理感觉有点大材小用了.

在vue2.4中,为了解决该需求,引入了$attrs 和$listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下,父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外),将会“回退”且作为普通的HTML特性应用在子组件的根元素上。接下来看一个跨级通信的例子:

// app.vue
// index.vue
<template>
 <p>
 <child-com1
 :name="name"
 :age="age"
 :gender="gender"
 :height="height"
 title="程序员成长"
 ></child-com1>
 </p>
</template>
<script>
const childCom1 = () => import("./childCom1.vue");
export default {
 components: { childCom1 },
 data() {
 return {
 name: "zhang",
 age: "18",
 gender: "女",
 height: "158"
 };
 }
};
</script>
// childCom1.vue
<template class="border">
 <p>
 <p>name: {{ name}}</p>
 <p>childCom1的$attrs: {{ $attrs }}</p>
 <child-com2 v-bind="$attrs"></child-com2>
 </p>
</template>
<script>
const childCom2 = () => import("./childCom2.vue");
export default {
 components: {
 childCom2
 },
 inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
 props: {
 name: String // name作为props属性绑定
 },
 created() {
 console.log(this.$attrs);
 // { "age": "18", "gender": "女", "height": "158", "title": "程序员成长" }
 }
};
</script>
// childCom2.vue
<template>
 <p class="border">
 <p>age: {{ age}}</p>
 <p>childCom2: {{ $attrs }}</p>
 </p>
</template>
<script>
export default {
 inheritAttrs: false,
 props: {
 age: String
 },
 created() {
 console.log(this.$attrs); 
 // { "gender": "女", "height": "158", "title": "程序员成长指北" }
 }
};
</script>

总结

常见使用场景可以分为三类:
父子组件通信: props; $parent / $children; provide / inject ; ref ; $attrs / $listeners
兄弟组件通信: eventBus ; vuex
跨级通信: eventBus;Vuex;provide / inject 、$attrs / $listeners

Das obige ist der detaillierte Inhalt vonEinführung in 8 Möglichkeiten zur Kommunikation mit Vue-Komponenten (Sammlung). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen