美文网首页
组件中常见的通信方式

组件中常见的通信方式

作者: 欢宝吖_ | 来源:发表于2022-11-11 17:05 被阅读0次

    一、父组件向子组件传递

    父组件通过props方式向子组件传递父组件的数据
    props是单向绑定,只能父传子
    props只读,不可对props进行修改,要修改只能将新数据传递给父组件,父组件修改数据后,再传递给子组件

    • 给子组件通过自定义属性绑定父组件需要传递的数据
    • 子组件通过props来接收父组件传递的数据,props是数组
    props1.png props2.png
    • 父组件代码块
    <template>
      <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
        <hello-world :msg="msg" :info="info" ></hello-world>
      </div>
    </template>
    
    <script>
    import HelloWorld from '@/components/HelloWorld.vue'
    export default {
      name: 'HomeView',
      data: function () {
        return {
          msg: '这是父组件的msg',
          info: '这是父组件的info',
        }
      },
      components: {
        HelloWorld
      }
    }
    </script>
    
    
    • 子组件代码块
    <template>
      <div class="hello">
        <h1>{{msg}}</h1>
        <h1>{{info}}</h1>  
      </div>
    </template>
    
    <script>
    export default {
      props: ['msg', 'info'],
      name: 'HelloWorld',
    }
    </script>
    

    二、子组件向父组件传递

    • 注册自定义事件 this.$emit() 第一个参数是自定义事件名,第二个参数是需要传的参数(多个参数就传数组或者对象)
    • v-on 监听子组件上面的自定义事件 如果事件不写小括号,那么methods中的第一个参数就是自定义事件中传递过来的值;如果需要额外传递参数,则需要使用$event来接收自定义事件传的参数
    $emit1.png $emit2.png
    • 子组件代码块
    <template>
      <div class="hello">
        <h1>{{msg}}</h1>
        <h1>{{info}}</h1>
        <input type="button" value="子传父" @click="sendFmsg">
      </div>
    </template>
    
    <script>
    export default {
      props: ['msg', 'info'],
      name: 'HelloWorld',
      data: function () {
        return {
          fmsg: '我是子组件的fmsg'
        }
      },
      methods: {
        sendFmsg () {
          this.$emit('handle-fmsg', this.fmsg)
        }
      }
    }
    </script>
    
    <style scoped lang="less">
    
    </style>
    
    
    • 父组件代码块
    <template>
      <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
        <hello-world :msg="msg" :info="info" v-on:handle-fmsg="getfmsg" ></hello-world>
        <h1>{{fmsg}}</h1>
      </div>
    </template>
    
    <script>
    import HelloWorld from '@/components/HelloWorld.vue'
    
    export default {
      name: 'HomeView',
      data: function () {
        return {
          msg: '这是父组件的msg',
          info: '这是父组件的info',
          fmsg: ''
        }
      },
      methods: {
        getfmsg (val) {
          this.fmsg = val
        }
      },
      components: {
        HelloWorld
      }
    }
    </script>
    
    

    三、provide/inject

    祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题。父组件的所有后代组件都可以通过inject获取父组件通过provide传递的数据。

    provide1.png provide2.png
    • 父组件代码块
    <template>
      <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
        <hello-world></hello-world>
      </div>
    </template>
    
    <script>
    import HelloWorld from '@/components/HelloWorld.vue'
    
    export default {
      name: 'HomeView',
      data: function () {
        return {
          info: '我是父组件的info',
          msg: '我是父组件的msg'
        }
      },
      provide: function () {
        return {
          info: this.info,
          msg: this.msg
        }
      },
      components: {
        HelloWorld
      }
    }
    </script>
    
    • 子组件代码块
    <template>
      <div class="hello">
        <h1>{{info}}</h1>
        <h2>{{msg}}</h2>
        <son-com></son-com>
      </div>
    </template>
    
    <script>
    import sonCom from '@/components/sonCom.vue'
    export default {
      inject: ['info', 'msg'],
      name: 'HelloWorld',
      components: {
        sonCom
      }
    }
    </script>
    
    • 孙组件代码块
    <template>
      <div class="son">
        <h1>{{info}}</h1>
        <h2>{{msg}}</h2>
      </div>
    </template>
    
    <script>
    export default {
      inject: ['info', 'msg'],
    }
    </script>
    

    parent和children

    parent和$children这两种方法是直接获取组件实例,可以直接调组件的方法或者数据

    • 在子组件中打印this.$parent,输出结果是父组件的实例,是个对象,里面有父组件中的数据info,那我们在子组件就可以直接调用
    $parent1.png
    • 在父组件中打印this.$children,输出结果是子组件的实例,是个数组,里面有子组件中的数据msg,那我们在父组件就可以直接调用
    $children1.png pc1.png pc2.png
    • 父组件代码块
    <template>
      <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
        <hello-world></hello-world>
        <h1>{{msg}}</h1>
      </div>
    </template>
    
    <script>
    import HelloWorld from '@/components/HelloWorld.vue'
    
    export default {
      name: 'HomeView',
      data: function () {
        return {
          info: '我是父组件的info',
          msg: ''
        }
      },
      mounted () {
        console.log(this.$children)
        this.msg = this.$children[0].msg
      },
      components: {
        HelloWorld
      }
    }
    </script>
    
    
    • 子组件代码块
    <template>
      <div class="hello">
        <h2>{{info}}</h2>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      data: function () {
        return {
          info: '',
          msg: '我是子组件的msg'
        }
      },
      mounted () {
        console.log(this.$parent)
        this.info = this.$parent.info
      }
    }
    </script>
    
    <style scoped lang="less">
    
    </style>
    
    

    五、vuex

    • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式, 采用集中式存储管理应用的所有组件的状态,解决多组件数据通信

    vuex的五个属性

    state: 定义全局都可使用的数据

    mutations : 使用mutations里面的方法来修改state里面的数据(类似于methods)

    getters: 类似于computed(计算属性,对现有的状态进行计算得到新的数据),对state里面的数据进行某些处理

    actions: 可以使用commit触发mutations里面的方法,也可以发起异步请求,进行异步操作

    modules: 对各个模块进行拆分,让每个数据都有与之相关独立的mutations、getters和actions

    在项目中配置vuex

    • 在创建项目进行配置的时候,将vuex选上,就很方便,可以省去很多操作
    vuex1.png

    代码


    vuex2.png

    效果


    vuex3.png

    vuex代码块

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        msg: 'vue里的全局数据',
        num: 1
      },
      // 相当于对state里的数据进行运算得到的数据,类似计算属性对data数据的处理
      getters: {
        numDb (state) {
          return state.num * 2
        }
      },
      // 定义修改state里面的数据的方法
      mutations: {
        updateMsg (state) {
          state.msg = '修改之后的msg数据'
        },
        updateNum (state, info) {
          state.num += info
        }
      },
      // actions中的方法触发mutations中的方法从而改变state里的数据。也可以在这里执行异步操作
      actions: {
        actionsUpdateNum (c, val) {
          c.commit('updateNum', val)
        }
      },
      modules: {
      }
    })
    
    

    子组件代码块

    <template>
      <div class="about">
        <h1>This is an about page</h1>
        <h2>state的msg:{{$store.state.msg}}</h2>
        <button @click="updateMsg">修改msg</button>
        <h2>state的num:{{$store.state.num}}</h2>
        <button @click="updateNum(5)">+5</button>
        <button @click="updateNum(10)">+10</button>
        <h2>getters处理之后的num:{{$store.getters.numDb}}</h2>
        <button @click="actionsUpdateNum(1)">actions修改</button>
      </div>
    </template>
    
    <script>
    import store from '@/store/index'
    export default {
      store,
      methods: {
        updateMsg () {
          // 触发vuex的mutations中的方法修改msg
          this.$store.commit('updateMsg')
        },
        // 组件methods通过调用vuex实例的commit方法触发vuex中mutations方法
        updateNum (info) {
          this.$store.commit('updateNum', info)
        },
        // 组件methods通过调用vuex实例的dispatch方法触发vuex中actions方法
        actionsUpdateNum (val) {
          this.$store.dispatch('actionsUpdateNum', val)
        }
      }
    }
    </script>
    
    

    以上几种是比较常见的方法,记住上面的方法,可以应对大部分组件的通信,还有其他方法的也可以一起分享!

    相关文章

      网友评论

          本文标题:组件中常见的通信方式

          本文链接:https://www.haomeiwen.com/subject/boafxdtx.html