Vue组件通信

Vue组件通信主要分为以下几种:
  1. 父子级通信推荐使用:props/$emit、$parent/$children/$refs、$attrs/$listeners
  2. 兄弟组件通信推荐使用:$emit/$on、Vuex
  3. 无关系组件通信推荐使用:$emit/$on、Vuex、$attrs/$listeners、provide/inject

1、props和$emit(父子组件通信)

子组件使用props 接收父组件传递的值(父组件向子组件传值)。子组件通过 $emit ,让父组件接收事件,改变父组件的data里面的值(子组件向父组件传值)。

⚠️注意

prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。

  1. 不应该在一个子组件内部改变 prop,这样会破坏单向的数据绑定,导致数据流难以理解。如果有这样的需要,可以通过 data 属性接收或使用 computed 属性进行转换。
  2. 如果 props 传递的是引用类型(对象或者数组),在子组件中改变这个对象或数组,父组件的状态会也会做相应的更新,利用这一点就能够实现父子组件数据的“双向绑定”,虽然这样实现能够节省代码,但会牺牲数据流向的简洁性,令人难以理解,最好不要这样去做。
  3. 想要实现父子组件的数据“双向绑定”,可以使用 v-model 或 .sync。

父组件:

<template>
  <div>
    <input type="text" v-model="name">
    <!-- 引入子组件,:childName这个就是子组件接收的参数名 -->
    <child :childName="name" @change='changeHandle'></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: '父组件传给子组件的name'
      }
    },
    methods: {
        changeHandle(val) {
          this.name = val;
        }
    }
  }
</script>

子组件:

<template>
  <div>
    <span>{{inputName}}</span>
  </div>
</template>
<script>
  export default {
    // 通过props接收父组件的值
    props: {
      inputName: String
    },
    methods: {
       changeHandle() { 
         this.$emit('change', '123');
      }
    }
  }
</script>

这里的props有两种写法对象和数组,用法不一样,效果都一样。这里我就直接把官方的解释贴出来吧

2、$emit和$on(兄弟、非父子组件间通信)

通过创建一个包含Vue 的实例的eventBus中间仓库,用来触发事件和监听事件,实现兄弟、非父子组件的通信。当组件A执行setValue方法触发了$emit后,会触发组件B中的$on监听事件。

bus.js:

import Vue from 'vue'
export default new Vue()

组件A:

<template>
  <div>
    <span>{{val}}</span>
    <input type="button" value="setter" @click="setValue">
  </div>
</template>
<script>
  // 引入公共的bus,来做为中间传值的工具
  import Bus from './bus.js'
  export default {
    data () {
      return {
        val: 123
      }
    },
    methods: {
      setValue: function () {
        Bus.$emit('valKey', this.val)
      }
    }
  }
</script>

组件B:

<template>
  <div>
    <span>{{val}}</span>
  </div>
</template>
<script>
  import Bus from './bus.js'
  export default {
    data () {
      return {
        val: 0
      }
    },
    mounted: function () {
      // 用$on事件来接收参数
      Bus.$on('valKey', (data) => {
        this.val = data
      })
    }
  }
</script>

3、Vuex

Vuex 是一个单向的数据流的状态管理模式,state 存放数据,当需要改变state 的数据时,只能通过 mutation 更改,如果有异步操作,可以使用 action,最终action 还是通过mutation 更改state 的数据。

  • Vue Components:Vue 组件,可以执行dispatch 方法触发action;

  • dispatch:组件触发action 的方法;

  • actions:负责接收组件触发的行为,可以在这里面调用commit()方法更改state中的数据;

  • commit:执行mutation的方法,commit('mutation 名称');

  • mutations:更改 state 数据的方法,只能进行同步操作;

  • state:存储数据的容器对象;

4.、$parent和$children(父子组件通信)

$parent和$children 可以访问到父组件或子组件(数组)的实例,所以也可以用作通信。$children和$ref的区别在于一个是返回所有子组件,一个是指定的子组件。

<!--父组件A-->
<template> 
    <h1> 父组件 </h1 >
    <child ref = "child" ></child> 
</template >
<script > 
    export default {
        components:    {
          child
        },
        mounted() {
            console.log(this.$children);
            // 子组件实例数组
            console.log(this.$refs.child);
            // 子组件child实例
        }
      }
</script> 
<!--子组件child--> 
<template> 
   <h1> 子组件 </h1>
</template> 
<script>
    export default{
        mounted() {
            console.log(this.$parent);
            // 父组件实例
        }
    }
</script>

5、$attrs/$listeners

this.$attrs 包含了父作用域中不作为prop被识别的特性绑定(class和style除外),解释就是,父组件传递了props ,但是子组件没有全部使用props 接收,没被子组件接收的那些props,在$attrs中就可以获取到;$listeners 即是包含了父作用域中的(不含.native修饰器的)v-on 事件监听器,可以使用 v-on='$listeners'传入到内部组件;在跨级组件中传递属性和事件非常有用。

< !--顶级组件A-->
<template >
    <!--组件B-->
    <componentb data1="data1" data2="data2" @="" event1="handleEvent1" event2="handleEvent2"></componentb>
</template>

<script>
export default
    {
        data() {
            return {
                data1: 'data1',
                data2: 'data2'
            };
        },
        components: {
            componentb
        },
        mounted() {
            handleEvent1() {
                console.log('子级组件触发的事件');
            },
            handleEvent2() {
                console.log('孙子级组件触发的事件');
            }
        }
    }
</script>

<!--子组件B-->
<template> 
    <h1>data1的值:{{data1}} </h1>
    <!--组件C-->
    <componentc v-bind="$attrs" v-on="$listeners"></componentc>
</template>
<script>
    export default {
        props: {
            data1 // 这里只获取了父级传递的props的data1属性
        },
        components: {
            componentc
        },
        mounted() {
            console.log(this.$attrs); // 可以打印出 'data2'
        }
    }
</script>

<!--孙子组件c-->
<template>
</template>
<script>
    export default {
        props: {
            'data2'
        },
        mounted() {   
            this.$emit('event2');
        }
    }
</script> 

6. provide和inject

祖先组件通过 provide 向子孙级组件提供一个对象或返回一个对象的函数,该对象包含可以注入子孙组件的属性。

Vue 不建议直接应用于程序代码中,主要是为高阶插件/组件库提供使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值