Maison  >  Article  >  interface Web  >  Introduction détaillée à la communication de données Vue (avec exemples)

Introduction détaillée à la communication de données Vue (avec exemples)

不言
不言avant
2018-11-20 14:27:272559parcourir

Cet article vous apporte une introduction détaillée à la communication de données Vue (avec des exemples). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1. Introduction

Les composants sont l'une des fonctionnalités les plus puissantes de vue.js, et les portées des instances de composants sont indépendantes les unes des autres, ce qui signifie que les différents composants Les données ne peuvent pas se référencer. La manière de transférer les données entre les composants est cruciale. Cet article tente de répertorier certaines méthodes courantes de transfert de données, telles que les accessoires, $emit/$on et vuex, ainsi que les nouveaux $attrs/$listeners et provide/inject, et les décrit de manière simple. comprendre les exemples. La différence, j'espère que cela pourra être utile à mes amis.

2. Props

Le composant parent A passe au composant enfant B via les accessoires, et B à A est implémenté via $emit dans le composant B et v-on dans le composant A.

Prop est lié à sens unique. Lorsque les propriétés du composant parent changent, elles seront transmises au composant enfant, mais pas l'inverse.
Et il n'est pas autorisé de changer de prop directement à l'intérieur d'un. composant enfant, sinon il signalera une erreur. Puis parfois si on veut modifier le prop passé, il y a les méthodes suivantes :

Méthode 1 : Si le sous-composant veut l'utiliser comme donnée locale, vous pouvez stocker les données dans une autre variable puis opérer cela affecte les données du composant parent.

    <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>

Bien que cette méthode puisse affecter les données transmises par le composant parent en exploitant une autre variable, un gros inconvénient est qu'à partir de maintenant, le composant enfant ne peut pas changer à mesure que les données du composant parent changent. À l'heure actuelle, si vous utilisez des propriétés calculées, bien que les modifications puissent être synchronisées, le sous-composant ne peut pas modifier les données transmises. Cette méthode est donc moins couramment utilisée.

Méthode 2 : Si le composant enfant souhaite modifier les données et les mettre à jour de manière synchrone avec le composant parent, il existe deux méthodes :

Utiliser .sync (pris en charge dans la version). 1.0, pas dans la version 2.0. Pris en charge (à nouveau pris en charge dans la version 2.3) doit déclencher explicitement un événement de mise à jour.

<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>

Introduction détaillée à la communication de données Vue (avec exemples)

b Vous pouvez envelopper les données du composant parent dans un objet, puis modifier l'objet. dans les attributs du composant enfant (car l'objet est un type référence et pointe vers le même espace mémoire), il est recommandé de

<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>

Introduction détaillée à la communication de données Vue (avec exemples)

Cela est dû au fait que les objets et les tableaux sont transmis par référence en JavaScript, donc pour un accessoire de type tableau ou objet, la modification de l'objet ou du tableau lui-même dans le composant enfant affectera l'état de le composant parent.

3. $emit/$on

Cette méthode utilise une instance Vue vide comme bus d'événements central (centre d'événements) et l'utilise pour déclencher des événements et écouter des événements, intelligemment, il implémente de manière légère la communication entre tous les composants, y compris parent-enfant, frère et niveau croisé. Lorsque notre projet est relativement volumineux, nous pouvons choisir vuex, une meilleure solution de gestion d'état.

1. Méthode d'implémentation spécifique :

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

2. Par exemple : il existe trois composants frères, à savoir A, B et C. Comment le composant C obtient-il les données du composant A. ou 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>

Introduction détaillée à la communication de données Vue (avec exemples)

4. >1. Présentez brièvement le principe de Vuex

Vuex implémente un flux de données unidirectionnel et dispose d'un état pour stocker les données globalement. Lorsqu'un composant souhaite modifier les données dans l'état, cela doit être fait via Mutation. Mutation fournit également un mode abonné pour les appels de plug-in externes afin d'obtenir des mises à jour des données d'état. Lorsque toutes les opérations asynchrones (communément appelées interfaces back-end pour obtenir des données mises à jour de manière asynchrone) ou les opérations synchrones par lots nécessitent une action, l'action ne peut pas modifier directement l'état et les données d'état doivent toujours être modifiées via Mutation. Enfin, en fonction des changements d'état, il est rendu à la vue. Introduction détaillée à la communication de données Vue (avec exemples)2. Présentez brièvement les principales fonctions de chaque module dans le processus :

Composants Vue : composants Vue. Sur la page HTML, il est responsable de la réception des opérations utilisateur et d'autres comportements interactifs, et de l'exécution de la méthode de répartition pour déclencher l'action correspondante pour répondre.

dispatch : méthode de déclenchement du comportement d'opération, qui est la seule méthode capable d'exécuter des actions.
  • 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属性

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

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