vue组件间通信的多种方式

一般情况下我们把vue中的组件关系分为父子组件通信, 和非父子组件之间通信

一: 父子传值props / $emit

  1. 父向子传值:在子组件的标签上通过自定义属性传递父组件的数据,子组件的内部通过 props 接收父向子传递的数据
<!-- 父组件 -->
<template>
  <div class="section">
    <child :msg="articleList"></child>
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'HelloWorld',
  components: { comArticle },
  data() {
    return {
      msg: '启动'
    }
  }
}
</script>

 

<!-- 子组件 child.vue -->
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  props: {
      msg: String
  }
}
</script>
2.子向父通信: 在子组件的标签上自定义事件,自定义事件的值是父组件的方法,在子组件内部通过 this.$emit()方法触发事件,第一个参数为自定义事件,第二个参数可以传递子组件的内部数据,此时父组件中的方法就可以执行了
<!-- 父组件 -->
<template>
  <div class="section">
    <child :msg="articleList" @changMsg="changMsg"></child>
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'HelloWorld',
  components: { comArticle },
  data() {
    return {
      msg: 'kokokokoko'
    }
  },
  methods:{
      changMsg(msg) {
          this.msg = msg
      }
  }
}
</script>
<!-- 子组件 child.vue -->
<template>
  <div>
    {{ msg }}
    <button @click="change">改变字符串</button>
  </div>
</template>

<script>
export default {
  props: {
      msg: String
  },
  methods: {
      change(){
          this.$emit('changMsg', 'okokokkok')
      }
  }
}
</script>

二..sync 修饰符(语法糖)

当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。 通俗的说:.sync修饰符可以实现子组件与父组件的双向绑定,并且可以实现子组件同步修改父组件的值。

<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" />

使用.sync

<text-document v-bind:title.sync="doc.title" />

这样,在子组件中,就可以通过下面代码来实现对这个 prop 重新赋值了

this.$emit('update:title', newTitle)

v-model(语法糖)

 我们知道v-model 是用来在表单控件或者组件上创建双向绑定的,他的本质是 v-bind 和 v-on 的语法糖,在一个组件上使用 v-model,默认会为组件绑定名为 value 的 prop 和名为 input 的事件。

//在父组件中
<template>
	<div>
		<myinput v-model="msg"></myinput>
	</div>
</template>
 
<script>
    import myinput from '../components/myinput.vue'
	export default {
		components:{myinput},
        data:function(){
			return {
				msg: 'hello'
			}
		},
	}
</script>
 
 
 
//在子组件中
<template>
	<div>
		<input type="text" :value="value" @input="input">
	</div>
</template>
 
<script>
	export default {
		props:['value'],
		methods:{
			input(e){
				console.log(e.target.value)
				this.$emit('input',e.target.value)
			}
		}
	}
</script>

    有时,在某些特定的控件中名为 value 的属性会有特殊的含义,这时可以通过 v-model 选项来回避这种冲突。

四 :ref / $refs 

ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据

// 子组件 A.vue

export default {
  data () {
    return {
      name: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      console.log('hello')
    }
  }
}

// 父组件 app.vue

<template>
  <component-a ref="comA"></component-a>
</template>
<script>
  export default {
    mounted () {
      const comA = this.$refs.comA;
      console.log(comA.name);  // Vue.js
      comA.sayHello();  // hello
    }
  }
</script>

ref 这种方式,就是获取子组件的实例,然后可以直接子组件的方法和访问操作data的数据,就是父组件控制子组件的一种方式,子组件想向父组件传参或操作,只能通过其他的方式了

五: eventBus(兄弟组件通信)

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

// 创建一个中央时间总线类
class Bus {
  constructor() {
    this.callbacks = {} // 存放事件的名字
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }
  $emit(name, args) {
    if (this.callbacks[name]) {
      this.callbacks[name].forEach((cb) => cb(args))
    }
  }
}

// main.js
Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上
// 另一种方式
Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能
this.$bus.$emit('foo')
this.$bus.$on('foo', this.handle)

六:provide 与 inject

  • 在祖先组件定义provide属性,返回传递的值
  • 在后代组件通过inject接收组件传递过来的值

祖先组件

provide(){
    return {
        foo:'foo'
    }
}

后代组件

inject: ['foo'] // 获取到祖先组件传递过来的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值