根据组件关系划分
父子
- props/$emit,$on
- $parent/$children
- $refs
兄弟
- Bus
- Vuex
跨级
- Bus
- Vuex
- provide / inject
- $attrs/$listeners
父子
props/$emit,$on
父
<template>
<div>
<test3-a :value="value"
@input="handleChange"></test3-a>
</div>
</template>
<script>
import test3A from '../components/test3-a.vue'
export default {
components: { test3A },
data () {
return {
value: 1
}
},
methods: {
handleChange (val) {
this.value = parseInt(val)
}
}
}
</script>
子
<template>
<div>
<button @click="increase(-1)">减1</button>
<span> {{currentValue}} </span>
<button @click="increase(1)">加1</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number
}
},
data () {
return {
currentValue: this.value
}
},
methods: {
increase (val) {
this.currentValue = this.value + val
this.$emit('input', this.currentValue)
}
}
}
</script>
props/$emit,$on(v-model写法)
v-model 是一个语法糖,可以拆解为 props: value 和 events: input。就是说组件必须提供一个名为 value 的 prop,以及名为 input 的自定义事件
父
<template>
<div>
<test3-a v-model="value"></test3-a>
</div>
</template>
<script>
import test3A from '../components/test3-a.vue'
export default {
components: { test3A },
data () {
return {
value: 1
}
}
}
</script>
子(不用修改)
<template>
<div>
<button @click="increase(-1)">减1</button>
<span> {{currentValue}} </span>
<button @click="increase(1)">加1</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number
}
},
data () {
return {
currentValue: this.value
}
},
methods: {
increase (val) {
this.currentValue = this.value + val
this.$emit('input', this.currentValue)
}
}
}
</script>
props/$emit,$on(.sync写法)
.sync 不是真正的双向绑定,而是一个语法糖,修改数据还是在父组件完成的,并非在子组件
父
<template>
<div>
<test3-a :value.sync="value"></test3-a>
</div>
</template>
<script>
import test3A from '../components/test3-a.vue'
export default {
components: { test3A },
data () {
return {
value: 1
}
}
}
</script>
子
<template>
<div>
<button @click="increase(-1)">减1</button>
<span> {{value}} </span>
<button @click="increase(1)">加1</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number
}
},
methods: {
increase (val) {
this.$emit('update:value', this.value + val)
}
}
}
</script>
$refs/$parent,$children
父
<template>
<div>
<button @click="handleRef">handleRef</button>
<test2-a ref="test2a"
:value="value"></test2-a>
</div>
</template>
<script>
import test2A from '../components/test2-a.vue'
export default {
components: { test2A },
data () {
return {
value: 1
}
},
methods: {
handleRef () {
this.$children[0].currentValue = 2
// this.$refs.test2a.currentValue = 2
}
}
}
</script>
子
<template>
<div>
<p>{{currentValue}}</p>
<button @click="handleChange">handleChange</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number
}
},
data () {
return {
currentValue: this.value
}
},
methods: {
handleChange () {
this.$parent.value = 2
this.currentValue = this.$parent.value
}
}
}
</script>
兄弟
bus
/tools/bus.js
import Vue from 'vue'
export default new Vue()
父
<template>
<div>
<p>bus通信</p>
<test4-a></test4-a>
<test4-b></test4-b>
</div>
</template>
<script>
import test4A from '../components/test4-a.vue'
import test4B from '../components/test4-b.vue'
export default {
components: {
test4A,
test4B
}
}
</script>
子 test4-a
<template>
<div>
组件test4-a
<button @click="sendMsg">发个消息级兄弟组件b</button>
</div>
</template>
<script>
import bus from '../tools/bus'
export default {
methods: {
sendMsg () {
bus.$emit('send', 'hello b')
}
}
}
</script>
子 test4-b
<template>
<div>
<p>组件tes4-b:{{ msg }}</p>
</div>
</template>
<script>
import bus from '../tools/bus'
export default {
data () {
return {
msg: 'i am message'
}
},
created () {
bus.$on('send', data => {
this.msg = data
})
}
}
</script>
跨级
provide / inject(父级与后代)
//app.vue
<script>
export default {
provide () {
return {
app: this
}
},
data () {
return {
adminUser : null
}
},
methods: {
setAdminUser () {
this.adminUser = 'admin'
},
},
mounted () {
this.setAdminUser ();
}
}
</script>
任何页面组件
<template>
<div>
{{ app.adminUser }}
</div>
</template>
<script>
export default {
inject: ['app']
}
</script>
$attrs/$listeners
爷
<template>
<div>
<test1-a :value="value"
@sendToUp="handleOn">
</test1-a>
</div>
</template>
<script>
import test1A from '@/components/test1-a.vue'
export default {
data () {
return {
value: 'Hello, world'
}
},
components: { test1A },
methods: {
handleOn (val) {
this.value = val
}
}
}
</script>
父
<template>
<div>
<p>attrs:{{$attrs}}</p>
<test1-a-children v-bind="$attrs"
v-on="$listeners"></test1-a-children>
</div>
</template>
<script>
import test1AChildren from './test1-a-children'
export default {
components: {
test1AChildren
}
}
</script>
孙
<template>
<div>
<p>value:{{value}}</p>
<button @click="handleSend">我要发射火箭</button>
</div>
</template>
<script>
export default {
props: ['value'],
methods: {
handleSend () {
this.$emit('sendToUp', 'test1-a-children')
}
}
}
</script>