1、Props
适用场景:父 -> 子
props的三种写法:
比如我要传name,age,sex这三个数据
-
字符串数组形式
(简单声明接收)
props:["name","age","sex"]
-
对象形式
(类型限制)
props:{ name:"String",//限制类型为字符串类型 age:"Number", sex:"String" }
-
对象形式
较为完整点,限制更多
props:{ name:{ type:"String", required:true, }, age:{ type:"Number", default:18 }, sex:{ type:"String", required:true, default:"男" } }
其中required指是否要求必填,default指如果没有值则以default的值传参。
required和default同时出现的情况不多。
2、自定义事件
适用场景:子 -> 父
子组件要想给父组件传递数据,就先要在父组件中给子组件绑定自定义事件(事件的回调在父组件上)
绑定自定义事件(两种方式):
注:demo是自定义事件的事件名字
-
在父组件中:
<Father @demo="test" />
或
<Father v-on:demo="test" />
-
在父组件中:
<Father ref="big" /> ...... muthods:{ test(){ ......//回调函数 } } mounted(){ this.$reds.big.$on("demo",this.test); //注意这里如果适用$refs方法的话,直接在里面写回调函数的时候, //要把回调写成箭头函数,否则this指向会出现问题! //如果回调在回调在methods里面就不用担心this指向了 }
触发自定义事件
在子组件中:
this.$emit("demo",数据);
解绑自定义事件
this.$off("demo");
组件上也可以绑定原生DOM事件,但需要添加native修饰符
<Father @click.native="test" />
3、全局事件总线
适用场景:任意组件间通用
安装全局事件总线:
new Vue({
......
beforeCreate(){
Vue.prototype.$bus = this;//$bus就是当前的VM
}
.....
})
使用全局事件总线
-
接收数据。A组件想要数据,B组件发送数据。则在A组件中给$bus绑定自定义事件,事件在回调函数在A组件身上。
A组件中
methods:{
test(data数据){
......//回调函数
}
},
mounted(){
this.$bus.$on("demo",this.test);
}
-
发送数据
B组件中:触发事件
this.$bus.$emit("demo",数据)
解绑全局事件总线:
在beforeDestroy钩子中利用this.$off()解绑当前组件用到的自定义事件。
4、消息订阅与发布
适用场景:任意组件间通用
使用步骤:
-
1、安装pubsub
npm install pubsub-js
-
2、引入pubsub
import pubsub from "pubsub-js"
-
3、接收数据。A组件要数据,B组件发送数据。
A组件中:
methods:{ test(data数据){ ...... } }, mounted(){ this.pid = pubsub.subscribe("demo",this.test);//订阅消息 }
-
4、接收数据
B组件中:
pubsub.publish("demo",数据);//发布消息
-
5、取消订阅
在beforeDestroy钩子中:
pubsub.unsunscribe(pid);
5、Vuex
适用场景:任意组件间通信
详细适用请看Vuex官方文档,这里只简单地写下用法。
使用步骤:
-
1、初始化数据,配置actions、mutations、state
export deafult { state:{ name:"", age:0, sex:"" }, actions:{ getData(context,value){//getData是actions的一个方法名 context.commit("GETDATA",value); //调用context下的commit方法提交给mutatins } }, mutations:{ GETDATA(state,value){//这里为了区分是mutations里的方法,写成大写 state.name = value.name; state.age = value.age; steta.sex = value.sex; } } }
-
组件中读取Vuex中的数据
this.$store.state("name")
-
组件中修改Vuex中的数据
this.$store.dispatch("getData");
或者
this.$store.commit("GETDATA");
注意:若没有网络请求或者其他业务逻辑,则可以直接绕过actions,然后直接commit到mutations修改数据
6、slot插槽
使用场景:父 -> 子
分类:默认插槽、具名插槽、作用域插槽
- 一、默认插槽
子组件中:
<template>
<h2>
{{title}}分类
</h2>
<slot>如果父组件什么结构也没给,就显示这句话</slot>
</template>
父组件中:
<template>
<Son title="游戏">
<ul>
<li v-for="item in games" :key="item.index">
{{item}}
</li>
</ul>
</Son>
</template>
...
data(){
return {
games:["洛克王国","天天酷跑","王者荣耀","QQ飞车"]
}
}
可以理解成slot是子组件挖了一个坑,然后父组件拿着结构去填充。
-
二、具名插槽
子组件中:
<template> <h2> {{title}}分类 </h2> <slot name="center"> 如果父组件什么结构也没给,就显示这句话 </slot> </template>
父组件中:
<template> <Son title="游戏"> <ul slot="center"> <li v-for="item in games" :key="item.index"> {{item}} </li> </ul> </Son> </template> ... data(){ return { games:["洛克王国","天天酷跑","王者荣耀","QQ飞车"] } }
-
三、作用域插槽
子组件中:
<template> <h2> {{title}}分类 </h2> <slot :games="games"> 如果父组件什么结构也没给,就显示这句话 </slot> </template> data(){ return { games:["洛克王国","天天酷跑","王者荣耀","QQ飞车"] } }
父组件中:
<template> <Son title="游戏"> <template scope="scopeData"> {{scopeData}} 这里其实就是传来的一个对象,里面有一个games数组 <ul> <li v-for="item in scopeData.games" :key="item.index"> {{item}} </li> </ul> </template> </Son> </template>
这里的作用域插槽,其实就是数据在子组件上,但是根据数据生成的结构需要父组件来决定。(games在子组件上,但使用数据所遍历出来的结构由父组件决定)