Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue组件中通信 #28

Open
Geek-James opened this issue Aug 22, 2019 · 0 comments
Open

vue组件中通信 #28

Geek-James opened this issue Aug 22, 2019 · 0 comments
Labels
Vue About Vue

Comments

@Geek-James
Copy link
Owner

Geek-James commented Aug 22, 2019

本文总结了vue组件间通信的几种方式,如props$emit/$onvuex$parent / $children$attrs/$listeners和provide/inject,以通俗易懂的实例讲述这其中的差别及使用场景,希望对小伙伴有些许帮助。

组件之间通信是Vue中最常用,最基础的部分,通常组件之前的通信分为以下几种:

  • 1.父组件给子组件以及子子组件传递值,传递事件
  • 2.子组件给父组件传递值,传递事件
  • 3.兄弟组件之间传递值,传递事件

方法一、props/$emit

1.父组件给子组件传值

父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。

子组件使用this.$emit('function',param)向父组件传值

父组件通过v-on:function="function"来接受子组件传递过来的值

接下来我们通过一个例子来加深以上理解:

自定义一个Son.vue子组件,引入到父组件中
在父组件中定义一个数据

<template>
    <div id="app">
        <!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
        <son v-bind:user="user"></son>  
    </div>
</template>
<script>
import Son from './components/Son'

export default {
    name: 'app',
    components: {
        Son,
    },
    data () {
        return { // 父组件定义数据,传递给子组件
            user: ["james", "alice", "joho"]
        }
    },
  }
</script>
    

子组件中通过prop来定义父组件传值的值类型,是否是必须以及默认值

<script>
export default {
    components: {

    },
    data () {
        return {

        };
    },
    computed: {

    },
    methods: {
    },
    props: {
        user: { //这个就是父组件中子标签自定义名字
            type: Array,
            required: true,
            default: []
        }
    },
}
</script>

然后在适当的位置将父组件传递过来的数据进行渲染

<template>
    <div>
        <ul>
            <li v-for="(item,index) in user"
                :key="index">姓名:{{item}}</li>
        </ul>

    </div>
</template>

浏览器打开会显示user里面的值.

总结:父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed

2.子组件向父组件传值(通过事件形式)

我们通过一个案例来说明子组件是如何给父组件传递值的,点击子组件的按钮,子组件向父组件传递值,然后改变父组件里文字的值.

子组件中:

子组件包含一个点击事件

// 定义一个点击事件
 <son v-bind:user="user"
             @titleChange="changeTitle">
</son>

在点击事件中通过this.$emit()来传递事件

<script>
//import x from ''
export default {
    components: {

    },
    data () {
        return {
            title: '我是子组件',
            toParentData: '我是子组件传递的数据'
        };
    },
    computed: {

    },
    methods: {
        btnClick () {
            this.$emit('titleChange', this.toParentData);
        }
    },
    }
</script>

父组件中:
通过v-on来接受子组件发出的事件名称:titleChange并且和自己的changeTitle事件绑定

<template>
    <div id="app">
        <!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
        <son v-bind:user="user"
             v-on:titleChange="changeTitle"></son>
        <p>{{msg}}</p>
    </div>
</template>

实现changeTitle方法,改变data中的msg数据

<script>
import Son from './components/Son'

export default {
    name: 'app',
    components: {
        Son,
    },
    data () {
        return {
            user: ["james", "alice", "joho"],
            msg: '我是父组件显示的内容'
        }
    },
    methods: {
        changeTitle (title) {
            this.msg = title;
        }
    }
}
</script>

总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。

中央事件总线 Bus 进行通信

子孙的链式通信显然会使得组件紧耦合,同时兄弟组件间的通信该如何实现呢?这里介绍中央事件总线的方式,实际上就是用一个vue实例(Bus)作为媒介,需要通信的组件都引入 Bus,之后通过分别触发和监听 Bus 事件,进而实现组件之间的通信和参数传递。

  • 1.首先建 Vue 实例作为总线:
// Bus.js
import Vue from 'vue'
export default new Vue;
  • 2.需要通信的组件都引入 Bus.js,使用 $emit发送信息:
// ComponentA.vue
<template>
  <div>
    <b>组件A:</b><button @click="handleBus">传递数值给需要的组件</button>
  </div>
</template>

<script>
  import Bus from './bus.js' 
  export default {
    methods: {
      handleBus () {
        Bus.$emit('someBusMessage','来自ComponentA的数据')
      }
    }
  }
</script>
  • 3.需要组件A信息的就使用$on来监听:
// ComponentB.vue
<template>
  <div>
    <b>组件B:</b><button @click="handleBus">接收组件A的信息</button>
    <p>{{message}}</p>
  </div>
</template>

<script>
  import Bus from './bus.js' 
  export default {
    data() {
      return {
        message: ''
      }
    },
    created () {
      let that = this // 保存当前对象的作用域this
      Bus.$on('someBusMessage',function (data) {
        that.message = data
      })
    },
    beforeDestroy () {
      // 手动销毁 $on 事件,防止多次触发
      Bus.$off('someBusMessage', this.someBusMessage)
    }
  }
</script>

常见使用场景可以分为三类:

  • 父子通信:
    父向子传递数据是通过 props,子向父是通过 events($emit);
    通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
  • 兄弟通信:
    Bus;Vuex
  • 跨级通信:
    Bus;Vuex;provide / inject API、$attrs/$listeners

参考资料:https://juejin.im/post/5cde0b43f265da03867e78d3

@Geek-James Geek-James added the Vue About Vue label Aug 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Vue About Vue
Projects
None yet
Development

No branches or pull requests

1 participant