vue.js入门(3)——详解组件通信


Posted in Javascript onDecember 02, 2016

本文介绍vue.js组件,具体如下:

5.2 组件通信

尽管子组件可以用this.$parent访问它的父组件及其父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽量显式地使用 props 传递数据。另外,在子组件中修改父组件的状态是非常糟糕的做法,因为:

1.这让父组件与子组件紧密地耦合;

2.只看父组件,很难理解父组件的状态。因为它可能被任意子组件修改!理想情况下,只有组件自己能修改它的状态。

每个Vue实例都是一个事件触发器:

  • $on()——监听事件。
  • $emit()——把事件沿着作用域链向上派送。(触发事件)
  • $dispatch()——派发事件,事件沿着父链冒泡。
  • $broadcast()——广播事件,事件向下传导给所有的后代。

5.2.1 监听与触发

v-on监听自定义事件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <!--子组件模板-->
    <template id="child-template">
      <input v-model="msg" />
      <button v-on:click="notify">Dispatch Event</button>
    </template>
    <!--父组件模板-->
    <div id="events-example">
      <p>Messages: {{ messages | json }}</p>
      <child v-on:child-msg="handleIt"></child>
    </div>
  </body>
  <script src="js/vue.js"></script>
  <script>
//    注册子组件
//    将当前消息派发出去
    Vue.component('child', {
      template: '#child-template',
      data: function (){
        return { msg: 'hello' }
      },
      methods: {
        notify: function() {
          if(this.msg.trim()){
            this.$dispatch('child-msg',this.msg);
            this.msg = '';
          }
        }
      }
    })
//    初始化父组件
//    在收到消息时将事件推入一个数组中
    var parent = new Vue({
      el: '#events-example',
      data: {
        messages: []
      },
      methods:{
        'handleIt': function(){
          alert("a");
        }
      }
    })
  </script>
</html>

vue.js入门(3)——详解组件通信

父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="counter-event-example">
     <p>{{ total }}</p>
     <button-counter v-on:increment="incrementTotal"></button-counter>
     <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
  </body>
  <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
    Vue.component('button-counter', {
     template: '<button v-on:click="increment">{{ counter }}</button>',
     data: function () {
      return {
       counter: 0
      }
     },
     methods: {
      increment: function () {
       this.counter += 1
       this.$emit('increment')
      }
     },
    })
    new Vue({
     el: '#counter-event-example',
     data: {
      total: 0
     },
     methods: {
      incrementTotal: function () {
       this.total += 1
      }
     }
    })
  </script>
</html>

vue.js入门(3)——详解组件通信vue.js入门(3)——详解组件通信

在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰v-on 。例如:

<my-component v-on:click.native="doTheThing"></my-component>

5.2.2 派发事件——$dispatch()

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <p>Messages: {{ messages | json }}</p>
      <child-component></child-component>
    </div>
    <template id="child-component">
      <input v-model="msg" />
      <button v-on:click="notify">Dispatch Event</button>
    </template>

  <script src="js/vue.js"></script>
  <script>
    // 注册子组件
    Vue.component('child-component', {
      template: '#child-component',
      data: function() {
        return {
          msg: ''
        }
      },
      methods: {
        notify: function() {
          if (this.msg.trim()) {
            this.$dispatch('child-msg', this.msg)
            this.msg = ''
          }
        }
      }
    })
  
    // 初始化父组件
    new Vue({
      el: '#app',
      data: {
        messages: []
      },
      events: {
        'child-msg': function(msg) {
          this.messages.push(msg)
        }
      }
    })
  </script>
  </body>
</html>

vue.js入门(3)——详解组件通信

vue.js入门(3)——详解组件通信

vue.js入门(3)——详解组件通信

  1. 子组件的button元素绑定了click事件,该事件指向notify方法
  2. 子组件的notify方法在处理时,调用了$dispatch,将事件派发到父组件的child-msg事件,并给该该事件提供了一个msg参数
  3. 父组件的events选项中定义了child-msg事件,父组件接收到子组件的派发后,调用child-msg事件。

 5.2.3 广播事件——$broadcast()

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <input v-model="msg" />
      <button v-on:click="notify">Broadcast Event</button>
      <child-component></child-component>
    </div>
    
    <template id="child-component">
      <ul>
        <li v-for="item in messages">
          父组件录入了信息:{{ item }}
        </li>
      </ul>
    </template>

  <script src="js/vue.js"></script>
  <script>
    // 注册子组件
    Vue.component('child-component', {
      template: '#child-component',
      data: function() {
        return {
          messages: []
        }
      },
      events: {
        'parent-msg': function(msg) {
          this.messages.push(msg)
        }
      }
    })
    // 初始化父组件
    new Vue({
      el: '#app',
      data: {
        msg: ''
      },
      methods: {
        notify: function() {
          if (this.msg.trim()) {
            this.$broadcast('parent-msg', this.msg)
          }
        }
      }
    })
  </script>
  </body>
