专栏首页菜鸟计划vue组件详解(三)——组件通信

vue组件详解(三)——组件通信

组件之间通信可以用下图表示:

组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。

一、自定义事件

当子组件需要向父组件传递数据时,就要用到自定义事件。

子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件。

父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如:

        <div id="app9">
            <p>总数:{{total}}</p>
            <my-component9 @add="getTotal" @cut="getTotal"></my-component9>
        </div>
Vue.component('my-component9',{
    template: '<div>' +
    '               <button @click="increase">+1</button>' +
    '               <button @click="reduce">-1</button>' +
            '</div>',
    data: function(){
        return {
            count: 0
        }
    },
    methods:{
        increase: function(){
            this.count++;
            this.$emit('add',this.count)  //广播的事件名和数据
        },
        reduce: function(){
            this.count--;
            this.$emit('cut',this.count)  //广播的事件名和数据
        }
    }
});

var app9 = new Vue({
    el: '#app9',
    data:{
        total: 0
    },
    methods:{
        getTotal: function(count){
            this.total = count;
        }
    }
});

二、使用v-model

Vue2 .x 可以在自定义组件上使用v-model 指令,直接看一个事例:

        <div id="app10">
            <p>总数:{{total}}</p>
            <my-component10 v-model="total"></my-component10>  //这个地方v-model实际是一个语法糖,可以直接理解为接收到广播input里面的数据(this.total=count)。
        </div>
Vue.component('my-component10',{
    template: '<div>' +
                '<button @click="increase">+1</button>' +
                '<button @click="reduce">-1</button>' +
              '</div>',
    data: function(){
        return {
            count: 0
        }
    },
    methods:{
        increase: function(){
            this.count++;
            this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input
        },
        reduce: function(){
            this.count--;
            this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input
        }
    }
});

var app10 = new Vue({
    el: '#app10',
    data:{
        total: 0
    }
});

 v-model 还可以用来创建自定义的表单输入组件, 进行数据双向绑定,例如:

        <div id="app11">
            <p>总数:{{total}}</p>
            <my-component11 v-model="total"></my-component11>
            <button @click="reduce">-1</button>
        </div>
Vue.component('my-component11', {
    props: ['value'],  //使用v-model的表单组件时,父组件通过value来进行传值
    template: '<input :value="value" @input="updateValue">',
    methods: {
        updateValue: function(event){
            this.$emit('input', event.target.value);
        }
    }
});

var app11 = new Vue({
   el: '#app11',
   data:{
      total: 0
    },
    methods:{
        reduce: function(){
            this.total--
        }
    }
});

父组件的total发生变化时,会通过传递value值,影响子组件input中的value值,而子组件改变自己input中的value值,又会广播给父组件,影响父组件中的total值。

实现这样一个具有双向绑定的v -model 组件要满足下面两个要求:

•接收一个value 属性。 • 在有新的value 时触发input 事件。

三、非父子组件通信

在Vue . 2.x 中, 推荐使用一个空的Vue 实例作为中央事件总线( bu s ),也就是一个中介。

直接看一个事例:

        <div id="app12">
            <p>{{message}}</p>
            <my-component12></my-component12>
        </div>
var bus = new Vue();

Vue.component('my-component12',{
   template: '<button @click="updateMessage">传递事件信息</button>',
    methods: {
        updateMessage: function(){
            bus.$emit('updateMessage','更新我的组件信息');   //利用中介bus传播事件
        }
    }
});

var app12 = new Vue({
   el: '#app12',
   data:{
        message: ''
    },
    mounted: function(){
        var _this = this;   //这一步赋值必须有
        bus.$on('updateMessage',function(data){     //利用中介bus接收事件
            _this.message = data;
        })
    }
});

在app 初始化时,也就是在生命周期mounted 钩子函数里监听了来自bus 的事件updateMessage(mounted挂载这一步相当于在两个组件直间提前安排了一个中介,当两个组件通信时,就可以通过该中介相互传递消息了) ,

而在组件my-component12中,点击按钮会通过bus 把事件updateMessage发出去,此时app 就会接收到来自bus 的事件,进而在回调里完成自己的业务逻辑。

这种方法巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级,而且Vue 1.x 和Vue 2.x 都适用。

四、父链与子组件索引

除了中央事件总线bus 外,还有两种方法可以实现组件间通信:父链和子组件索引。

在子组件中,使用this.$parent 可以直接访问该组件的父实例或组件,父组件也可以通过this.$children 访问它所有的子组件,而且可以递归向上或向下无线访问, 直到根实例或最内层的组件。

4.1父链

        <div id="app13">
            <p>{{message}}</p>
            <my-component13></my-component13>
        </div>
Vue.component('my-component13',{
    template: '<button @click="updateMessage">通过父链直接修改数据</button>',
    methods: {
        updateMessage: function(){
            this.$parent.message = '来自组件my-component13的内容'  //通过this.$parent直接修改父组件的内容
        }
    }
});

