Vue 组件通信

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

自定义事件–子组件给父组件传递数据

使用 v-on 除了监听 DOM 事件外,还可以用于组件之间的自定义事件

JS 的设计模式–观察者模式,有dispatchEvent 和 addEventListener 两个方法,Vue 组件也有与之类似的一套模式,子组件用 $emit 来触发事件,父组件用 $on() 来监听子组件事件。

步骤:

  1. 自定义事件;
  2. 在子组件用 $emit 触发事件,第一个参数是事件名,后面的参数是要传递的数据;
  3. 在自定义事件中用一个参数来接收
<div id="app">
  count 的值为{{count}}
  <hr>
  <my-component @change="handle"></my-component>  // 自定义 change 事件
</div>

<script>
  var app = new Vue({
    el: '#app',
    data: { count: 1000 },
    methods: {
      handle: function(value) {
        this.count = value      // 接收
      }
    },
	components: {
	  'my-component': {
		  template: `<div><button @click="plus">+1000</button><button @click="cut">-1000</button></div>`,
      data: function() {
      	return {
          count: 1000
        }
      },
      methods: {
        plus: function() {
          this.count += 1000
          this.$emit('change', this.count)   // 触发事件并传递数据
        },
        cut: function() {
          this.count -= 1000
          this.$emit('change', this.count)
        }
      }
	}
})
</script>

组件使用 v-model

v-model 其实是一个语法糖,其在背后做了两件事:

  1. 用 v-bind 绑定一个 value 属性
  2. 用 v-on 指令给当前元素绑定一个 input 事件

使用 v-model 时,v-model 做的是

  1. 接收一个 value 属性
  2. 当有新的 value 时触发 input 事件
<div id="app">
  count:{{count}}
  <hr/>
  <child-component v-model="count"></child-component>
</div>

<script>
  var app = new Vue({
    el: '#app',
    data: { count: 0 },
    components: {
	  'child-component': {
		data: function() {
		  return { count: 0 }
		},
		template: '<button @click="plus">+1</button>',
		methods: {
		  plus: function() {
			this.count++
			this.$emit('input', this.count)   // 触发 input 事件
		  }
		}
	  }
	}
  })
</script>

this.$emit 这行代码其实就是触发了 input 事件,而 input 事件后面的参数就是传递给 v-model 绑定的 value 属性的值。

v-model 其实就做到了绑定事件加上接收事件触发传递过来的参数数据。

非父子组件之间的通信

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

var bus = new Vue()

接收消息数据的组件

bus.$on('msg', function(msg) {
  // 监听事件并接收传递过来的参数,参数可以是多个
  console.log(msg)
  ...
})

发送消息数据的组件

bus.$emit('msg', "这是来自发送组件的消息")

具体示例:

<div id="app">
  <a-component></a-component>
  <b-component></b-component>
</div>

---------------------------
|          根组件          |
|       -----------       |
|      |  子组件 a  |      |
|       -----------       |
|                         |
|       -----------       |
|      |  子组件 b  |      |
|       -----------       |
|                         |
---------------------------

Vue.component('a-component', {
  template: '<button @click="setmsg">组件a</button>',
  methods: {
	setmsg: function() {
	  this.$root.bus.$emit('msg', "这是来自a组件的消息")
	}
  }
})

Vue.component('b-component', {
  template: '<div></div>',
  created: function() {
	this.$root.bus.$on('msg', function(msg) {
    console.log(msg)
	})
  }
})

var app = new Vue({
  el: '#app',
  data: {
	  bus: new Vue()
  }
})

父链:this.$parent

可以通过 this.$parent.xxx 来修改父组件的指定内容

<div id="app">
  <child-component></child-component>
  <br/>
  这是父组件的 msg:{{msg}}
</div>

Vue.component('child-component', {
  template: '<button @click="setFatherData">改变父组件数据</button>',
  methods: {
    setFatherData: function() {
	  this.$parent.msg = "通过子组件修改的数据"
    }
  }
})

var app = new Vue({
  el: '#app',
  data: {
	msg: '父组件的初始数据'
  }
})

子链:this.$refs

为子组件添加特殊属性 ref 作为索引

通过 this.$refs.索引.xxx 来获取指定子组件的内容

<div id="app">
  <a-component ref="a"></a-component>
  <b-component ref="b"></b-component>   // 添加索引
  <br/>
  <button @click="getmsg">获取子组件 a 的 msg </button>
  <br/>
  父组件当前的 msg:{{msg}}
</div>

Vue.component('a-component', {
  template: '<div></div>',
  data: function() {
	return {
	  msg: '组件 a msg'
  	}
  }
})

Vue.component('b-component', {
  template: '<div></div>',
  data: function() {
	return {
	  msg: '组件 b msg'
  	}
  }
})

var app = new Vue({
  el: '#app',
  data: {
	msg: '父组件初始 msg'
  },
  methods: {
	getmsg: function() {
	  this.msg = this.$refs.a.msg   // 获取指定子组件内容
	}
  }
})
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值