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 相关文章推荐
jQuery Deferred和Promise创建响应式应用程序详细介绍
Mar 05 Javascript
捕获浏览器关闭、刷新事件不同情况下的处理方法
Jun 02 Javascript
给js文件传参数(详解)
Jul 13 Javascript
javascript 面向对象封装与继承
Nov 27 Javascript
jQuery Easyui实现左右布局
Jan 26 Javascript
jQuery 生成svg矢量二维码
Aug 09 Javascript
Jquery表单验证失败后不提交的解决方法
Oct 18 Javascript
Bootstrap 实现查询的完美方法
Oct 26 Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
Mar 05 Javascript
微信小程序中添加客服按钮contact-button功能
Apr 27 Javascript
Vue中keep-alive 实现后退不刷新并保持滚动位置
Mar 17 Javascript
Jquery Fade用法详解
Nov 06 jQuery
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模板技术原理【一】
2008/01/10 PHP
PHPThumb图片处理实例
2014/05/03 PHP
php出现web系统多域名登录失败的解决方法
2014/09/30 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
2014/11/19 PHP
Linux下编译redis和phpredis的方法
2016/04/07 PHP
javascript之锁定表格栏位
2007/06/29 Javascript
javascript中的array数组使用技巧
2010/01/31 Javascript
读jQuery之一(对象的组成)
2011/06/11 Javascript
js弹出窗口之弹出层的小例子
2013/06/17 Javascript
Js判断CSS文件加载完毕的具体实现
2014/01/17 Javascript
JavaScript开发人员的10个关键习惯小结
2014/12/05 Javascript
jquery禁止回车触发表单提交
2014/12/12 Javascript
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
2015/01/01 NodeJs
javascript与Python快速排序实例对比
2015/08/10 Javascript
Jquery操作Ajax方法小结
2015/11/29 Javascript
KnockoutJs快速入门教程
2016/05/16 Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
2016/05/21 Javascript
jQuery遍历DOM的父级元素、子级元素和同级元素的方法总结
2016/07/07 Javascript
JQuery中Ajax的操作完整例子
2017/03/07 Javascript
node.js实现微信JS-API封装接口的示例代码
2017/09/06 Javascript
vue中keep-alive的用法及问题描述
2018/05/15 Javascript
js canvas实现5张图片合成一张图片
2019/07/15 Javascript
Vue3.0中的monorepo管理模式的实现
2019/10/14 Javascript
vue+iview实现文件上传
2020/11/17 Vue.js
Python导入txt数据到mysql的方法
2015/04/08 Python
Python入门_浅谈数据结构的4种基本类型
2017/05/16 Python
使用python实现简单五子棋游戏
2019/06/18 Python
用pyqt5 给按钮设置图标和css样式的方法
2019/06/24 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
使用PYTHON解析Wireshark的PCAP文件方法
2019/07/23 Python
基于python的列表list和集合set操作
2019/11/24 Python
Habitat家居英国官方网站:沙发、家具、照明、厨房和户外
2019/12/12 全球购物
初中班主任寄语
2014/04/04 职场文书
详解Python小数据池和代码块缓存机制
2021/04/07 Python
Python 数据可视化工具 Pyecharts 安装及应用
2022/04/20 Python
Ubuntu Server 安装Tomcat并配置systemctl
2022/04/28 Servers