Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

不言
不言nach vorne
2018-11-20 14:27:272514Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen). Freunde in Not können darauf zurückgreifen.

1. Einführung

Komponenten sind eine der leistungsstärksten Funktionen von vue.js, und die Bereiche der Komponenteninstanzen sind unabhängig voneinander, was bedeutet, dass verschiedene Komponenten die Daten können sich nicht gegenseitig referenzieren. Es ist entscheidend, wie Daten zwischen Komponenten übertragen werden. In diesem Artikel wird versucht, einige gängige Datenübertragungsmethoden wie props, $emit/$on und vuex sowie die neuen Methoden $attrs/$listeners und Provide/Inject aufzulisten und sie mit einfach zu verstehenden Methoden zu beschreiben. Ich hoffe, dass der Unterschied für meine Freunde hilfreich sein kann.

2. Requisiten

Übergeordnete Komponente A wird über Requisiten an untergeordnete Komponente B übergeben, und B an A wird über $emit in Komponente B und v-on in Komponente A implementiert.

Prop ist unidirektional gebunden. Wenn sich die Eigenschaften der übergeordneten Komponente ändern, werden sie an die untergeordnete Komponente übertragen, aber nicht umgekehrt.
Und es ist nicht erlaubt, prop direkt innerhalb von a zu ändern Untergeordnete Komponente, andernfalls wird ein Fehler gemeldet. Wenn wir dann manchmal die übergebene Requisite ändern möchten, gibt es die folgenden Methoden:

Methode 1: Wenn die Unterkomponente sie als lokale Daten verwenden möchte, können Sie die Daten in einer anderen Variablen speichern und dann ausführen Es wirkt sich auf die Daten in der übergeordneten Komponente aus.

    <div>
    <h2>父组件:{{name}}</h2>
    <input>
    <my-hello></my-hello>
  </div>
  <template>
    <div>
      <h3>子组件{{username}}</h3>
      <button>修改数据</button>
    </div>
  </template>
  <script>
    var vm = new Vue({ //父组件
      el: &#39;#itany&#39;,
      data: {
        name: "tom"
      },
      components: {
        &#39;my-hello&#39;: { //子组件
          props: ["name"],
          template: &#39;#hello&#39;,
          data() {
            return {
              username: this.name
            }
          },
          //   computed: {
          //     changeName() { //如果要实时监测父组件数据的变化,还必须用到计算属性,
                                 然而计算属性不能直接被更改
          //       return this.name
          //     }
          //   },
          methods: {
            change() {
              this.username = "alice";
              // this.changeName = "alice";该方法无效,不能直接更改计算属性
            }
          },
        }
      }
    });
  </script>

Obwohl diese Methode die von der übergeordneten Komponente übergebenen Daten durch den Betrieb einer anderen Variablen beeinflussen kann, besteht ein großer Nachteil darin, dass sich die untergeordnete Komponente von nun an nicht mehr ändern kann, wenn sich die Daten der übergeordneten Komponente ändern. Wenn Sie zu diesem Zeitpunkt berechnete Eigenschaften verwenden, können die Änderungen zwar synchronisiert werden, die Unterkomponente kann die übergebenen Daten jedoch nicht ändern. Daher wird diese Methode weniger häufig verwendet.

Methode 2: Wenn die untergeordnete Komponente die Daten ändern und synchron zur übergeordneten Komponente aktualisieren möchte, gibt es zwei Methoden:

a. Verwenden Sie .sync (in Version unterstützt). 1.0, nicht in Version 2.0 Unterstützt (erneut unterstützt in Version 2.3) muss explizit ein Update-Ereignis auslösen.

<div>
  <h2>父组件:{{name}}</h2>
  <input>
  <hr>
  <my-hello></my-hello>
</div>
<template>
  <div> 
    <h3>子组件:{{name}}</h3>
    <button>修改数据</button>
  </div>
