【Vuejs】1025- Vue 组件通信的 8 种方式

我就是我 2022-08-31 00:53 310阅读 0赞

前言

做了半年的公司系统,终于就在前天上线了。后期改BUG时间拖得太长了,出现的大部分BUG 是 前端 与后端 信息不对称导致的,逻辑性错误不怎么多,业务比较用户体验上稍微差点,毕竟第一次做这么大的系统(100w+),通过这次系统的开发,总结了不少经验,如何更好的跟后端人员协作开发以及如何设计来提高用户体验上,之前自己做开发没关注这方面,只注重功能实现,后期的这块多补补。
项目上线后,接下来就是后期的维护更新了,最近时间终于不是之前那么忙碌了,简单的对系统做了下复盘。由于项目采用的技术栈是Vue, 平常开发只注重功能实现了,接下来陆续会对 Vue 深入分析,来封装常用业务组件,以及Vue源码解析

本章将是对Vue 组件通信的8方法总结,日常开发使用组件通信非常密切,熟悉组件通信可以更好的开发业务。

d3ccff23ca40e9d854a0cc5d7b80931e.png

Vue 组件之间传值

1. 父组件 向 子组件 传递值

  1. 在父组件中引入子组件

      1. 注册子组件
      1. 在页面中使用,子组件标签上 动态绑定传入动态值 / 静态值
      1. 在子组件中,使用 props 来接受 父组件 传递过了的值

    「子组件接收的父组件的值分为引用类型和普通类型两种:」

    • 「普通类型:字符串(String)、数字(Number)、布尔值(Boolean)、空(Null)」
    • 「引用类型:数组(Array)、对象(Object)」

  1. #父组件
  2. <template>
  3. <div>
  4. <!-- 传递值 -->
  5. <Test
  6. :obj="obj"
  7. info="测试"/>
  8. </div>
  9. </template>
  10. <script>
  11. // 引入子组件
  12. import Test from "../components/Test.vue";
  13. export default {
  14. name: "about",
  15. // 注册子组件
  16. components: {
  17. Test,
  18. },
  19. data() {
  20. return {
  21. obj: {
  22. code: 200,
  23. title: "前端自学社区",
  24. },
  25. };
  26. },
  27. };
  28. </script>
  29. <template>
  30. <div>
  31. <h1>{
  32. {obj.code}}</h1><br>
  33. <h2>{
  34. {obj.title}}</h2>
  35. <h3>{
  36. {info}}</h3>
  37. </div>
  38. </template>
  39. <script>
  40. export default {
  41. name:'test',
  42. props:{
  43. obj:Object,
  44. info: [String,Number] //info值为其中一种类型即可,其他类型报警告
  45. }
  46. }
  47. </script>

由于 Vue 是 单向数据流, 子组件 是不能直接 修改 父组件 的 值。

2. 子组件 向父组件传递值

子组件通过绑定事件,通过 this.$emit('函数名',传递参数)

  1. #父组件
  2. <Test
  3. :obj="obj"
  4. info="测试"
  5. @modify="modifyFatherValue"/>
  6. <script>
  7. // 引入子组件
  8. import Test from "../components/Test.vue";
  9. export default {
  10. name: "about",
  11. // 注册子组件
  12. components: {
  13. Test,
  14. },
  15. data() {
  16. return {
  17. msg:'我是父组件'
  18. };
  19. },
  20. methods:{
  21. // 接受子组件传递来的值,赋值给data中的属性
  22. modifyFatherValue(e){
  23. this.msg = e
  24. }
  25. }
  26. };
  27. </script>
  28. # 子组件
  29. <button @click="modifyValue">修改父组件的值</button>
  30. <script>
  31. export default {
  32. name:'test',
  33. methods:{
  34. modifyValue(){
  35. this.$emit('modify','子组件传递过来的值')
  36. }
  37. }
  38. }
  39. </script>

3. 父组件 通过 $refs / $children 来获取子组件值

$refs :

  • 获取DOM 元素 和 组件实例来获取组件的属性和方法。
  • 通过在 子组件 上绑定 ref ,使用 this.$refs.refName.子组件属性 / 子组件方法

$children :

  • 当前实例的子组件,它返回的是一个子组件的集合。如果想获取哪个组件属性和方法,可以通过 this.$children[index].子组件属性/f方法

示例 Text 组件

  1. <script>
  2. export default {
  3. name:'test',
  4. data() {
  5. return {
  6. datas:"我是子组件值"
  7. }
  8. },
  9. props:{
  10. obj:Object,
  11. info: [String,Number]
  12. },
  13. methods:{
  14. getValue(){
  15. console.log('我是Test1')
  16. }
  17. }
  18. }
  19. </script>

