组件数据通信方案总结

本文目录:

  • 1.父组件向子组件传值及优化
  • 2.子组件向父组件传数据
  • 3.prop单向数据流
  • 4.Prop / $emit
  • 5.emit` / `on`
  • 6.Vuex
  • 7.其他常见方法
  • 8.总结

1.父组件向子组件传值及优化

父组件向子组件传数据口诀:冒号传,props收,子组件内部就可以重新使用了
子组件top组件结构代码

<div class="header">
    <div class="personal" @click="goToUsercenter">我     的</div>
    <div>MIKO</div>
    <i class="iconfont icon-chaxun" @click="goToSearch"></i>
</div>

这个top组件的标题,图片地址,和总计歌曲数量都是由使用它的父组件传递进来的
其props代码如下

props: {
   title: {
      type: String,
      default: ""
   },
   img: {
      type: String,
      default: ""
   },
   count: {
       type: Number,
       default: 0
   }
}

不设定默认值的写法:

props: {
  title: String,
  img: String,
  count: Number
}

引用它的父组件标签代码
<top :title="title" :img="img" :count="formatData.length"></top>
title和img可以直接是data中的变量,但是这样写不是很完善,如:
<top :title="formatData[0].name" :img="formatData[0].al.picUrl" :count="formatData.length"></top>
为了优化体验,也可以设定在computed中:

computed: {
    title() {
       if (this.formatData.length > 0) {
           return this.formatData[0].name;
       } else {
           return "暂无数据";
       }
    }
}

如果既想优化代码,又不想使用computed,也可以用v-if
<top v-if="formatData.length" :title="formatData[0].name" :img="formatData[0].al.picUrl" :count="formatData.length"></top>

2.子组件向父组件传数据

子组件向父组件传递消息,是通过子组件调用父组件的事件,然后用参数的形式传递的
需求:子组件的按钮点击触发自定义事件_event,同时把自身的数据“xiaohong”传递出去,父组件接收这个数据并且进行使用
子组件代码
<button @click="$emit('_myevent', 'nodeing')">点击</button>
父组件代码在调用子组件的标签中通过自定义事件触发自身的事件:
<children-component @_myevent="sayhi"></children-component>
触发了自身的的sayhi事件:

methods: {
   sayhi(name){
        alert('hi,' + name)
   }
}

3.prop单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。
这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。 在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

2.这个 prop 以一种原始的值传入且需要进行转换。 在这种情况下,最好使用这个 prop 的值来定义一个计算属性

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

以上的是最常用的两种父子组件传值的方法,实际项目中的组件关系不止是父子关系,还有其他更复杂的关系,下面是对常见的组件通信方案的总结:

4.Prop / $emit

1、 Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 Prop 特性的时候,它就变成了那个组件实例的一个属性 。父组件向子组件传值,通过绑定属性来向子组件传入数据,子组件通过 props 属性获取对应数据。
父组件代码:
<child :title="title"></child>
子组件代码:

props: {
  title: {
    type: String
  }
}

2、emit 子组件向父组件传值(通过事件形式),子组件通过emit 事件向父组件发送消息,将自己的数据传递给父组件。
父组件代码

<child @changeTitle="parentTitle"></child>
......
parentTitle(e) {
  this.title = e;
}

子组件代码

<button @click="childTitle">我给父组件赋值</button>

childTitle(){
  this.$emit('changeTitle', 'new-title')
}

5.$emit / $on

这个方法是通过创建了一个空的 vue 实例,当做 $emit 事件的处理中心(事件总线),通过他来触发以及监听事件,方便的实现了任意组件间的通信,包含父子,兄弟,隔代组件。
父组件代码

<template>
  <div class="container">
    <child1 :Event="Event"></child1>
    <child2 :Event="Event"></child2>
    <child3 :Event="Event"></child3>
  </div>
</template>
<script>
import Vue from "vue";
import Child1 from "./component/child1.vue";
import Child2 from "./component/child2.vue";
import Child3 from "./component/child3.vue";
const Event = new Vue();
export default {
  name: "demo",
  data: function() {
    return {
      Event: Event
    };
  },
  components: {
    Child1,
    Child2,
    Child3
  },
};
</script>

子组件child1.vue代码

<template>
  <div class="center">
    1.我的名字是:{{name}}
    <button @click="send">我给3组件赋值</button>
  </div>
</template>
<script>
export default{
  name: "demo1",
  data() {
    return {
      name: "大卫"
    };
  },
  props: {
    Event
  },
  methods: {
    send() {
      this.Event.$emit("message-a", this.name);
    }
  }
};
</script>

子组件child2.vue代码

<template>
  <div class="center">
    2.我的年龄是:{{age}}岁
    <button @click="send">我给组件3赋值</button>
  </div>
</template>
<script>
/* eslint-disable */
export default {
  name: "demo2",
  data() {
    return {
      age: "3"
    };
  },
  props: {
    Event
  },
  methods: {
    send() {
      this.Event.$emit("message-b", this.age);
    }
  }
};
</script>

子组件child3.vue代码

<template>
  <div class="center">我的名字是{{name}},今年{{age}}岁</div>
</template>
<script>
export default{
  name: 'demo3',
  data() {
    return {
      name: '',
      age: ''
    };
  },
  props: {
    Event
  },
  mounted() {
    this.Event.$on('message-a', name => {
      this.name = name;
    });
    this.Event.$on('message-b', age => {
      this.age = age;
    });
  },
};
</script>

总结:巧妙的在父子,兄弟,隔代组件中都可以互相数据通信。

6.Vuex

Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 实现了一个单项数据流,通过创建一个全局的 State 数据,组件想要修改 State 数据只能通过 Mutation 来进行,例如页面上的操作想要修改 State 数据时,需要通过 Dispatch (触发 Action ),而 Action 也不能直接操作数据,还需要通过 Mutation 来修改 State 中数据,最后根据 State 中数据的变化,来渲染页面。
Vuex的详细用法见文集《Vue全家桶》中的文章《详解Vuex》。

7.其他常见方法

  • $attrs / $listeners
  • Provider / Inject
  • $parent / $children & $refs

$parent / $children: 指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用 this.$parent 访问父实例,子实例被推入父实例的 $children 数组中。
$refs: 一个对象,持有注册过 ref 特性的所有 DOM 元素和组件实例。ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件。
父组件代码

<template>
  <div class="container">
    <p>我的title:{{title}}</p>
    <p>我的name:{{name}}</p>
    <child1 ref="comp1"></child1>
    <child2 ref="comp2"></child2>
  </div>
</template>
<script>
import Child1 from './component/child1.vue';
import Child2 from './component/child2.vue';
export default {
  name: 'demo',
  data: function() {
    return {
      title: null,
      name: null,
      content: '就是我'
    };
  },
  components: {
    Child1,
    Child2
  },
  mounted() {
    const comp1 = this.$refs.comp1;
    this.title = comp1.title;
    comp1.sayHello();
    this.name = this.$children[1].title;
  },
};
</script>

子组件1:ref方式

<template>
  <div>
    <div class="center">我的父组件是谁:{{content}}</div>
  </div>
</template>

<script>
export default {
  name: 'demo1',
  data() {
    return {
      title: '我是子组件',
      content: null
    };
  },
  mounted() {
    this.content = this.$parent.content;
  },
  methods: {
    sayHello() {
      window.alert('Hello');
    }
  }
};
</script>

子组件2:children方式

<template>
  <div>
    <div class="center"></div>
  </div>
</template>

<script>
export default{
  name: 'demo2',
  data() {
    return {
      title: '我是子组件2'
    };
  },
};
</script>

通过例子可以看到这两种方式都可以父子间通信,而缺点也很统一,就是都不能跨级以及兄弟间通信。
小总结:父子组件间共享数据以及方法的便捷实践之一。

8.总结

组件间不同的使用场景可以分为 3 类,对应的通信方式如下:
• 父子通信:Props / $emit$emit / $on,Vuex,$attrs / $listeners,provide/inject,$parent / $children$refs
• 兄弟通信:$emit / $on,Vuex
• 隔代(跨级)通信:$emit / $on,Vuex,provide / inject,$attrs / $listeners
大家可以根据自己的使用场景选择不同的通信方式,当然还是要自己写写代码,试验一把来的印象深刻。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引...
    用技术改变世界阅读 6,526评论 1 3
  • vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢?首...
    云翼飞阅读 3,616评论 0 0
  • 原文地址 vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通...
    lovelydong阅读 2,976评论 0 0
  • vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢?首...
    咿呀咿呀_b53d阅读 5,028评论 0 18
  • 人总是在接近幸福时倍感幸福,在幸福进行时却患得患失。 特质的东北风味面食,打上鸡蛋,加上热狗、鸡柳,秘诀在于香甜的...
    Cassie_7434阅读 1,670评论 0 1