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 相关文章推荐
让广告代码不再影响你的网页加载速度
Jul 07 Javascript
jquery 实现的全选和反选
Apr 15 Javascript
js中判断控件是否存在
Aug 25 Javascript
SeaJS入门教程系列之SeaJS介绍(一)
Mar 03 Javascript
Javascript writable特性介绍
Feb 27 Javascript
JavaScript数据类型详解
Apr 01 Javascript
基于百度地图实现产品销售的单位位置查看功能设计与实现
Oct 21 Javascript
JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
Jan 05 Javascript
nuxt.js 缓存实践
Jun 25 Javascript
vue中axios的二次封装实例讲解
Oct 14 Javascript
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
Aug 25 Javascript
vue3引入highlight.js进行代码高亮的方法实例
Apr 08 Vue.js
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中的实现trim函数代码
2007/03/19 PHP
PHP stream_context_create()作用和用法分析
2011/03/29 PHP
CentOS下PHP安装Oracle扩展
2015/02/15 PHP
curl 出现错误的调试方法(必看)
2017/02/13 PHP
javascript[js]获取url参数的代码
2007/10/17 Javascript
Ajax,UTF-8还是GB2312 eval 还是execScript
2008/11/13 Javascript
兼容多浏览器的iframe自适应高度(ie8 、谷歌浏览器4.0和 firefox3.5.3)
2009/11/04 Javascript
jQuery插件的写法分享
2013/06/12 Javascript
JavaScript获取当前网页标题(title)的方法
2015/04/03 Javascript
WEB前端开发都应知道的jquery小技巧及jquery三个简写
2015/11/15 Javascript
基于jQuery实现网页打印功能
2015/12/01 Javascript
jquery做个日期选择适用于手机端示例
2017/01/10 Javascript
在js中做数字字符串补0(js补零)
2017/03/25 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
Vue插件之滑动验证码
2019/09/21 Javascript
Node.js开发之套接字(socket)编程入门示例
2019/11/05 Javascript
JS 数组和对象的深拷贝操作示例
2020/06/06 Javascript
Vue左滑组件slider使用详解
2020/08/21 Javascript
python根据日期返回星期几的方法
2015/07/06 Python
python如何生成各种随机分布图
2018/08/27 Python
对python pandas读取剪贴板内容的方法详解
2019/01/24 Python
python写入文件自动换行问题的方法
2019/07/05 Python
Python greenlet和gevent使用代码示例解析
2020/04/01 Python
Django获取model中的字段名和字段的verbose_name方式
2020/05/19 Python
python中的测试框架
2020/11/13 Python
Python实现石头剪刀布游戏
2021/01/20 Python
jupyter notebook指定启动目录的方法
2021/03/02 Python
工作失职检讨书范文
2014/01/16 职场文书
教师党的群众路线教育实践活动个人整改措施
2014/11/04 职场文书
运动会通讯稿100字
2015/07/20 职场文书
公安干警正风肃纪心得体会
2016/01/15 职场文书
JVM上高性能数据格式库包Apache Arrow入门和架构详解(Gkatziouras)
2021/05/26 Servers
mysql中between的边界,范围说明
2021/06/08 MySQL
解析Java异步之call future
2021/06/14 Java/Android
nginx作grpc的反向代理踩坑总结
2021/07/07 Servers
oracle重置序列从0开始递增1
2022/02/28 Oracle