示例 Text2组件

  1. <template>
  2. <div>
  3. <h1>我是Test2</h1>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name:'test',
  9. data() {
  10. return {
  11. datas:"我是Test2"
  12. }
  13. },
  14. created(){
  15. console.log( this.$parent.obj )
  16. this.$parent.getQuery()
  17. },
  18. methods:{
  19. getTest2(){
  20. console.log(this.datas)
  21. }
  22. }
  23. }
  24. </script>

refs

  1. <template>
  2. <div>
  3. // 给子组件上绑定 ref
  4. <Test
  5. ref="son"
  6. />
  7. <Test2/>
  8. </div>
  9. </template>
  10. // 通过 $refs 示例来获取 子组件的属性和方法
  11. console.log( this.$refs.son.datas)
  12. this.$refs.son.getValue()

$children

  1. // 通过 $children 来获取 子组件的属性和方法
  2. this.$children[0].getValue(); // 我是 Test1
  3. this.$children[1].getTest2(); //我是 Test2
  4. console.log(`---------${this.$children[1].datas}`); //我是Test2

4. 子组件 通过 $parent 来获取父组件实例的属性和方法

  1. <script>
  2. export default {
  3. name:'test',
  4. created(){
  5. console.log( this.$parent.obj )
  6. this.$parent.getQuery()
  7. },
  8. }
  9. </script>

5. $attrs$listeners 获取父组件实例属性和方法(组件嵌套情况下使用)

$attrs:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件。当一个组件没有声明任何 props 时,它包含所有父作用域的绑定 (class 和 style 除外)。

$listeners:包含了父作用域中的 (不含 .native 修饰符) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件。它是一个对象,里面包含了作用在这个组件上的所有事件监听器,相当于子组件继承了父组件的事件。

使用场景:多层嵌套组件的情况下使用,可以避免使用Vuex来做数据处理, 使用 v-bind="$attrs" v-on="$listeners" 很方便达到业务数据传递。

父组件

  1. <template>
  2. <div>
  3. <Test3
  4. :status="status"
  5. :title="title"
  6. @getData="getData" />
  7. </div>
  8. </template>
  9. <script>
  10. import Test3 from "../components/Test3.vue";
  11. export default {
  12. name:'person',
  13. data(){
  14. return {
  15. title:'personal 组件',
  16. status: false
  17. }
  18. },
  19. methods:{
  20. getData(){
  21. console.log(this.title)
  22. }
  23. },
  24. components:{
  25. Test3
  26. }
  27. }
  28. </script>

子组件1

  1. <template>
  2. <div>
  3. <h1>Test3 组件</h1>
  4. <br /><br />
  5. // 通过 $attrs(属性,除了【props中定义的属性】) 和 $listeners(方法) 来给嵌套子组件传递父组件的属性和方法
  6. <Test4 v-bind="$attrs" v-on="$listeners"/>
  7. </div>
  8. </template>
  9. <script>
  10. // 引入子子组件
  11. import Test4 from "../components/Test4";
  12. export default {
  13. name: "test3",
  14. props: ["title"],
  15. components: {
  16. Test4,
  17. },
  18. created() {
  19. console.log(this.$attrs); //{status: false}
  20. console.log("-----------");
  21. console.log(this.$listeners); // {getData: ƒ}
  22. },
  23. };
  24. </script>

嵌套子组件

  1. <template>
  2. <div>
  3. <h1>Test4 组件</h1>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name:'test4',
  9. created(){
  10. console.log('-----Test4------')
  11. console.log(this.$attrs) //{status: false}
  12. console.log(this.$listeners) // {getData: ƒ}
  13. }
  14. }
  15. </script>

6. 跨组件之间传值

通过新建一个 js 文件,导入vue , 导出vue 实例;然后通过 给导出的实例 上绑定事件$emit 事件 , 然后再通过 $on 监听触发的事件,这样就可以达到全局组件数据共享。

使用场景:

它可以满足任意场景传递数据, 父子组件传值 , 子父传值 , 兄弟组件之间传值 , 跨级组件之间传值 .

通信数据比较简单时,可以采用这种 方案,项目比较庞大,可以采用 Vuex .

vue .js

  1. /*
  2. * @Description:
  3. * @Author: ZhangXin
  4. * @Date: 2021-01-22 15:48:56
  5. * @LastEditTime: 2021-01-22 15:51:24
  6. * @LastEditors: ZhangXin
  7. */
  8. import Vue from 'vue'
  9. export default new Vue()