</html>

和派发事件相反。前者在子组件绑定,调用$dispatch派发到父组件;后者在父组件中绑定,调用$broadcast广播到子组件。

 5.2.4 父子组件之间的访问

  • 父组件访问子组件:使用$children或$refs
  • 子组件访问父组件:使用$parent
  • 子组件访问根组件:使用$root

$children:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <parent-component></parent-component>
    </div>
    
    <template id="parent-component">
      <child-component1></child-component1>
      <child-component2></child-component2>
      <button v-on:click="showChildComponentData">显示子组件的数据</button>
    </template>
    
    <template id="child-component1">
      <h2>This is child component 1</h2>
    </template>
    
    <template id="child-component2">
      <h2>This is child component 2</h2>
    </template>
    <script src="js/vue.js"></script>
    <script>
      Vue.component('parent-component', {
        template: '#parent-component',
        components: {
          'child-component1': {
            template: '#child-component1',
            data: function() {
              return {
                msg: 'child component 111111'
              }
            }
          },
          'child-component2': {
            template: '#child-component2',
            data: function() {
              return {
                msg: 'child component 222222'
              }
            }
          }
        },
        methods: {
          showChildComponentData: function() {
            for (var i = 0; i < this.$children.length; i++) {
              alert(this.$children[i].msg)
            }
          }
        }
      })
    
      new Vue({
        el: '#app'
      })
    </script>
  </body>
</html>

vue.js入门(3)——详解组件通信

vue.js入门(3)——详解组件通信

vue.js入门(3)——详解组件通信

$ref可以给子组件指定索引ID:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <parent-component></parent-component>
    </div>
    
    <template id="parent-component">
      <!--<child-component1></child-component1>
      <child-component2></child-component2>-->
      <child-component1 v-ref:cc1></child-component1>
      <child-component2 v-ref:cc2></child-component2>
      <button v-on:click="showChildComponentData">显示子组件的数据</button>
    </template>
    
    <template id="child-component1">
      <h2>This is child component 1</h2>
    </template>
    
    <template id="child-component2">
      <h2>This is child component 2</h2>
    </template>
    <script src="js/vue.js"></script>
    <script>
      Vue.component('parent-component', {
        template: '#parent-component',
        components: {
          'child-component1': {
            template: '#child-component1',
            data: function() {
              return {
                msg: 'child component 111111'
              }
            }
          },
          'child-component2': {
            template: '#child-component2',
            data: function() {
              return {
                msg: 'child component 222222'
              }
            }
          }
        },
        methods: {
          showChildComponentData: function() {
//            for (var i = 0; i < this.$children.length; i++) {
//              alert(this.$children[i].msg)
//            }
            alert(this.$refs.cc1.msg);
            alert(this.$refs.cc2.msg);
          }
        }
      })
      new Vue({
        el: '#app'
      })
    </script>
  </body>
</html>

 

效果与$children相同。

$parent:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <parent-component></parent-component>
    </div>
    
    <template id="parent-component">
      <child-component></child-component>
    </template>
    
    <template id="child-component">
      <h2>This is a child component</h2>
      <button v-on:click="showParentComponentData">显示父组件的数据</button>
    </template>
    
    <script src="js/vue.js"></script>
    <script>
      Vue.component('parent-component', {
        template: '#parent-component',
        components: {
          'child-component': {
            template: '#child-component',
            methods: {
              showParentComponentData: function() {
                alert(this.$parent.msg)
              }
            }
          }
        },
        data: function() {
          return {
            msg: 'parent component message'
          }
        }
      })
      new Vue({
        el: '#app'
      })
    </script>
  </body>
</html>

vue.js入门(3)——详解组件通信

