Vue组件通信

props

父传子组件的属性,props值可以是一个数组或对象。

$emit

子传父组件绑定自定义事件。

1
2
3
4
// 父组件
<home @title="title">
// 子组件
this.$emit('title',[{title:'这是title'}])

vuex

vuex是一个状态管理器插件,适合数据共享多的项目。

  • state:定义存储数据的仓库,可通过this.$store.statemapState访问;
  • getters:获取store值,可认为是store的计算属性,可通过this.$store.gettersmapGetters访问;
  • mutations:同步改变store值,为什么会设计成同步,因为mutation是直接改变store值,Vue对操作进行了记录,如果是异步无法追踪改变,可通过mapMutations调用;
  • actions:异步调用函数执行mutation,进而改变store值,可通过this.$dispatchmapActions访问;
  • modules:模块,如果状态过多,可以拆分成模块,最后在入口通过...解构引入。

parent父实例和children子实例

  • 父组件this.$children
  • 子组件this.$parent

childrenparent并不保证顺序,也不是响应式,只能拿到一级父组件和子组件。

$refs

1
2
3
4
5
6
// 父组件
<home ref="home"/>

mounted(){
// this.$refs.home 即可拿到子组件的实例,就可以直接操作 data 和 methods
}

$root

1
2
3
4
5
6
// 父组件
mounted(){
console.log(this.$root) //获取根实例,最后所有组件都是挂载到根实例上
console.log(this.$root.$children[0]) //获取根实例的一级子组件
console.log(this.$root.$children[0].$children[0]) //获取根实例的二级子组件
}

.sync

1
2
3
4
5
6
7
8
9
10
// 父组件
<home :title.sync="title" />
//编译时会被扩展为
<home :title="title" @update:title="val => title = val"/>

// 子组件
// 子组件可以通过$emit触发 update 方法改变
mounted(){
this.$emit("update:title", '这是新的title')
}

v-slot

v-slot作用就是将父组件的template传入子组件。

插槽分类:匿名插槽(默认插槽),没有命名,有且仅有一个。

1
2
3
4
5
6
7
8
9
10
11
// 父组件
<todo-list>
<template v-slot:default>
任意内容
<p>我是匿名插槽</p>
</template>
</todo-list>

// 子组件
<slot>我是默认值</slot>
//v-slot:default写上感觉和具名写法比较统一,容易理解,也可以不用写

具名插槽:相对匿名插槽组件slot标签带name命名。

1
2
3
4
5
6
7
8
9
10
// 父组件
<todo-list>
<template v-slot:todo>
任意内容
<p>我是匿名插槽</p>
</template>
</todo-list>

//子组件
<slot name="todo">我是默认值</slot>

作用域插槽:子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 父组件
<todo-list>
<template v-slot:todo="slotProps" >
{{slotProps.user.firstName}}
</template>
</todo-list>
//slotProps 可以随意命名
//slotProps 获取的是子组件标签slot上属性数据的集合所有v-bind:user="user"

// 子组件
<slot name="todo" :user="user" :test="test">
{{ user.lastName }}
</slot>
data() {
return {
user:{
lastName:"Zhang",
firstName:"san"
},
test:[1,2,3,4]
}
},
// {{ user.lastName }}是默认数据 v-slot:todo 当父页面没有(="slotProps")

EventBus

  1. 生命一个全局Vue实例变量EventBus,把所有的通信数据、事件监听都存储到这个变量上;
  2. 类似于Vuex,但这种方式只适用于极小的项目;
  3. 原理就是利用onemit,并实例化一个全局Vue实现数据共享;
  4. 可以实现平级、嵌套组件传值,但是对应的事件名eventTarget必须是全局唯一的。
1
2
3
4
5
6
7
8
9
10
// 在 main.js
Vue.prototype.$eventBus=new Vue();

// 传值组件
this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值')

// 接收组件
this.$eventBus.$on("eventTarget",v=>{
console.log('eventTarget',v);//这是eventTarget传过来的值
})

路由传参

  1. 方案一:
1
2
3
4
5
6
7
8
9
10
11
12
// 路由定义
{
path: '/describe/:id',
name: 'Describe',
component: Describe
}
// 页面传参
this.$router.push({
path: `/describe/${id}`,
})
// 页面获取
this.$route.params.id
  1. 方案二:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 路由定义
{
path: '/describe',
name: 'Describe',
omponent: Describe
}
// 页面传参
this.$router.push({
name: 'Describe',
params: {
id: id
}
})
// 页面获取
this.$route.params.id
  1. 方案三:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 路由定义
{
path: '/describe',
name: 'Describe',
component: Describe
}
// 页面传参
this.$router.push({
path: '/describe',
query: {
id: id
`}
)
// 页面获取
this.$route.query.id

三种方案对比,方案二参数不会拼接在路由后面,页面刷新参数会丢失;方案一和三参数拼接在后面,暴露了信息。