文章目录
组件通信
一、父向子传值用props
props:[‘传入的值名称’] ----props:[‘w’]
props:{传入值名称: 类型判断,}----props:[ w: Number]
完整写法
props: {
w: {
type: Number, //类型
required: true, //是否必须
default: 0, //默认值
validator(val) { //自定义校验
if (val) { return false }
},
},
父
<template>
<div class="app">
<BaseProgress :w="width"></BaseProgress>
</div>
</template>
<script>
//子组件
import BaseProgress from './components/BaseProgress.vue'
export default {
data() {
return {
width: 30,
}
},
components: {
BaseProgress,
},
}
</script>
子组件
<template>
<div class="base-progress">
<div class="inner" :style="{ width: w + '%' }">
<span>{{ w }}%</span>
</div>
</div>
</template>
<script>
export default {
// 1.基础写法(类型校验)
// props: {
// w: Number,
// },
// 2.完整写法(类型、默认值、非空、自定义校验)
props: {
w: {
type: Number,
required: true,
default: 0,
validator(val) {
// console.log(val)
if (val >= 100 || val <= 0) {
console.error('传入的范围必须是0-100之间')
return false
} else {
return true
}
},
},
},
}
</script>
<style scoped>
.base-progress {
height: 26px;
width: 400px;
border-radius: 15px;
background-color: #272425;
border: 3px solid #272425;
box-sizing: border-box;
margin-bottom: 30px;
}
.inner {
position: relative;
background: #379bff;
border-radius: 15px;
height: 25px;
box-sizing: border-box;
left: -3px;
top: -2px;
}
.inner span {
position: absolute;
right: 0;
top: 26px;
}
</style>
data与props都可以给组件提供数据
props与data区别
1)data数据是自己内部数据,可以随便修改
2)props数是外部传入的,不能直接修改,要遵循单向数据流
父组件的props更新,会单向向下流动,影响到子组件
如果需要修改,需要使用$emit()通知父级修改
二、子向父传值用$emit()
子组件发送事件 this.$emit(‘父组件自定义事件名’,携带的参数)
父组件通过绑定自定义事件接收参数 <子组件名 @自定义事件=‘methods中处理方法’>
父组件通过在methods中的处理方法形参中接收传递过来的数据
父
<template id="cala">
<div>
<BaseCount :count="count" @changeCount="handleChange"></BaseCount>
</div>
</template>
<script>
import BaseCount from './components/BaseCount.vue'
export default {
data() {
return {
count: 100
}
},
components: {
BaseCount
},
methods: {
handleChange(newVal) {
// console.log(newVal);
this.count = newVal
}
}
}
</script>
子组件
<template>
<div class="base-count">
<button @click="handleSub">-</button>
<span>{{ count }}</span>
<button @click="handleAdd">+</button>
</div>
</template>
<script>
export default {
props: {
count: {
type: Number,
},
},
methods: {
handleSub() {
this.$emit('changeCount', this.count - 1)
},
handleAdd() {
this.$emit('changeCount', this.count + 1)
},
},
}
</script>
三、父访问子 $children
或者$refs
1)使用 $children
数组类型
可以访问到子组件的数据,方法
父
<template>
<div class="app">
<BaseProgress :w="width"></BaseProgress>
<BaseCount :count="count" @changeCount="handleChange"></BaseCount>
<button @click="btn">点击</button>
</div>
</template>
<script>
import BaseProgress from './components/BaseProgress.vue'
import BaseCount from './components/BaseCount.vue'
export default {
data() {
return {
width: 30,
count: 100
}
},
components: {
BaseProgress,
BaseCount
},
methods: {
handleChange(newVal) {
this.count = newVal
},
btn() {
console.log(this.$children);
//使用子组件方法
this.$children[1].handleSub()
//打印子组件数据
console.log(this.$children[1].name);
}
}
}
</script>
2)$refs
对象类型,默认空对象{}
<template>
<div class="app">
<BaseProgress :w="width" ref="base"></BaseProgress>
<button @click="btn">点击</button>
</div>
</template>
<script>
import BaseProgress from './components/BaseProgress.vue'
export default {
data() {
return {
width: 30
}
},
components: {
BaseProgress
},
methods: {
btn() {
console.log(this.$refs);
// 可以直接访问到子组件数据
console.log(this.$refs.base.uname);
}
}
}
</script>
四、子访问父 $parent
,$root
1)$parent
为父组件 VueComponent对象
子组件
<template>
<div class="base-progress">
<button @click="btnclick">子组件访问父组件</button>
</div>
</template>
<script>
export default {
data() {
return {
uname: 'value',
};
},
methods: {
btnclick() {
console.log(this.$parent);
}
}
}
</script>
2)$root
即为根组件,为vue实例
五、非父子通信使用事件总线event bus 或者provide & inject
1)event bus 事件总线
非父子组件之间,进行简易消息传递。复杂场景要使用vuex
- 创建一个都能访问到的事件总线 (空 Vue 实例)
在utils下新建EventBus.js
import Vue from 'vue';
const Bus = new Vue();
export default Bus
- A 组件(接收方),监听 Bus 实例的事件
在created里面监听bus事件
Bus.$on('事件名', (参数) => { })
BaseA组件
<template>
<div class="base-a">
我是A组件(接受方)
<p>{{msg}}</p>
</div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
data() {
return {
msg: '',
}
},
created() {
Bus.$on('sendMsg', (msg) => {
// console.log(msg)
this.msg = msg
})
},
}
</script>
<style scoped>
.base-a {
width: 200px;
height: 200px;
border: 3px solid #000;
border-radius: 3px;
margin: 10px;
}
</style>
- B 组件(发送方),触发 Bus 实例的事件
Bus.$emit('事件名', 携带的参数)
BaseB组件
<template>
<div class="base-b">
<div>我是B组件(发布方)</div>
<button @click="sendMsgFn">发送消息</button>
</div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
methods: {
sendMsgFn() {
Bus.$emit('sendMsg', '今天天气不错,适合旅游')
},
},
}
</script>
<style scoped>
.base-b {
width: 200px;
height: 200px;
border: 3px solid #000;
border-radius: 3px;
margin: 10px;
}
</style>
2)provide & inject
跨层级共享数据
- 父组件 provide 提供数据
父组件
export default {
provide(){
return {
str:this.str, //简单类型是非响应式的
obj:this.obj //复杂类型是响应式的
}
},
data(){
return {
str:'数据',
obj:{
name:'aa',
age:19
}
}
}
}
- 子/孙组件 inject 取值使用
子/祖孙组件
export default {
inject: ['str', 'obj'],
}
父组件中简单类型数据值发生变化,子/祖孙inject到的值不会响应式变化
父组件中复杂类型数据值发生变化,子/祖孙inject到的值响应式变化