首先Vue组件之间的传值有两种
父子通信和非父子通信(bus通信)
1.父子通信
父传子:
首先你得传一个值过去吧
<body>
<div id="app">
<input type="button" @click="handlclik" value="点击" />
<navbar :mytitle="title" v-for="title in list" ></navbar>
</div>
</body>
<script>
Vue.component('navbar', {
template: `<div>{{mytitle}}</div>`,
props: ["mytitle"],
data() {
return {
data: '这是一段组件插入',
}
},
methods: {
}
})
var vue = new Vue({
el: '#app',
data: {
list: ['首页', '列表', '详情'],
},
methods: {
handlclik() {
}
}
})
</script>
父传子类似于传过去一个键值对(key:value) 比如上述导航栏组件中,父传子的是一个mytitle:title 键值对,用了一个v-for循环取出里面的值:首页,列表,详情等,然后传给子组件.
父亲传过去了,子组件当然要接收了 ,于是子组件定义了props属性数组来接收父亲传过来的对象,类似于你爸给你打钱,你得用微信或银行卡来接收.
然后就能显示了
当然你也可以传很多东西,只是要增加键值对的数量
比如
<navbar :mytitle="title" mymsg="多来一个字符串!" v-for="title in list" ></navbar>
//然后相应的子组件要接收他
props:["mytitle","mymsg"]
此方法只适用于传 字符串! 当然了,你也可以在子组件中进行强转,但未免太过麻烦,所以我们是能直接接收来自父组件的类似于boolean值或者number值的
只要更改一下props格式:
props: {
mytitle:String,
mymsg:Number,
myboolean:Boolean,
},
//相应的父组件
<navbar :mytitle="title" :mymsg='123' :myboolean='true'
v-for="title in list" ></navbar>
显示的为
还有一种写法
props: {
mytitle: {
type: String,
default: ''
}
}
这里就有一个type类型,表示我这个mytitle期望获得一个String类型的值,如果是别的就会报错,default 为空,表示默认为空值,有时候我们要传给子组件一个值,只是暂时我们还没有传,但我们已经写好了这种通信方式,只是没有传过去而已,这时我们就有一个默认值default,一旦我们传过去一个值,就会覆盖这个default默认值
2.子传父
记住子传父是通过事件触发的,也可以把你给你爸打钱理解为一个事件!
首先你得你孩子你得银行卡吧
<navbar @bank-card="reciveMoney" ></navbar>
然后孩子用事件就得打钱吧
Vue.component('navbar', {
template: `<div><button @click="handleClick">给爸爸打钱!</button></div> `,
data() {
return {
money: 10000,
}
},
methods: {
handleClick(){
this.$emit("bank-card",this.money);
}
}
})
这里得this.$emit就是打钱得意思emit有发射的意思,理解为打钱就行了
,然后bank-card就是你要打钱的银行卡,this.money就是你要打的钱
打完了父亲得接收吧
methods: {
reciveMoney(childMoney) {
console.log(childMoney)
}
}
接收完了就ok了,
还有一种方式,通过ref
介绍一下ref:ef 被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例
注意:只要想要在Vue中直接操作DOM元素,就必须用ref属性进行注册
例如:
<body>
<div id="app">
<input type="text" ref='mytext' />
<div ref='mydiv'></div>
<button @click="handleClick">点击获取dom节点</button>
<navbar></navbar>
</div>
</body>
<script>
Vue.component('navbar', {
template: `<div></div>`,
data() {
return {
money: 10000,
}
},
methods: {
}
})
new Vue({
el: '#app',
data: {
list: ['首页', '列表', '详情'],
money: '',
},
methods: {
handleClick() {
console.log(this.$refs)
}
}
})
</script>
点击获取dom节点,控制台就会打印:
看到这里大家已经大概明白了
比如我想获得输入框的内容
改一下代码:
console.log(this.$refs.mytext.value)
打印的就会是
这样呢,如果把他加在组件中呢?
改一下代码
<navbar ref='mynavbar'></navbar>
console.log(this.$refs.mynavbar)
打印的:
是不是直接就获得了money的值了呢
拿来用就可以直接
this.$refs.mynavbar.money
注意:ref方法可以做到,但是在开发中不推荐使用,因为他不经过子组件的同意直接拿到子组件的值修改使用,万一将来数据出错,由于不知道数据是谁修改的,将极大的增加纠错难度,不推荐使用!
3.兄弟组件传值(子组件传子组件)
1.找个相同的父组件,通过父组件作为中间人传值,方法同上
2.bus通信
中间人传值可以解决一些简单的问题,但是如果子组件嵌套子组件呢?比如你的孩子又有了一个孩子,你孩子的孩子还有了一个孩子,总不能一个个找父亲,一个个传回来吧?
这时就可以用bus通信,bus:中央控制总线
通过中央控制总线来进行各个组件的传值
首先定义一个bus,很简单,一个空的vue,名字为bus(其实名字你随意取),
var bus = new Vue()
其实这个就类似于微信的发布-订阅模式,或者有点像java的观察者模式,
用bus.$on来监听,bus. $emit来发布
<body>
<div id="app">
<child1></child1>
<child2></child2>
</div>
</body>
<script>
var bus = new Vue()
Vue.component('child1', {
template: `<div><button @click='emit'>发布</button></div>`,
data() {
return {
msg1:'震惊!zs竟然干出这种事...'
}
},
methods: {
emit(){
bus.$emit('wechat',this.msg1);
}
}
})
Vue.component('child2', {
template: `<div>{{msg2}}</div>`,
data() {
return {
msg2:''
}
},
mounted() {
bus.$on("wechat",(data)=>{
console.log(data)
this.msg2=data
})
}
})
new Vue({
el: '#app',
data: {
list: ['首页', '列表', '详情'],
money: '',
},
methods: {
handleClick() {
console.log(this.$refs.mynavbar.money)
}
}
})
</script>
也类似于中间人,不过这个中间人是bus,通过bus.$on和bus. $emit同时监听wechat,发送和接收消息,也是通过方法接收发送的,mounted方法是vue生命周期创建时自动调用的一个方法,(data)=>{}是方法的简写模式,省略了方法名,data就是传来的msg1,这样就实现了子组件子组件的传值