组件A

  1. <!--
  2. * @Description:
  3. * @Author: ZhangXin
  4. * @Date: 2021-01-22 14:44:17
  5. * @LastEditTime: 2021-01-22 16:25:33
  6. * @LastEditors: ZhangXin
  7. -->
  8. <template>
  9. <div>
  10. <button @click="changeValue">改变</button>
  11. </div>
  12. </template>
  13. <script>
  14. import zxVue from '../util/newVue.js';
  15. export default {
  16. name:'person',
  17. data(){
  18. return {
  19. title:'personal 组件',
  20. status: false
  21. }
  22. },
  23. methods:{
  24. changeValue(){
  25. // 通过给 vue实例绑定事件
  26. zxVue.$emit("getTitle", this.title)
  27. }
  28. }
  29. }
  30. </script>

组件C

  1. <!--
  2. * @Description:
  3. * @Author: ZhangXin
  4. * @Date: 2021-01-22 15:07:30
  5. * @LastEditTime: 2021-01-22 16:26:38
  6. * @LastEditors: ZhangXin
  7. -->
  8. <template>
  9. <div>
  10. <h1>Test4 组件</h1>
  11. <h1>{
  12. { title }}</h1>
  13. </div>
  14. </template>
  15. <script>
  16. import zxVue from "../util/newVue";
  17. export default {
  18. name: "test4",
  19. data() {
  20. return {
  21. title: "test4",
  22. };
  23. },
  24. mounted(){
  25. // 通过 vue 实例.$on 监听事件名,来接收跨级组件传递过来的值
  26. zxVue.$on("getTitle", (item) => {
  27. this.title = item;
  28. console.log(item)
  29. });
  30. }
  31. };
  32. </script>

7. Vuex

这里就不介绍了,完了单独写一篇文章精讲Vuex

8. provideinject 实现父组件向子孙孙组件传值。(层级不限)

provideinject 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

provide :

  • 是一个对象或返回一个对象的函数
  • 该对象包含可注入其子孙的属性。

inject :

  • 是一个字符串数组 或者是一个对象
  • 用来在子组件或者子孙组件中注入 provide 提供的父组件属性。

使用场景:

provide/inject可以轻松实现跨级访问父组件的数据

  1. # provide
  2. //对象
  3. provide:{
  4. name:'测试'
  5. }
  6. //返回对象的函数
  7. provide(){
  8. return {
  9. name: '测试'
  10. }
  11. }
  12. #inject
  13. inject:['name']

父组件

  1. <!--
  2. * @Description:
  3. * @Author: ZhangXin
  4. * @Date: 2021-01-22 23:24:16
  5. * @LastEditTime: 2021-01-22 23:49:50
  6. * @LastEditors: ZhangXin
  7. -->
  8. <template>
  9. <div>
  10. <h1>我是父组件</h1>
  11. <Son />
  12. </div>
  13. </template>
  14. <script>
  15. import Son from '../components/son/SonOne'
  16. export default {
  17. name:'father',
  18. provide(){
  19. return {
  20. titleFather: '父组件的值'
  21. }
  22. },
  23. components:{
  24. Son
  25. },
  26. data(){
  27. return{
  28. title:'我是父组件 '
  29. }
  30. },
  31. }
  32. </script>

子组件

  1. <template>
  2. <div>
  3. <h1>我是子孙组件</h1>
  4. </div>
  5. </template>
  6. <script>
  7. import SonTwo from '../son/SonTwo'
  8. export default {
  9. name:'sonone',
  10. components:{
  11. SonTwo
  12. },
  13. inject:['titleFather'],
  14. created(){
  15. console.log(`${this.titleFather}-----------SonTwo`)
  16. },
  17. data(){
  18. return{
  19. title:'我是子组件 '
  20. }
  21. },
  22. }
  23. </script>

子孙组件

  1. <template>
  2. <div>
  3. <h1>我是子孙组件</h1>
  4. </div>
  5. </template>
  6. <script>
  7. import SonTwo from '../son/SonTwo'
  8. export default {
  9. name:'sonone',
  10. components:{
  11. SonTwo
  12. },
  13. inject:['titleFather'],
  14. created(){
  15. console.log(`${this.titleFather}-----------SonTwo`)
  16. },
  17. data(){
  18. return{
  19. title:'我是子组件 '
  20. }
  21. },
  22. }
  23. </script>

480e4932249a8cd58912cd0fdf21f18b.gif

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

  1. 正则 / 框架 / 算法等 重温系列(16篇全)

  2. Webpack4 入门(上)|| Webpack4 入门(下)

  3. MobX 入门(上) || MobX 入门(下)

  4. 120+篇原创系列汇总

2fd2fa622a1b40fa667c42af697bb641.gif

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 120+ 篇原创文章

发表评论

表情:
评论列表 (有 0 条评论,310人围观)

还没有评论,来说两句吧...

相关阅读