vue组件传值是项目开发中必备的功能点,本文将介绍一些常用的组件传值方法,并给出相应的示例。
前提
搭建项目,本文示例是在vue脚手架中完成的,具体如下:
1. 安装node
2. 全局安装vue脚手架,npm install --global vue-cli
3. 新建项目,vue init webpack 项目名
4. 完成之后进入对应目录,启动项目即可
- 父传子之props
// father.vue
<template>
<div>
<h1>我是父亲辈</h1>
<Child :msg = "msg"/>
</div>
</template>
<script>
import Child from './child'
export default {
components: { Child },
data () {
return {
msg: 'Welcome child',
}
}
}
</script>
// child.vue
<template>
<div>
我是孩子辈,父亲传给我的话是: {{ msg }}
</div>
</template>
<script>
export default {
props: ['msg']
}
</script>
结果展示如下:- 子传父之$emit
// father.vue
<template>
<div>
<h1>我是父亲辈,孩子给我传的话是:{{ msg }}</h1>
<Child @sendFromChild="sendFromChild"/>
</div>
</template>
<script>
import Child from './child'
export default {
components: { Child },
data () {
return {
msg: ''
}
},
methods: {
sendFromChild (msg) {
this.msg = msg
}
}
}
</script>
// child.vue
<template>
<div>
我是孩子辈 <button @click="sendMsg">点击我向父亲传话</button>
</div>
</template>
<script>
export default {
methods: {
sendMsg () {
this.$emit('sendFromChild', 'I am child')
}
}
}
</script>
- 兄弟之间通信parent/root
兄弟之间通信,可以通过共同的父辈或祖先搭桥。并结合emit,on。已parent为例:
// father.vue
<template>
<div>
<h1>我是父亲辈</h1>
<Child1 />
<Child2 />
</div>
</template>
<script>
import Child1 from './child1'
import Child2 from './child2'
export default {
components: { Child1, Child2 }
}
</script>
// child1.vue
<template>
<div>
我是孩子1 <button @click="sendMsg">点击我向孩子2传话</button>
</div>
</template>
<script>
export default {
methods: {
sendMsg () {
this.$parent.$emit('sendFromBrother', 'Hello, i am child1')
}
}
}
</script>
// child2.vue
<template>
<div>
我是孩子2, 我的兄弟给我传话了:{{ msg }}
</div>
</template>
<script>
export default {
data () {
return {
msg: ''
}
},
mounted () {
this.$parent.$on('sendFromBrother', (value) => {
this.msg = value
})
}
}
</script>
- 父组件通过$children访问子组件实现父子通信。
// father.vue
<template>
<div>
<h1>我是父亲辈, 我可以拿到孩子的msg属性: {{ msg }}</h1>
<Child1 />
</div>
</template>
<script>
import Child1 from './child1'
export default {
components: { Child1 },
data () {
return {
msg: ''
}
},
mounted () {
this.msg = this.$children[0].msg
}
}
</script>
// child.vue
<template>
<div>
我是孩子,我有个属性msg为: {{ msg }}
</div>
</template>
<script>
export default {
data () {
return {
msg: 'This is a message'
}
}
}
</script>
- 获取子节点引用refs
// father.vye
<template>
<div>
<h1>我是父亲辈, 我可以拿到孩子的msg属性:{{ msg }}</h1>
<Child1 ref="child" />
</div>
</template>
<script>
import Child1 from './child1'
export default {
components: { Child1 },
data () {
return {
msg: ''
}
},
mounted () {
this.msg = this.$refs.child.msg
}
}
</script>
// child.vue
<template>
<div>
我是孩子, 我有个msg属性,值为:{{ msg }}
</div>
</template>
<script>
export default {
data () {
return {
msg: 'This is a message'
}
}
}
</script>
- 任意两个组件传值之事件总线
// bus.js
// Bus:事件派发、监听和回调管理
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))
}
}
}
export default Bus
// main.js 中引入bus,并注入到vue中
import Vue from 'vue'
import App from './App'
import router from './router'
import Bus from './bus' // 引入
Vue.config.productionTip = false
Vue.prototype.$bus = new Bus() // 注入
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
// father.vue
<template>
<div>
<h1>我是父亲辈</h1>
<Child1 />
<Child2 />
</div>
</template>
<script>
import Child1 from './child1'
import Child2 from './child2'
export default {
components: { Child1, Child2 }
}
</script>
// child1.vue
<template>
<div>
我是孩子1 <button @click="sendMsg">点击我向孩子2传话</button>
</div>
</template>
<script>
export default {
methods: {
sendMsg () {
this.$bus.$emit('sendFromBrother', 'Hello, i am child1')
}
}
}
</script>
// child2.vue
<template>
<div>
我是孩子2, 我的兄弟给我传话了:{{ msg }}
</div>
</template>
<script>
export default {
data () {
return {
msg: ''
}
},
mounted () {
this.$bus.$on('sendFromBrother', (value) => {
this.msg = value
})
}
}
</script>
- 任意两个组件传值之vuex
vuex主要创建唯一的全局数据管理者store,通过它管理数据并通知组件状态变更,后面文章会详细讲述,此处不赘述 - attrs/listeners
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外
// father.vue
<template>
<div>
<h1>我是父亲辈, {{msg}}</h1>
<Child :msg="msg" foo="foo" @updateMsg="updateMsg" />
</div>
</template>
<script>
import Child from './child'
export default {
components: { Child },
data () {
return {
msg: 'this is a meaasge'
}
},
methods: {
updateMsg () {
this.msg = 'updated message'
}
}
}
</script>
// child.vue
<template>
<div>
<h3>我是孩子辈</h3>
<div>我从父亲拿到的数据{{foo}}</div>
<GrandSon bar="bar" v-bind="$attrs" v-on="$listeners" />
</div>
</template>
<script>
import GrandSon from './grandSon'
export default {
components: { GrandSon },
props: ['foo']
}
</script>
// grandSon.vue
<template>
<div>
<h5>我是孙子辈</h5>
<div>我拿到的$attrs数据有:{{$attrs}}</div>
<button @click="changeMsg">点击改变msg</button>
</div>
</template>
<script>
export default {
methods: {
changeMsg () {
console.log(this.$listeners, '$listeners')
this.$emit('updateMsg')
}
}
}
</script>
- 祖先和后代传值provide/inject
// father.vue
<template>
<div>
<h1>我是父亲辈</h1>
<Child />
</div>
</template>
<script>
import Child from './child.vue'
export default {
components: { Child },
provide () {
return {msg: 'msg from father'}
}
}
</script>
// child.vue
<template>
<div>
<h3>我是孩子辈</h3>
<GrandSon />
</div>
</template>
<script>
import GrandSon from './grandSon'
export default {
components: { GrandSon }
}
</script>
//grandSon.vue
<template>
<div>
<h5>我是孙子辈</h5>
<div>我拿到祖先的值: {{msg}}</div>
</div>
</template>
<script>
export default {
inject: ['msg']
}
</script>
总结
上面介绍了9种组件之间传值的方法,下面简单的总结一下。
1.父向子传值
- props
- 子向父传值
- $emit
- ref
- children
- 兄弟之间传值
- $parent
- $root
- $bus
- 祖孙之间传值
- attrs/listeners
- provide/inject
- 任意组件传值
- vuex