vue组件通信

本文深入探讨Vue.js中父子组件、非父子组件间的通信机制,包括数据传递、事件触发、状态共享等核心概念,以及非常规通信方案的讨论。
  • 父子组件通信

    • data选项为什么是一个函数?

      组件是一个聚合体,也是一个整体,他需要一个独立的作用空间

    • 为什么data函数需要返回一个返回值,该返回值时对象而不是数组?

    • 过程

      • 父组件将自己的数据同 v-bind 绑定在 子组件身上

         <div id="app">
            <Father></Father>
          </div>
          
          <template id="father">
            <div>
              <h3> 这里是father </h3>
              <Son :money = "money"></Son>
            </div>
          </template>
        
          <template id="son">
            <div>
              <h3> 这里是son </h3>
              <p> 我收到了父亲给的 {{ money + 100 }} </p>
            </div>
          </template>
        
        
        Vue.component('Father',{
            template: '#father',
            data () {
              return {
                money: 3000
              }
            }
          })
        
      • 子组件通过 props属性接收

          Vue.component('Son',{
            template: '#son',
            // props: ['money']
            // 数据验证
            // props: {
            //   'money': Number 
            // }
            props: {
              'money': {
                validator ( val ) { // 验证函数  如果没有通过 验证则会报错,但是并不不会影响程序的继续执行。
                  return val > 2000
                }
              }
            }
          })
        
    • props需要进行数据验证

      • 怎么做数据验证

        • 验证类型

          props: {
                'money': Number 
               }
          
        • 验证函数

           props: {
                'money': {
                  validator ( val ) { // 验证函数  如果没有通过 验证则会报错,但是并不不会影响程序的继续执行。
                    return val > 2000
                  }
                }
          
      • 第三方验证

        • (TS)
        • 插件:vue-validator
  • 子父组件通信

    • 数据从子给到父

    • 通过自定义事件的触发

      • 事件的发布

        通过网元素身上绑定事件来发布

      • 事件的订阅

        通过this.$emit

      <div id="app">
          <Father></Father>
      </div>
        <template id="father">
          <div>
            <h3> 这里是father </h3>
            <p> 我现在有 {{ gk }} </p>
            <Son @give = "fn"></Son>
          </div>
        </template>
      
        <template id="son">
          <div>
            <h3> 这里是son </h3>
            <button @click = "giveHongbao"> 给父亲红包 </button>
          </div>
        </template>
      </body>
      <script>
         Vue.component('Father',{
          template: '#father',
          data ( ) {
            return {
              gk: 0
            }
          },
          methods: {
            fn ( val ) {
              this.gk = val 
            }
          }
        })
      
        Vue.component('Son',{
          template: '#son',
          data () {
            return {
              money: 5000
            }
          },
          methods: {
            giveHongbao () {
              this.$emit('give',this.money)
            }
          }
        })
        new Vue({
          el: '#app'
        })
      </script>
      
  • 非父子组件通信

    • 兄弟元素的加入

      在父组件的son中通过ref组件就能够获得所要绑定的组件及属性

      “女儿通过”kick () {this.$emit(‘fn’)}来触发father中的fn函数

      father的fn函数即可调用son的方法

      [外链图片转存失败(img-8DmI8Vfk-1566779335374)(F:\。千锋前端\Vue.js\vue笔记\img\img\非父子组件通信-ref_看图王.png)]

      <body>
        <div id="app">
          <Father></Father>
        </div>
      </body>
      
      <template id="father">
        <div>
          <h3> 这里是父组件 </h3>
          <Girl @fn = "fn"></Girl>
          <Son ref = "son"></Son>
        </div>
      </template>
      
      <template id="son">
        <div>
          <h3> 这里是son组件 </h3>
          <p v-show = "flag"> o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o </p>
        </div>
      </template>
      
      <template id="girl">
        <div>
          <h3> 这里是girl组件 </h3>
          <button @click = "kick"> 揍 </button>
        </div>
      </template>
      
      
      <script>
        Vue.component('Father',{
          template: '#father',
          methods: {
            fn () {
              this.$refs.son.changeFlag()
            }
          }
        })
      
        Vue.component('Son',{
          template: '#son',
          data () {
            return {
              flag: false
            }
          },
          methods: {
            changeFlag () {
              this.flag = !this.flag 
            }
          }
        })
      
        Vue.component('Girl',{
          template: '#girl',
          methods: {
            kick () {
              this.$emit('fn')
            }
          }
        })
      
        new Vue({
          el: '#app'
        })
      </script>
      
    • 自己的数据自己更改,别人只能间接的去触发自己的方法

  • 多组件状态共享(vuex)

  • 非常规通信方案

    • 兵哥建议: 如果标准方案可以实现,就不要用非常规手段

      1. 可以实现子父通信
      • 父组件通过 v-bind 绑定一个方法给子组件
      • 子组件通过 props选项接收这个方法,然后直接调用
      1. 父组件 通过 v-bind 绑定 一个对象类型数据 给子组件
      2. 子组件直接使用,如果更改这个数据,那么父组件数据也更改了
        • 原因: 同一个地址
        • 非常规在哪里?
          • 违背了单向数据流
在面试中回答 Vue 组件通信相关问题,可从组件通信背景、常见方式、最佳实践、常见问题等方面阐述,以下是详细要点及示例: ### 组件通信背景 Vue 组件通信在实际项目中非常重要,是开发者面试中的高频考点。掌握好组件通信技巧,能提升代码的可维护性和应用性能 [^1][^3]。 ### 常见通信方式 - **Props 和 Emit**:Props 用于父组件向子组件传递数据,Emit 用于子组件触发父组件的自定义事件。示例代码如下: ```vue <!-- 父组件 --> <template> <div> <child-component :message="parentMessage" @childEvent="handleChildEvent"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent' }; }, methods: { handleChildEvent(data) { console.log('Received data from child:', data); } } }; </script> <!-- 子组件 --> <template> <div> <p>{{ message }}</p> <button @click="sendDataToParent">Send data to parent</button> </div> </template> <script> export default { props: ['message'], methods: { sendDataToParent() { this.$emit('childEvent', 'Hello from child'); } } }; </script> ``` - **Provide/Inject**:适用于跨层级组件通信,父组件通过 provide 提供数据,后代组件通过 inject 注入数据。示例代码如下: ```vue <!-- 祖先组件 --> <template> <div> <descendant-component></descendant-component> </div> </template> <script> import DescendantComponent from './DescendantComponent.vue'; export default { components: { DescendantComponent }, provide() { return { sharedData: 'Shared data from ancestor' }; } }; </script> <!-- 后代组件 --> <template> <div> <p>{{ sharedData }}</p> </div> </template> <script> export default { inject: ['sharedData'] }; </script> ``` - **Vuex/Pinia 状态管理**:用于管理应用的全局状态,多个组件可以共享和修改这些状态。以 Vuex 为例,示例代码如下: ```javascript // store/index.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { incrementAsync({ commit }) { setTimeout(() => { commit('increment'); }, 1000); } }, getters: { doubleCount(state) { return state.count * 2; } } }); // 组件中使用 <template> <div> <p>Count: {{ $store.state.count }}</p> <p>Double Count: {{ $store.getters.doubleCount }}</p> <button @click="$store.commit('increment')">Increment</button> <button @click="$store.dispatch('incrementAsync')">Increment Async</button> </div> </template> <script> export default { // ... }; </script> ``` - **EventBus(不推荐)**:创建一个全局的事件总线对象,组件可以通过它发布和订阅事件。示例代码如下: ```javascript // event-bus.js import Vue from 'vue'; export const eventBus = new Vue(); // 发送事件的组件 import { eventBus } from './event-bus.js'; export default { methods: { sendEvent() { eventBus.$emit('customEvent', 'Event data'); } } }; // 接收事件的组件 import { eventBus } from './event-bus.js'; export default { created() { eventBus.$on('customEvent', (data) => { console.log('Received event data:', data); }); } }; ``` ### 最佳实践 - **父子组件通信**:优先使用 Props 和 Emit 进行数据传递和事件触发 [^1][^3]。 - **跨组件通信**:对于跨层级组件,可使用 Provide/Inject;对于多个组件共享状态,使用 Vuex 或 Pinia [^1][^3]。 ### 常见问题 - **Props 单向数据流**:Props 是单向绑定的,子组件不能直接修改父组件传递的 Props 值,应通过 Emit 触发父组件的事件来修改 [^1]。 - **组件解耦**:使用状态管理库(如 Vuex、Pinia)可以实现组件之间的解耦,提高代码的可维护性 [^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值