var app13 = new Vue({
    el: '#app13',
    data:{
        message: ''
    }
});

尽管V ue 允许这样操作,但在业务中, 子组件应该尽可能地避免依赖父组件的数据,更不应该去主动修改它的数据,因为这样使得父子组件紧藕合,理想情况下,只有组件自己能修改它的状态。

4.2 子组件索引

当子组件较多时, 通过this.$children 来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。Vue 提供了子组件索引的方法,用特殊的属性ref来为子组件指定一个索引名称。

        <div id="app14">
            <p>{{message}}</p>
            <my-component14 ref="com14"></my-component14>
            <button @click="handleRef">通过ref获取子组件实例</button>
        </div>
Vue.component('my-component14',{
    template: '<div>子组件</div>',
    data: function(){
        return {
            message: '子组件内容'
        }
    }
});

var app14 = new Vue({
    el: '#app14',
    data:{
        message: ''
    },
    methods: {
        handleRef: function(){
             this.message = this.$refs.com14.message;   //通过$refs获取子组件实例
        }
    }
});

 在父组件模板中,子组件标签上使用ref 指定一个名称,井在父组件内通过this.$refs 来访问指定名称的子组件。

$refs 只在组件渲染完成后才填充,并且它是非响应式的. 它仅仅作为一个直接访问子组件的应急方案,应当尽量避免在模板或计算属性中使用$refs。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vue 组件通信

    该章节的内容到这里就全部结束了,源码我已经发到了 GitHub Vue-Communication 上了,有需要的同学可自行下载

    Nian糕
  • Vue基础:组件--组件及组件通信

    组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML...

    奋飛
  • Vue 组件(二):父子组件通信

    子组件是不能直接访问父组件中的数据的,但有时候父子组件之间需要进行数据交互,这就涉及到了父子组件通信的问题。简单来说,父组件向子组件通信是通过 props 进行...

    Chor
  • Vue 父子组件通信 兄弟组件通信 深层组件通信 方式一览

    this.$parent   获取父组件实例 可以使用父组件实例的属性 this.$children 获取子组件数组 可以利用下标调用子组件实例的属性

    憧憬博客
  • vue 父子组件通信

    本文作者:IMWeb jacksun 原文出处:IMWeb社区 未经同意,禁止转载 一.父组件向子组件发送数据 APP.vue(父组件) ? Hell...

    IMWeb前端团队
  • VUE 组件通信总结

    https://cn.vuejs.org/v2/guide/state-management.html

    菜的黑人牙膏
  • vue 父子组件通信

    [removed] export default { props:["msg"] } [removed]

    IMWeb前端团队
  • Vue父子组件通信

    Vue开发,父子组件之间通信很常用,有传数据的,有调用方法的,有子组件操作父组件,也有父组件操作子组件,今天就简单说一下几个父子组件之间通信的方法。

    wade
  • vue组件详解(一)——组件与复用

    一、什么是组件 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。 二、组件用法 组件需要注册后...

    柴小智
  • day87-Vue基础-组件注册、组件通信、组件混入、组件插槽

    少年包青菜
  • 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组...

    啦啦啦321
  • VUE组件之间的通信

    1.父子组件通信 父传子 (1)通过在父组件v-model绑定数据,在子组件进行用props进行数据的接收 父组件

    ZEHAN
  • Vue组件间通信方式

      当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问。在父组件中使用子组件,本质通过v-bind绑定属性传入子组件,子组件...

    TimothyJia
  • Vue - 组件通信之$attrs、$listeners

    vue通信手段有很多种,props/emit、vuex、event bus、provide/inject 等。还有一种通信方式,那就是 $attrs 和 $li...

    WahFung
  • vue组件详解(五)——组件高级用法

    一、递归组件 组件在它的模板内可以递归地调用自己, 只要给组件设置name 的选项就可以了。 示例如下: <div id="app19"> ...

    柴小智
  • 8种vue组件通信方式详细解析实例

    对于vue来说,组件是非常常见的,有很多平台都封装了了属于自己一套的组件,如element ui、we ui等等。同时组件之间的消息传递也是非常重要的,下面是我...

    Javanx
  • 详解vue组件三大核心概念

    本文主要介绍属性、事件和插槽这三个vue基础概念、使用方法及其容易被忽略的一些重要细节。如果你阅读别人写的组件,可以从这三个部分展开,它们可以帮助你快速了解一个...

    Nealyang
  • 6. vue组件详解(一)

    组件系统是 Vue 的一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。几乎任意类型的应用界面都可以抽象为一个组件树:

    用户7798898
  • vue父子组件通信以及非父子组件通信的方法

    组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系,父子关系、兄弟...

    青年码农

扫码关注云+社区

领取腾讯云代金券