</template>
<script>
  var vm = new Vue({ //父组件
      el: &#39;#itany&#39;,
      data: {
        name: &#39;tom&#39;
      },
      components: {
        &#39;my-hello&#39;: { //子组件
           template: &#39;#hello&#39;,
           props: [&#39;name&#39;],
           methods: {
             change() {
              // this.name=&#39;alice&#39;;这种写法不行
                 this.$emit(&#39;update:name&#39;, &#39;alice123&#39;);
            //方式2:a.使用.sync,需要显式地触发一个更新事件
             }
           }
           }
        }
    });
</script>

Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

b Sie können die Daten in der übergeordneten Komponente in ein Objekt einschließen und dann die Eigenschaften des Objekt in der untergeordneten Komponente (da das Objekt ein Referenztyp ist und auf denselben Speicherbereich verweist),

<div>
    <h2>父组件:{{name}}</h2>
    <input>
    <h2>父组件:{{user.age}}</h2>
    <hr>
    <my-hello></my-hello>
</div>

<template>
    <div>
        <h3>子组件:{{name}}</h3>
        <h3>子组件:{{user.age}}</h3>
        <button>修改数据</button>
    </div>
</template>
<script>
    var vm = new Vue({ //父组件
        el: &#39;#itany&#39;,
        data: {
            name: &#39;tom&#39;,
            user: { //父组件中的数据包装成对象
                name: &#39;zhangsan&#39;,
                age: 24
            }
        },
        components: {
            &#39;my-hello&#39;: { //子组件
                template: &#39;#hello&#39;,
                props: [&#39;name&#39;, &#39;user&#39;],
                methods: {
                    change() {
                        this.user.age = 18;
                    }
                }
            }
        }
    });
</script>

Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

wird empfohlen. Dies liegt daran, dass Objekte und Arrays in JavaScript per Referenz übergeben werden. Bei einer Array- oder Objekttyp-Requisite wirkt sich also die Änderung des Objekts oder Arrays selbst in der untergeordneten Komponente auf den Status der übergeordneten Komponente .

3. $emit/$on

Diese Methode verwendet eine leere Vue-Instanz als zentralen Ereignisbus (Ereigniszentrum) und verwendet sie zum Auslösen von Ereignissen und zum Abhören von Ereignissen. Clever Es implementiert auf einfache Weise die Kommunikation zwischen allen Komponenten, einschließlich Eltern-Kind-, Bruder- und Ebenenübergreifender Kommunikation. Wenn unser Projekt relativ groß ist, können wir vuex wählen, eine bessere Lösung für die Zustandsverwaltung.

1. Spezifische Implementierungsmethode:

    var Event=new Vue();
    Event.$emit(事件名,数据);
    Event.$on(事件名,data => {});

2. Zum Beispiel: Es gibt drei Geschwisterkomponenten, nämlich A, B und C. Wie erhält Komponente C die Daten von Komponente A oder B?

<div>
    <my-a></my-a>
    <my-b></my-b>
    <my-c></my-c>
</div>
<template>
  <div>
    <h3>A组件:{{name}}</h3>
    <button>将数据发送给C组件</button>
  </div>
</template>
<template>
  <div>
    <h3>B组件:{{age}}</h3>
    <button>将数组发送给C组件</button>
  </div>
</template>
<template>
  <div>
    <h3>C组件:{{name}},{{age}}</h3>
  </div>
</template>
<script>
var Event = new Vue();//定义一个空的Vue实例
var A = {
    template: &#39;#a&#39;,
    data() {
      return {
        name: &#39;tom&#39;
      }
    },
    methods: {
      send() {
        Event.$emit(&#39;data-a&#39;, this.name);
      }
    }
}
var B = {
    template: &#39;#b&#39;,
    data() {
      return {
        age: 20
      }
    },
    methods: {
      send() {
        Event.$emit(&#39;data-b&#39;, this.age);
      }
    }
}
var C = {
    template: &#39;#c&#39;,
    data() {
      return {
        name: &#39;&#39;,
        age: ""
      }
    },
    mounted() {//在模板编译完成后执行
     Event.$on(&#39;data-a&#39;,name => {
         this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
     })
     Event.$on(&#39;data-b&#39;,age => {
         this.age = age;
     })
    }
}
var vm = new Vue({
    el: &#39;#itany&#39;,
    components: {
      &#39;my-a&#39;: A,
      &#39;my-b&#39;: B,
      &#39;my-c&#39;: C
    }
});    
</script>

Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

4. vuex

Detaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen)

1. Kurz vorstellen Das Prinzip von Vuex

Vuex implementiert einen unidirektionalen Datenfluss und verfügt über einen Status zum globalen Speichern von Daten. Wenn eine Komponente die Daten im Status ändern möchte, muss dies auch durch Mutation erfolgen Abonnentenmodus für externe Plug-Ins zum Aufrufen und Abrufen von Statusdaten. Wenn alle asynchronen Vorgänge (üblicherweise als Back-End-Schnittstellen zum asynchronen Erhalten aktualisierter Daten bezeichnet) oder synchrone Batch-Vorgänge eine Aktion erfordern, kann die Aktion den Status nicht direkt ändern und die Statusdaten müssen weiterhin durch Mutation geändert werden. Basierend auf den Zustandsänderungen wird es schließlich für die Ansicht gerendert.

