一,父组件与子组件之间的通信
1,了解props属性
(1)props是单向绑定的,当父组件传递的数据发生变化时子组件props也会更新为最新值
(2)props的type(属性)和default(默认值)可以验证传入props参数的数据规格
(3)静态props传入的值不会发生变化,父组件中定义,子组件使用
(4)动态props要动态绑定父组件传入的数据
2,props静态传值子组件使用
<body>
<div id="box">
//通过父组件静态传值给子组件,子组件通过自定义属性接收父组件传的值
<navbar row="我是父组件的值"></navbar>
</div>
</body>
<script>
Vue.component("navbar",{
props:["row"],//通过props接收父组件传递的值
template:`
<div>
{{row}}
</div>
`
})
new Vue({
el:"#box",
data:{
// datalist:"我是父组件的值"
}
})
</script>
浏览器显示结果
3,父子通信通过props动态传递数据
<body>
<div id="box">
//动态绑定自定义属性 接收父组件的状态
<navbar :row="datalist"></navbar>
</div>
</body>
<script>
Vue.component("navbar",{
props:["row"],
template:`
<div>
{{row}}
</div>
`
})
new Vue({
el:"#box",
data:{
datalist:"我是父组件的动态值"
}
})
</script>
浏览器显示结果
4,props中type和default的使用
<body>
<div id="app">
<navbar myname="影院" :aaa="false"></navbar>
<navbar myname="电影" ></navbar>
</div>
</body>
<script>
Vue.component("navbar",{
props:{
//定义mymane的属性为字符串默认值为空,aaa为布尔型默认值为true
myname:
{
type:String,
default:""
},
aaa:{
type:Boolean,
default:true
}
},
template:`
<div style="background:red;border:5px solid black">
<button @click="handleft()" >left</button>
{{myname}}
<button @click="handright()" v-show="aaa">right</button>
</div>
`
})
new Vue({
el:"#app",
})
</script>
浏览器显示结果
5,子传父通过#emit事件传值
vm.#emit(evenname....,[args])
参数:evenname自定义事件名,[args] 需要发送的数据
作用:触发当前实例,附加参数都会传给监听器回调
<body>
<div id="box">
//@event父组件中自定义事件,父组件实现函数编写
<button-nav @event="eventprents"></button-nav>
</div>
</body>
<script>
Vue.component("buttonNav",{
data(){
return{
datalist:"我是子组件的数据"
}
},
template:`
<div>
//@click点击事件触发handshow函数
<button @click="handshow">按钮</button>
</div>
`,
methods:{
handshow(){
//函数运行 this.$emit触发event事件
//this.datalist是子组件向父组件传递的数据
this.$emit("event",this.datalist)
}
}
})
new Vue({
el:"#box",
methods:{
eventprents(){
//父组件接收数据并在控制台输出
console.log(res)
}
}
})
</script>
浏览器显示结果
6,通过ref实现子父组件通信
通过ref绑定元素可以通过this.$refs.name获取当前dom节点
通过ref绑定组件可以通过this.$refs.name获取当前组件实例,可以使用组件的方法
不介意使用ref直接改变子组件状态
<body>
<div id="box">
//ref绑定span标签
<span ref="a">aaaaaaaaaaa</span>
//通过点击事件触发handclick函数
<button @click="handclick">click</button>
//ref绑定navbar 组件
<navbar ref="b"></navbar>
</div>
</body>
<script>
Vue.component("navbar",{
data(){
return{
//定义子组件状态
mytext:"我是子组件的状态"
}
},
template:`
<div>
child
</div>
`
})
new Vue({
el: "#box",
data: {
},
methods: {
handclick(){
//获取span标签的dom节点
console.log(this.$refs.a)
//获取navbar组件的mytext状态
console.log(this.$refs.b.mytext)
}
}
})
浏览器显示结果
二,兄弟组件之间的通信
一,通过父组件作为中间人让其兄弟组件通信
子组件通过$emit事件给父组件传递值,父组件通过props属性传值给子组件
<div id="box">
//点击click事件调用handjson函数,获取json数据
<button @click="handjson">点击</button>
//父组件获取得json数据传给子组件navbar ,父组件复写eventclick函数
<navbar :list="datalist" @event="eventclick"></navbar>
//子组件filr-text接收子组件navbar 传递给父组件的数据
<filr-text :details="details"> </filr-text>
</div>
</body>
<script>
Vue.component("navbar",{
props:["list"],
template:`
<div>
<ul class="item">
<li v-for="(item,index) in list">
<img :src="item.img" alt="">
{{item.name}}
//点击事件触发handclick函数,并向函数发送一个index下标
<button @click="handclick(index)">詳情</button>
</li>
</ul>
</div>
`,
methods:{
handclick(index){
//函数运行触发this.$emit向event事件分发数据
//console.log(this.list[index].details)
this.$emit("event",this.list[index].details)
}
}
})
Vue.component("filrText",{
//接收子组件navbar发送给父组件,filrText通过动态绑定获取父组件状态
props:["details"],
template:`
<div class="filetext">
{{details}}
</div>
`
})
new Vue({
el:"#box",
data:{
datalist:'',
details:''
},
methods:{
handjson(){
//获取json数据
fetch("./test.json")
.then(res=>res.json())
.then(res=>{
//将json数据赋值给datalist
this.datalist=res.datalist
console.log(this.datalist)
// console.log(res.datalist)
})
},
eventclick(data){
//子组件向父组件发送的数据赋值给details
this.details=data
}
}
})
</script>
</html>
二,中央事件总线,订阅和发布模式
通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果
也就是:各个组件内部要传输的数据或者要执行的命令信息,靠bus来通信。
通过bus=new Vue()创建总线
bus.$emit("name") 发布者发布
bus.$on("name",回调接收) 订阅者接收
<div id="box">
<button @click="handjson">点击</button>
<navbar :list="datalist" ></navbar>
<filr-text > </filr-text>
</div>
</body>
<script>
//创建中央事件总线
var bus=new Vue();
Vue.component("navbar",{
props:["list"],
template:`
<div>
<ul class="item">
<li v-for="(item,index) in list">
<img :src="item.img" alt="">
{{item.name}}
<button @click="handclick(index)">詳情</button>
</li>
</ul>
</div>
`,
methods:{
handclick(index){
// console.log(this.list[index].details)
//发布者通过vue实例方法$emit发送事件名称和数据
bus.$emit("xiaoming",this.list[index].details)
// this.$emit("event",this.list[index].details)
}
}
})
Vue.component("filrText",{
data(){
return{
info:''
}
},
//挂载至生命周期
mounted(){
//订阅者通过发布者的事件名称接收发布者发送的数据
bus.$on("xiaoming",(data)=>{
this.info=data
})
},
template:`
<div class="filetext">
{{info}}
</div>
`
})
new Vue({
el:"#box",
data:{
datalist:'',
},
methods:{
handjson(){
fetch("./test.json")
.then(res=>res.json())
.then(res=>{
this.datalist=res.datalist
console.log(this.datalist)
// console.log(res.datalist)
})
},
}
})
</script>
</html>