vue项目实战中常见的数据通信方式

一、父组件传递数据到子组件中(属性传递)

  • 1、父组件

    <template>
      <div>
        <child01 :names="names" v-if="isLoading"/>
      </div>
    </template>
    
    <script>
    import child01 from './child01'
    export default {
      data () {
        return {
          names: [],
          isLoading: false
        }
      },
      methods: {
        getData () {
          setTimeout(() => {
            this.names = ['哈哈', '嘻嘻', '美美']
            this.isLoading = true
          }, 2000)
        }
      },
      mounted () {
        this.getData()
      },
      components: {
        child01
      }
    }
    </script>
  • 2、子组件

    <template>
      <div>
        <ul>
          <li v-for="(item, index) of names" :key="index">{{item}}</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        names: {
          type: Array
        }
      }
    }
    </script>

二、子组件传递值到父组件(方法传递)

  • 1、子组件

    <li v-for="(item, index) of names" :key="index" @click="sendVal(item)">{{item}}</li>
    ...
    methods: {
        sendVal (val) {
          this.$emit('sendVal', val)
        }
    }
    ...
  • 2、父组件

    <child01 :names="names" v-if="isLoading" @sendVal="sendVal"/>
    ...
    methods: {
        sendVal (val) {
          console.log(val)
        }
    },
    ...

三、父组件调用子组件的方法(直接使用ref)[也可以获取子组件的属性]

  • 1、子组件

    methods: {
        sendVal (val) {
            this.$emit('sendVal', val)
        },
        foo () {
            console.log('我是子组件的方法')
        }
    }
  • 2、父组件

    foo () {
      console.log('子组件中的数据===>', this.$refs.child)
      this.$refs.child.foo()
    }

四、子组件调用父组件的方法(属性)

  • 1、子组件

    bar () {
        console.log(this.$parent)
        this.$parent.names.push('张三')
    }

五、子组件同步修改父组件的值(在属性后面加sync)

  • 1、父组件

    <child01 :names="names" v-if="isLoading" @sendVal="sendVal" ref="child" :aa.sync="text"/>
  • 2、子组件

    post () {
      this.$emit('update:aa', '子组件的值')
    }

六、父组件传递给子组件,子组件又传递给孙组件

常见的方法:

  • 1、父传给给子,子传递给孙组件,逐级传递(非常麻烦而且不易于维护的)
  • 2、使用vuex状态机(杀鸡用牛刀,大材小用)
  • 3、使用Vue提供了【inheritAttrs】【attrs】
  • 4、使用provide/inject进行多级组件值传递

步骤

  • 1、定义一个父组件,传递两个参数到子组件和孙组件

    <template>
      <div>
        <child02 :text="text" :count="count"/>
      </div>
    </template>
    
    <script>
    import child02 from './child02'
    export default {
      data () {
        return {
          text: '父组件的值',
          count: 123456
        }
      },
      components: {
        child02
      }
    }
    </script>
    
    <style scoped>
    </style>
  • 2、子组件

    <template>
      <div>
        <h2>第二个组件</h2>
        <div>{{text}}</div>
        <child03 v-bind="$attrs"/>
      </div>
    </template>
    
    <script>
    import child03 from './child03'
    export default {
      props: {
        text: {
          type: String | Number
        }
      },
      // 解决父组件传递过来的值,没被使用的情况下挂载在本组件上(类似自定义属性)
      inheritAttrs: false,
      components: {
        child03
      },
      mounted () {
        console.log(this.$attrs)
      }
    }
    </script>
    
    <style scoped>
    </style>
  • 3、孙组件

    <template>
      <div>
        <h3>我是孙组件</h3>
      </div>
    </template>
    
    <script>
    export default {
      mounted () {
        console.log('我是孙组件', this.$attrs)
      }
    }
    </script>
    
    <style scoped>
    </style>

七、provide/inject多级组件传递值

  • 1、父组件中使用provide(也不需要写属性传递)

    provide: {
        parent: '父组件的值===='
    },
  • 2、在需要使用的子孙组件中使用

    export default {
      inject: ['parent'],
      mounted () {
        console.log(this.parent)
      }
    }

八、provide/inject异步创建数据

  • 1、父组件

    <template>
      <div>
        <child02 :text="text" :count="count" v-if="isLoad"/>
      </div>
    </template>
    
    <script>
    import child02 from './child02'
    export default {
      provide () {
        let parent = {}
        setTimeout(() => {
          Object.defineProperty(parent, 'value', {
            get: () => this.text,
            enumerable: true
          })
          this.isLoad = true
        }, 1000)
        return {
          parent
        }
      },
      data () {
        return {
          text: '父组件的值',
          count: {
            name: 'haa'
          },
          isLoad: false
        }
      },
      mounted () {
      },
      components: {
        child02
      }
    }
    </script>
    
    <style scoped>
    </style>
  • 2、子组件跟之前的一样

九、混入mixins的使用

其实这个功能有些类似于es6中的Object.assign()方法。根据一定的规则合并两个配置,常用于抽取相同的地方

  • 1、单独定义一个文件(自动关闭弹框)

    export const mixin = {
        methods: {
            autoClose () {
                setTimeout(() => {
                  this.$Modal.remove();
                }, 2000);
            }
        }
    }
  • 2、使用

    import {mixin} from './../utils/minx'
    export default {
      mixins: [mixin],
      methods: {
        childClose () {
          // close在本组件中没有定义,其实就是使用了minx里面的
          this.close()
        }
      }
    }

十、非父子组件传递

官方推荐使用bus组件,有两种实现方式

方法一(不需要单独创建一个组件)
  • 1、在入口文件中加入data

    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>',
      data: {
        Bus: new Vue()
      }
    })
  • 2、发送数据的组件

    <button @click="submit">提交</button>
    ...
    methods: {
        submit() {
            // 事件名字自定义,用不同的名字区别事件
            this.$root.Bus.$emit('eventName', 123)
        },
    },
  • 3、接收数据的组件

    ...
    created(){
        this.$root.Bus.$on('eventName', value => {
            this.print(value)
        })
    },
    
    methods: {
        print(value) {
            console.log(value)
        }
    },
    
    // 在组件销毁时别忘了解除事件绑定
    beforeDestroy() {
        this.$root.Bus.$off('eventName')
    },
    ...
方法二(单独创建一个bus.js)
  • 1、单独创建一个bus.js

    import Vue from 'vue'
    export default new Vue;
  • 2、在发送数据的组件中

    <button @click="bus">bus组件</button>
    ...
    import Bus from './bus.js'
    ...
    methods: {
        bus() {
          Bus.$emit('msg', '我要传递给兄弟组件, 你收到了吗')
        }
    },
  • 3、在接收数据的组件中

    import Bus from './bus.js'
    ...
    mounted() {
        Bus.$on('msg', (e) => {
          console.log('我是bar组件', e);
        })
    }

十一、源码下载传送门

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值