组件之间的数据共享

8/18/2022 vue

# 组件之间的数据共享

# 1. 组件之间的关系

在项目开发中,组件之间的关系分为如下 3 种:

① 父子关系

② 兄弟关系

③ 后代关系

在这里插入图片描述

# 2. 父子组件之间的数据共享

父子组件之间的数据共享又分为:

① 父、子共享数据

② 子、父共享数据

③ 父、子双向数据同步

# 2.1 父组件向子组件共享数据

父组件通过 v-bind 属性绑定向子组件共享数据。同时,子组件需要使用 props 接收数据。示例代码如下:

// 父组件
<template>
  <h2>app根组件</h2>
  <button @click="count += 1">+1</button>
  <hr>
  <son :name="name" :count="count"></son>
</template>

<script>
import son from './son.vue'
export default {
  name:'MyApp',
  data(){
    return{
      name:'星月',
      count:0
    }
  },
  components:{
    son
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 子组件
<template>
  <h2>son子组件</h2>
  name:{{ name }}
  count:{{ count }}
</template>

<script>
export default {
  name:'MySon',
  props:['name','count']
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

点击父组件的button,count成功传递到子组件:

在这里插入图片描述

# 2.2 子组件向父组件共享数据

子组件通过自定义事件的方式向父组件共享数据。示例代码如下:

<!-- 父组件 -->

<template>
  <h2>app根组件---{{ this.count }}</h2>
  <button @click="count += 1">+1</button>
  <hr>
  <son @addcount="getadd"></son>
</template>

<script>
import son from './son.vue'
export default {
  name:'MyApp',
  data(){
    return{
      name:'星月',
      count:0
    }
  },
  components:{
    son
  },
  methods: {
    getadd(con){
      this.count = con
    }
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- 子组件 -->

<template>
  <h2>son子组件</h2>
  <button @click="add">+1</button>
  count:{{ count }}
</template>

<script>
export default {
  name:'MySon',
  emits:['addcount'],
  data(){
    return{
      count:0
    }
  },
  methods: {
    add(){
      this.count += 1
      this.$emit('addcount',this.count)
    },
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2.3 父子组件之间数据的双向同步

父组件在使用子组件期间,可以使用 v-model 指令维护组件内外数据的双向同步:

① 在 v-bind: 指令之前添加 v-model 指令

② 在子组件中声明 emits 自定义事件,格式为 update:xxx

③ 调用 $emit() 触发自定义事件,更新父组件中的数据

在这里插入图片描述

app.vue代码

<template>
  <h1>app根组件{{ count }}</h1>
  <button @click="add">+1</button>
  <hr>
  <mymode v-model:mycount="count"></mymode>
</template>

<script>
import mymode from './mode.vue'

export default {
  name:'MyApp',
  data(){
    return{
      count:1
    }
  },
  components:{
    mymode
  },
  methods:{
    add() {
      this.count++
    }
  }

}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

mode.vue代码

<template>
  <h2>model子组件</h2>
  count的值:{{ mycount }}
  <button @click="add">+1</button>
</template>

<script>
export default {
  name:'mymodel',
  props:['mycount'],
  emits:['update:mycount'],
  methods:{
    add() {
      this.$emit('update:mycount',this.mycount + 1)
    } 
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3. 兄弟组件之间的数据共享

兄弟组件之间实现数据共享的方案是 EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实

现兄弟组件之间的数据共享。示意图如下:

在这里插入图片描述

# 3.1 安装 mitt 依赖包

在项目中运行如下的命令,安装 mitt 依赖包:

npm install mitt@2.1.0
1

# 3.2 创建公共的 EventBus 模块

在项目中创建公共的 eventBus 模块如下:

// 导入mitt包
import mitt from 'mitt'

// 创建 eventBus实例对象
const bs = mitt()

// 将实例导出
export default bs
1
2
3
4
5
6
7
8

# 3.3 在数据接收方自定义事件

在数据接收方,调用 bus.on('事件名称', 事件处理函数) 方法注册一个自定义事件。示例代码如下:

<template>
<hr>
  <h2>rigth数据接收--{{ count }}</h2>
</template>

<script>
import bs from './eventBus.js'

export default {
  data(){
    return{
      count:0
    }
  },
  created() {
    bs.on('add',(e)=>{
      this.count = e
    })
  },

}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 3.4 在数据接发送方触发事件

在数据发送方,调用 bus.emit('事件名称', 要发送的数据) 方法触发自定义事件。示例代码如下:

<template>
  <h2>left数据发送方</h2>
  {{ count }}
  <button @click="add">+1</button>
</template>

<script>
import bs from './eventBus.js'

export default {
  data(){
    return{
      count:0
    }
  },
  methods: {
    add(){
      this.count += 1
      bs.emit('add',this.count)
    }
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在数据发送方点击++,接收放数据跟着同步:

在这里插入图片描述

# 4. 后代关系组件之间的数据共享

后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用 provide 和 inject 实现后代关系组件之间的数据共享。

在这里插入图片描述

# 4.1 父节点通过 provide 共享数据

父节点的组件可以通过 provide 方法,对其子孙组件共享数据:

<template>
  <h2>app根组件</h2>
  <hr>
  <lift></lift>
</template>

<script>
import lift from './left.vue'
import rigth from './rigth.vue'

export default {
  name:'MyApp',
  data(){
    return{
      name:'星月',
      count:0   // 定义需要共享的数据
    }
  },
  provide(){  // 把需要共享的数据 return 出去
    return{
      count:this.count
    }
  },
  components:{
    lift,
    rigth,
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 4.2 子孙节点通过 inject 接收数据

子孙节点可以使用 inject 数组,接收父级节点向下共享的数据。示例代码如下:

<template>
<hr>
  <h2>三级组件</h2>
  共享过来的count: {{ count }}
</template>

<script>
export default {
  inject:['count']   // 使用 inject 接收共享过来的数据
}
</script>

1
2
3
4
5
6
7
8
9
10
11
12

# 4.3 父节点对外共享响应式的数据

父节点使用 provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据。示例代码如下:

<script>
import { computed } from 'vue'  //从vue中按需导入 computed 函数

export default {
  name:'MyApp',
  data(){
    return{
      // 定义需要共享的数据
      count:1   
    }
  },
  provide() {  // 把需要共享的数据 return 出去
    return {  // 使用computed 函数,把数据包装为响应式的数据
      count:computed(() => this.count)
    }
  },
  components:{
    lift,
    rigth,
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 4.4 子孙节点使用响应式的数据

如果父级节点共享的是响应式的数据,则子孙节点必须以 .value 的形式进行使用。示例代码如下:

<template>
<hr>
  <h2>三级组件</h2>
  共享过来的count: {{ count.value }}
</template>

<script>
export default {
  inject:['count']
}
</script>
1
2
3
4
5
6
7
8
9
10
11

# 5. vuex

vuex 是终极的组件之间的数据共享方案。在企业级的 vue 项目开发中,vuex 可以让组件之间的数据共享变得高 效、清晰、且易于维护。

在这里插入图片描述

# 6. 总结

  • 父子关系

​ ① 父 、子 属性绑定;

​ ② 子、父 事件绑定;

​ ③ 父、子互传组件上的 v-model;

  • 兄弟关系

​ ④ EventBus

  • 后代关系

​ ⑤ provide & inject

  • 全局数据共享

​ ⑥ vuex(后面单独学习)

Last Updated: 9/7/2022, 11:32:53 PM