1.兄弟组件传值
使用 $on(event,callback) 监听事件
使用 $emit(event, […args]) 触发事件
现有子组件a.vue,b.vue,它两是平级,现在要让a组件给b组件传值,a组件中的按钮点击,改变b组件中的值。
第一步:新建一个bus.js,并把该js分别引入到a,b组件中
//bus.js代码如下
import Vue from 'vue'
const bus=new Vue();
export default bus
使用如下方法分别引入到a,b组件中:
<script>
import bus from "@/plugin/eventbus.js";
};
</script>
在a组件中点击按钮通过bus.$emit(),把值传递给b组件:
<template>
<div>
<span @click="fun">点击传值</span>
</div>
</template>
<script>
import bus from "@/plugin/eventbus.js";
export default {
data() {
return {};
},
methods: {
fun() {
//通过bus.$emit进行发送事件,"myclick"表示事件名,第二个参数表示要传递的参数值
bus.$emit("myclick", "我来自a");
},
},
};
</script>
在b组件中通过bus.$on()来接收a组件传递过来的值
<template>
<div>
{{cname}}
</div>
</template>
<script>
import bus from "@/plugin/eventbus.js";
export default {
data(){
return{
cname:""
}
},
mounted(){
//通过bus.$on()来接收a组件传递过来的值,第一个参数“myclick”表示事件名,第二个参数放要执行的方法,这个值需要如何处理,比如我把这个值赋值给b组件中的cname变量
bus.$on('myclick',item=>{
this.cname=item;
})
}
}
</script>
现在把a,b组件都放入通一个父组件father.vue中,就完成了。
<template>
<div>
<a></a>
<b></b>
</div>
</template>
<script>
import a from '../components/a.vue';
import b from '../components/b.vue';
export default{
components:{a,b}
}
</script>
2.父子组件传值
子组件的传值是通过props来传递数据,$emit来触发事件;
props
1.如果无需验证,可以使用字符串数组格式
例如:
props: ['childArray','myname','userinfo']
2.如果需要验证,则需要使用对象格式,可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue会发出警告。当组件给其他人使用时,这很有用,要指定验证规格,需要用对象的形式,而不能用字符串数组。
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
注意:prop是单向数据流
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解
另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着不应该在子组件内部改变 prop。如果这么做了,Vue 会在控制台给出警告
实例:子组件要从父组件获取数据,并且子组件还要修改该内容?
解决办法:使用变量储存prop的初始值,并使用watch来观察prop的值的变化。发生变化时,更新变量的值
//在子组件中
<template>
<div>
获取父组件的传递过来的值:{{username}}
</div>
</template>
<script>
export default{
props:["fatherinfo"],
data(){
return{
username:this.fatherinfo
}
},
watch:{
//监听父组件的数据有无变化,如果变化,及时传递给子组件
fatherinfo(val){
this.username=val
}
}
}
</script>
//父组件中
<template>
<div>
<myvuea :fatherinfo="info"></myvuea>
</div>
</template>
<script>
import myvuea from "@/components/a.vue";
export default {
components: {
myvuea,
},
data(){
return{
info:"我的数据"
}
}
};
</script>
$emit
子组件可以使用 $emit
,让父组件监听到自定义事件 。$emit
绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数。
//在子组件中
<template>
<div>
<span @click="sendfather">向父组件发送数据</span>
</div>
</template>
<script>
export default{
methods:{
sendfather(){
//通过$emit发送数据到父组件,'childfun'表示事件名,第二个参数表示要发送给父组件的数据,可以传递多个参数this.$emit('childfun','x1','x2','x3');
this.$emit('childfun','今天天气不错');
}
}
}
</script>
//父组件中
<template>
<div>
// @childfun是子组件传递过来的事件名
<myvuea @childfun="getFun"></myvuea>
</div>
</template>
<script>
import myvuea from "@/components/a.vue";
export default {
components: {
myvuea,
},
methods: {
getFun(v) {
//参数v就是子组件传递过来的数据,当点击子组件中的按钮,就可以获取v的值
console.log(v);
},
},
};
</script>
3.父组件获取子组件中的所有函数和方法ref
- 如果ref用在子组件上,指向的是组件实例,可以理解为对子组件的索引,通过$ref可能获取到在子组件里定义的属性和方法。
- 如果ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通过$ref可能获取到该DOM 的属性集合,轻松访问到DOM元素,作用与JQ选择器类似。
要点:父组件中可以通过this.$refs.refName来访问元素或子组件的实例。
注意:this.$refs
是一个对象,持有当前组件中注册过 ref特性的所有 DOM 元素和子组件实例
注意:
$refs
只有在组件渲染完成后才填充,在初始渲染的时候不能访问它们,并且它是非响应式的,因此不能用它在模板中做数据绑定
1.ref 需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用,或者在 this.$nextTick(()=>{}) 中调用。
2.如果ref 是循环出来的,有多个重名,那么ref的值会是一个数组 ,此时要拿到单个的ref 只需要循环就可以了。
现在有子组件children.vue
<script>
export default{
data(){
return{
userinfo:{
name:"丽丽",
age:12
}
}
},
methods:{
myage(){
console.log("haha");
}
}
}
</script>
现在有父组件father.vue
<template>
<div>
//在父组件中给子组件添加一个ref
<myvuea ref="children"></myvuea>
</div>
</template>
<script>
import myvuea from "@/components/a.vue";
export default {
components: {
myvuea,
},
data() {
return {};
},
mounted(){
//获取子组件中的对象
let myuser=this.$refs.children.userinfo;
//获取并执行子组件中的方法
this.$refs.children.myage();
}
};
</script>