vue组件间的通信方法

vue组件间的通信方法有:

  1. 访问根组件: this.$root
  2. 访问父组件: this.$parent
  3. 使用ref访问组件
  4. props / $emit(常用)
  5. $attrs 和 $listeners
  6. provide 和 inject
  7. eventBus
  8. 自己实现简单的 Store 模式
  9. Vuex
$ref只能在mounted生命周期钩子函数被调用之后才能使用 
$root和$parent在各个生命周期钩子函数中都可以使用

1.访问根组件

//获取根组件的数据
this.$root.info;
//写入根组件数据
this.$root.info = 2;
//访问根组件的计算属性
this.$root.sm;
//调用根组件的方法
this.$root.prism();

当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

2.访问父组件

//获取父组件的数据
this.$parent.info;
//写入父组件数据
this.$parent.info = 2;
//访问父组件的计算属性
this.$parent.sm;
//调用父组件的方法
this.$parent.prism();

3.使用ref访问组件

<base-input ref="nameInput"></base-input>
this.$ref.nameInput.focus();

4.父子组件传值

  • 父组件向子组件传值
//父组件
<template>
  <div>
    <users :users="users"></users>
  </div>
</template>
<script>
import Users from "./components/Users"
export default {
    
    
  name: 'index',
  data(){
    
    
    return{
    
    
      users:["Henry","Bucky","Emily"]
    }
  },
  components:{
    
    
    "users":Users
  }
}
//users子组件
<template>
  <div class="hello">
    <ul>
      <li v-for="user in users">{
    
    {
    
    user}}</li>
    </ul>
  </div>
</template>
<script>
export default {
    
    
  name: 'HelloWorld',
  props:{
    
    
    users:{
    
    
      type:Array,
      required:true
    }
  }
}
</script>
  • 子组件向父组件传值(通过事件形式)
    子组件通过事件把数据传给父组件
// 子组件
<template>
  <header>
    <h1 @click="changeTitle">{
    
    {
    
    title}}</h1>//绑定一个点击事件
  </header>
</template>
<script>
export default {
    
    
  name: 'app-header',
  data() {
    
    
    return {
    
    
      title:"Vue.js Demo"
    }
  },
  methods:{
    
    
    changeTitle() {
    
    
      this.$emit("titleChanged","子向父组件传值");
    }
  }
}
</script>
// 父组件
<template>
  <div id="app">
    <app-header @titleChanged="updateTitle" ></app-header>
    //titleChanged与子组件$emit里的一样
    <h2>{
    
    {
    
    title}}</h2>
  </div>
</template>
<script>
import Header from "./components/Header"
export default {
    
    
  name: 'App',
  data(){
    
    
    return{
    
    
      title:"传递的是一个值"
    }
  },
  methods:{
    
    
    updateTitle(e){
    
       //声明这个函数
      this.title = e;
    }
  },
  components:{
    
    
   "app-header":Header,
  }
}
</script>

5.$attrs 和 $listeners

当要和一个嵌套很深的组件进行通信时,如果使用 prop 和 events 就会显的十分繁琐,中间的组件只起到了一个中转站的作用,像下面这样:

<!--父组件-->
  <parent-component :message="message">我是父组件</parent-component>
<!--子组件-->
  <child-component :message="message">我是子组件</child-component>
<!--孙子组件-->
  <grand-child-component :message="message">我是孙子组件</grand-child-component>
$attrs 会包含父组件中没有被 prop 接收的所有属性(不包含class 和 style 属性),可以通过 v-bind="$attrs" 直接将这些属性传入内部组件。
$listeners 会包含所有父组件中的 v-on 事件监听器 (不包含 .native 修饰器的) ,可以通过 v-on="$listeners" 传入内部组件。

下面以父组件和孙子组件的通信为例介绍它们的使用:


<!--父组件 parent.vue-->
<template>
    <child :name="name" :message="message" @sayHello="sayHello"></child>
</template>
<script>
export default {
    
    
    inheritAttrs: false,
    data() {
    
    
        return {
    
    
            name: '通信',
            message: 'Hi',
        }
    },
    methods: {
    
    
        sayHello(mes) {
    
    
            console.log('mes', mes) // => "hello"
        },
    },
}
</script>
<!--子组件 child.vue-->
<template>
    <grandchild v-bind="$attrs" v-on="$listeners"></grandchild>
</template>
<script>
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
    props: {
    
    
        name,
    },
}
</script>
<!--孙子组件 grand-child.vue-->
<template>
</template>
<script>
export default {
    
    
    created() {
    
    
        this.$emit('sayHello', 'hello')
    },
}
</script>

6.provide 和 inject

provideinject 需要在一起使用,它可以使一个祖先组件向其所有子孙后代注入一个依赖,可以指定想要提供给后代组件的数据/方法,不论组件层次有多深,都能够使用。

<!--祖先组件-->
<script>
export default {
    
    
    provide: {
    
    
        author: 'qzx',
    },
    data() {
    
    },
}
</script>
<!--子孙组件-->
<script>
export default {
    
    
    inject: ['author'],
    created() {
    
    
        console.log('author', this.author) // => qzx
    },
}
</script>

7.eventBus

对于比较小型的项目,没有必要引入 vuex 的情况下,可以使用 eventBus。相比我们上面说的所有通信方式,eventBus 可以实现任意两个组件间的通信

它的实现思想也很好理解,在要相互通信的两个组件中,都引入同一个新的vue实例,然后在两个组件中通过分别调用这个实例的事件触发和监听来实现通信。

//eventBus.js
import Vue from 'vue';
export default new Vue();
<!--组件A-->
<script>
import Bus from 'eventBus.js';
export default {
    
    
    methods: {
    
    
        sayHello() {
    
    
            Bus.$emit('sayHello', 'hello');
        }
    }
}
</script>
<!--组件B-->
<script>
import Bus from 'eventBus.js';
export default {
    
    
    created() {
    
    
        Bus.$on('sayHello', target => {
    
    
            console.log(target);  // => 'hello'
        });
    }
}
</script>

8.自己实现简单的 Store 模式

对于小型的项目,通信十分简单,这时使用 Vuex 反而会显得冗余和繁琐,这种情况最好不要使用 Vuex,可以自己在项目中实现简单的 Store。

//store.js
var store = {
    
    
  debug: true,
  state: {
    
    
    author: 'yushihu!'
  },
  setAuthorAction (newValue) {
    
    
    if (this.debug) console.log('setAuthorAction triggered with', newValue)
    this.state.author = newValue
  },
  deleteAuthorAction () {
    
    
    if (this.debug) console.log('deleteAuthorAction triggered')
    this.state.author = ''
  }
}

和 Vuex 一样,store 中 state 的改变都由 store 内部的 action 来触发,并且能够通过 log 保留触发的痕迹。这种方式十分适合在不需要使用 Vuex 的小项目中应用

9.Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。对一个中大型单页应用来说是不二之选。

使用 Vuex 并不代表就要把所有的状态放入 Vuex 管理,这样做会让代码变的冗长,无法直观的看出要做什么。对于严格属于组件私有的状态还是应该在组件内部管理更好。

猜你喜欢

转载自blog.csdn.net/baidu_39009276/article/details/123552915