2. Stellen Sie dabei kurz die Hauptfunktionen jedes Moduls vor:

  • Vue-Komponenten: Vue-Komponenten. Auf der HTML-Seite ist es dafür verantwortlich, interaktives Verhalten wie Benutzervorgänge zu empfangen und die Dispatch-Methode auszuführen, um die entsprechende Antwortaktion auszulösen.

  • Dispatch: Methode zum Auslösen des Betriebsverhaltens. Dies ist die einzige Methode, die Aktionen ausführen kann.

  • actions:操作行为处理模块,由组件中的$store.dispatch('action 名称', data1)来触发。然后由commit()来触发mutation的调用 , 间接更新 state。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。

  • commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。

  • mutations:状态改变操作方法,由actions中的commit('mutation 名称')来触发。是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。

  • state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。

  • getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

如果你想深入了解,请点击从头开始学习Vuex这篇文章

五、localStorage

1.简介

HTML5中新增了本地存储的解决方案----WebStorage,它分成两类:sessionStorage和localStorage。localStorage保存的数据长期存在,除非被清除,下一次访问该网站的时候,网页可以直接读取以前保存的数据

localStorage保存的数据,以“键值对”的形式存在。也就是说,每一项数据都有一个键名和对应的值。所有的数据都是以文本格式保存。
存入数据使用setItem方法。它接受两个参数,第一个是键名,第二个是保存的数据。
localStorage.setItem("key","value");
读取数据使用getItem方法。它只有一个参数,就是键名。
var valueLocal = localStorage.getItem("key");

如果想深入了解,请点击浏览器存储这篇文章

2.localStorage与Vuex区别

vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。

let defaultCity = "上海"
try {   // 用户关闭了本地存储功能,此时在外层加个try...catch
  if (!defaultCity){
    defaultCity = JSON.parse(window.localStorage.getItem('defaultCity'))
  }
}catch(e){}
export default new Vuex.Store({
  state: {
    city: defaultCity
  },
  mutations: {
    changeCity(state, city) {
      state.city = city
      try {
      window.localStorage.setItem('defaultCity', JSON.stringify(state.city));
      // 数据改变的时候把数据拷贝一份保存到localStorage里面
      } catch (e) {}
    }
  }
})

3.注意点

由于vuex里,我们保存的状态,都是数组,而localStorage只支持字符串,所以需要用JSON转换:

JSON.stringify(state.subscribeList);   // array -> string
JSON.parse(window.localStorage.getItem("subscribeList"));    // string -> array

六、$attrs/$listeners

1.简介

多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。但如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点大材小用。为此Vue2.4 版本提供了另一种方法,当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用

// demo.vue
  <template>
    <div>
      <foo>
    </foo>
</div>
  
  <script>
  const childCom = ()=> import(&#39;./childCom1.vue&#39;)
  export default {
    data () {
      return {
        foo: &#39;Hello World!&#39;,
        boo: &#39;Hello Javascript!&#39;,
        coo: &#39;Hello Vue&#39;,
        doo: &#39;Last&#39;
      }
    },
    components: { childCom }
  }
  </script></template>
// childCom1.vue
<template>
  <div>
    <p>foo: {{ foo }}</p>
    <p>attrs: {{ $attrs }}</p>
    <child-com2></child-com2>
  </div>
</template>
<script>
const childCom2 = ()=> import(&#39;./childCom2.vue&#39;)
export default {
  props: [&#39;foo&#39;],  // foo作为props属性绑定
  inheritAttrs: false,
  created () {
    console.log(this.$attrs) // { boo: &#39;Hello Javascript!&#39;, coo: &#39;Hello Vue&#39;, doo: &#39;Last&#39; }
  }
}
</script>
// childCom2.vue
<template>
  <div>
   <p>boo: {{ boo }}</p>
   <p>attrs: {{ $attrs }}</p>
   <child-com3></child-com3>
  </div>
</template>
<script>
const childCom3 = ()=> import(&#39;./childCom3.vue&#39;)
export default {
  props: [&#39;boo&#39;] // boo作为props属性绑定
  inheritAttrs: false,
  created () {
    console.log(this.$attrs) // { coo: &#39;Hello Vue&#39;, doo: &#39;Last&#39; }
  }
}
</script>

<span style="font-family: 微软雅黑, Microsoft YaHei;">$attrs表示没有继承数据的对象,格式为{属性名:属性值}。Vue2.4提供了$attrs , $listeners 来传递数据与事件,跨级组件之间的通讯变得更简单</span>

七、provide/inject

1.简介

Vue2.2.0新增API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。

2.举个例子

// 父组件
  export default {
    name: "Parent",
    provide: {
      parent: "父组件的值"
    }
  }
// 子组件
 export default {
    name: "",
    inject: ['parent'],
    data() {
      return {
        demo: this.parent //"父组件的值"
      }
    }
  }

上例中子组件中inject注入了父组件provide提供的变量parent,并将它提供给了data属性

如果需要源代码,请戳源代码

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die Vue-Datenkommunikation (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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