组件通信常用方式
基础方面必回的有:
父子组件传参
- props(父传子)
- $emit(event)(子传父)
其他组件传参
- vuex
- eventBus(事件总线:事件监听事件发布机制)
补充:其它
- $parent
- $refs/$children
- provide/ inject
- 能够实现祖先和后代之间传值
- $attrs / $listeners
- 包含了父作用域中不作为props被识别(且获取)的特性绑定(class和style除外)
补充:
eventBus
使用范围:
组件之间没有特定的关系,
适用场景如:导航栏有用户头像展示,我们通过个人中心设置修改用户头像,如何把我们的修改实时同步到导航栏中;
或者导航栏消息中心按钮有个图标显示当前的未读消息,用户进入消息中心后未读消息操作后变已读,及时更新到图标;
//实例:
//vue项目的main.js中全局定义
Vue.prototype.$EventBus = new Vue() // 定义全局的事件总线
// 当我们消息被修改后 发布事件
this.get(····,(res) => {
if (res.success == 'true') {
this.totalCount = res.data.totalCount
// 操作后更新数据,事件发布
+ this.$EventBus.$emit('navTotalCount',this.totalCount)
} else {
this.$message.error(res.msg);
}
},
(error) => {
this.$message.error('获取数据失败,请稍后重试');
}
);
// 如何获取 事件监听
//一般使用在生命周期created和mounted中 实例如下
created(){
// 监听eventbus获取收件箱未读消息总数
this.$EventBus.$on('navTotalCount', (val) => {
this.navtotalcount = val
})
},
解释:
Vue.prototype.$EventBus = new Vue():在vue的原型上定义一个EventBus属性,定义一个vue实例对象
引用
- p a r e n t , parent, parent,refs/$children
目标:在父组件中操作子组件(数据,方法)
在父组件中通过 this.$refs.子组件的引用
, this.$children[0]
都可以获取对子组件的引用-----直接拿到子组件的实例。
hclick () {
//console.dir(this.$children)
// 在父组件中获取子组件的引用
// 第一种方法: 给子组件加ref (this.$refs.com1)
// 再通过这个引用去访问子组件的数据,方法
this.$refs.com1.com11Method('abcccc1111')
// console.log(this.$refs.com1.msg)
// 第二种方法:this.$children。会得到一个数组,其中
// 保存对当前所有子组件的引用
}
在子组件中操作父组件(数据,方法)
// # this.$parent.数据项
// # this.$parent.方法()
hClick () {
// this.$parent 会获取父组件的实例。
// 通过父组件的实例就可以直接调用父组件的数据,方法
console.log(this.$parent.num)
this.$parent.num = 1000000
// 直接可以操作父组件中的数据修改
}
这种方式破坏了vue的单向数据流,不能体现父子组件之间的关系,不推荐使用
provide/ inject
场景:在祖先组件中有数据希望传给后代组件。
解决方案:provide/inject来实现。
步骤:
(1)在祖先组件中,通provide配置项来初始化数据。
provide () {
return {
num: 100
}
}
(2)后代组件中,通过inject来接收这个数据。
<div>
{{num}}
</div>
inject: ['num']
注意:
- 跨代传递
- 不具备响应式的效果。
$attrs / $listeners
场景:
从祖先传消息给孙子,重孙子(跨组件传递)
上面的例子,com11.vue只是中间过渡一下,不接收数据,也不需要抛出事件。中间(儿子)组件不需要进行接收进行传递
$attrs
在父组件中向子组件上添加自定义属性时,如果子组件内部没有通过props去接收,则它就自动收集到$attrs中。
about.vue
<son a="1" b="2" @someevent="hSomeevent"></son>
son.vue
它对a,b不感兴趣,它自己没有props去接收,所以a,b到这里之后,被收集到 a t t r s 中 , 用 attrs中,用 attrs中,用attrs向下级组件传递
<grandson v-bind="$attrs" v-on="$listeners"></grandson>
grandson.vue
props:['a','b'] // 收到从son中传递的数据
this.$emit('someevent')
原理图
params和query的区别
- 普通字符串,进行带参数的跳转。
<!-- 路径传参 路由规则{path:'/article/:id'}-->
<router-link to="/article/10001"></router-link>
## 接收参数:this.$route.params.id
<!-- 查询传参 路由规则{path:'/article'}-->
<router-link to="/article?id=10001"></router-link>
## 接收参数:this.$route.query.id
- 对象格式
params传参时需要加name值
<router-link :to="{path:'/item'}">普通跳转</router-link>
<router-link :to="{path:'/item?a=100'}">查询参数</router-link>
<router-link :to="{path:'/detail/1001'}">对象表示-带路径参数</router-link>
<router-link :to="{path:'/item',query:{a:100}}">查询参数-query</router-link>
<router-link :to="{name:'detail',params:{id:1002}}">路径参数-params</router-link>
路由传参中params和query的区别,什么场景该使用哪个?
-
类似文章详情页:/detail/1001
-
类似查询页:/search?a=1&b=2
name属性的作用及使用场景
-
name用来标识一个路由。在做跳转时,可能path比较深比较长,不好记忆(ip和域名),所以用name来跳。
this.$router.push({name:''})
-
在使用对象格式时传params时,必须要写name,而不能写path。
<router-link :to="{name:'detail',params:{id:1002}}">路径参数-params</router-link>
vuex
state, 状态管理数据
muation,修改state数据
state使用:
1、this.$store.state.XXX
2、map映射方式使用
import {mapState} from 'vuex'
compute:{...mapState(['xxx'])}
muation使用:
muation方法只能有两个参数,一个是state,一个是接受的参数,所以组件内部使用时只能穿一个参数(数值,字符,数组,对象),第二个参数无效
1、this.$store.commit('muation里面的方法名',n)
2、map映射方式使用
import {mapMutations} from 'vuex'
methods:{
...mapMutations(['xxx'])
// ...mapMutations({newname:'oldname'}) 重命名
sub(){
this.xxx()
// this.newname()
}
}
上述两个比较基础这里不做详细介绍
getters : 与计算属性相似。
actions:作用:Action 类似于 mutation,异步方式间接修改数据
module:模块化 state中数据过多,可以将state分割成模块,每个模块拥有自己的state,mutation,action,getter等
getters : 与计算属性相似。(data ----- computed, state ----- getter)
作用: 它的作用在state的基础上,派生一些新的状态
定义:
getters: { //它的第一个参数就是state。
gAge (state) {
return state.age > 30 ? '大哥' : '小哥哥'
},
gAge1 (state) {
return state.age > 30 ? '大哥' : '小哥哥'
}
}
调用:在组件内部,可以
(1)直接 $store.getters.getter的名字 来获取
(2) map映射
<p>{{gAge1}}</p>
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['gAge1'])
}
actions
作用:Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。如ajax调取接口
定义
actions: {
// 定义:
// action在执行的过程,会自动得到context:当前的state
aIncrement (context) {
setTimeout(() => {
// 用来发ajax取数据,把数据取回来之后,放到state context是当前的state对象,可以使用{state,getter,commit,dispatch}
context.commit('increment')
}, 3000)
}
}
调用
在组件中:
(1)this.$store.dispatch('actions名')
(2) map
methods: {
...mapActions(['aIncrement']),
hClick () {
this.aIncrement()
}
}
发ajax取数据,把数据取回来之后,放到state
actions:发请求,获取数据,调用mutation保存到state中。