如开篇所提,不建议在子组件中修改父组件的状态。

 5.2.5 非父子组件通信

有时候非父子关系的组件也需要通信。在简单的场景下,使用一个空的 Vue 实例作为中央事件总线:

var bus = new Vue()

// 触发组件 A 中的事件
bus.$emit('id-selected', 1)

// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
  // ...
})

在更多复杂的情况下,可以考虑使用专门的 状态管理模式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ExtJs grid行 右键菜单的两种方法
Jun 19 Javascript
JS操作Cookies的小例子
Oct 15 Javascript
js格式化时间小结
Nov 03 Javascript
Jquery实现瀑布流布局(备有详细注释)
Jul 31 Javascript
数据结构中的各种排序方法小结(JS实现)
Jul 23 Javascript
JavaScript实现向select下拉框中添加和删除元素的方法
Mar 07 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
Aug 29 jQuery
vue使用keep-alive实现数据缓存不刷新
Oct 21 Javascript
jQuery实现的上传图片本地预览效果简单示例
Mar 29 jQuery
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
May 07 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
Sep 01 Javascript
Javascript中Math.max和Math.max.apply的区别和用法详解
Aug 24 Javascript
javascript实现鼠标点击页面 移动DIV
Dec 02 #Javascript
jquery对所有input type=text的控件赋值实现方法
Dec 02 #Javascript
bootstrap使用validate实现简单校验功能
Dec 02 #Javascript
在网页中插入百度地图的步骤详解
Dec 02 #Javascript
PHP获取当前页面完整URL的方法
Dec 02 #Javascript
jQuery插件fullPage.js实现全屏滚动效果
Dec 02 #Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
Dec 02 #Javascript
You might like
PHP设计模式之调解者模式的深入解析
2013/06/13 PHP
php 获取SWF动画截图示例代码
2014/02/10 PHP
php数组指针操作详解
2017/02/14 PHP
利用PHP判断是否是连乘数字串的方法示例
2017/07/03 PHP
符合标准的js表单提交的代码
2007/09/13 Javascript
javascript笔记 String类replace函数的一些事
2011/09/22 Javascript
js onmousewheel事件多次触发问题解决方法
2014/10/17 Javascript
node.js中的fs.linkSync方法使用说明
2014/12/15 Javascript
JavaScript获得指定对象大小的方法
2015/07/01 Javascript
jQuery中prepend()方法使用详解
2015/08/11 Javascript
详解Angular的内置过滤器和自定义过滤器【推荐】
2016/12/26 Javascript
js实现适合新闻类图片的轮播效果
2017/02/05 Javascript
jQuery实现多张图片上传预览(不经过后端处理)
2017/04/29 jQuery
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
2019/01/20 Javascript
koa-router路由参数和前端路由的结合详解
2019/05/19 Javascript
js实现简单的随机点名器
2020/09/17 Javascript
JavaScript实现网页下拉菜单效果
2020/11/20 Javascript
详解JavaScript中分解数字的三种方法
2021/01/05 Javascript
python用于url解码和中文解析的小脚本(python url decoder)
2013/08/11 Python
python实现图片批量剪切示例
2014/03/25 Python
Python基于Socket实现的简单聊天程序示例
2017/08/05 Python
Tensorflow实现卷积神经网络用于人脸关键点识别
2018/03/05 Python
Python3.6使用tesseract-ocr的正确方法
2018/10/17 Python
python3利用ctypes传入一个字符串类型的列表方法
2019/02/12 Python
pandas使用函数批量处理数据(map、apply、applymap)
2020/11/27 Python
Python logging自定义字段输出及打印颜色
2020/11/30 Python
python和opencv构建运动检测器的实现
2021/03/03 Python
C#如何判断当前用户是否输入某个域
2015/12/07 面试题
为什么说Ruby是一种真正的面向对象程序设计语言
2012/10/30 面试题
爱心捐款感谢信
2015/01/20 职场文书
幼儿园个人总结
2015/02/28 职场文书
中秋节英文祝福语句(14句)
2019/09/11 职场文书
html+css实现赛博朋克风格按钮
2021/05/26 HTML / CSS
Java基于字符界面的简易收银台
2021/06/26 Java/Android
GoFrame框架数据校验之校验结果Error接口对象
2022/06/21 Golang
Android实现获取短信验证码并自动填充
2023/05/21 Java/Android