阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Vue.js 组件通信

      Vue 组件间通信方式

      快速原型开发

      可以快速识别。vue 文件封装组件插件等功能

      npm install @vue/cli -g
      npm install -g @vue/cli-service-global
      vue serve App.vue
      

      一 Props 传递数据 和 $emit 触发

      components
         ├── Grandson1.vue // 孙子1
         ├── Grandson2.vue // 孙子2
         ├── Parent.vue   // 父亲
         ├── Son1.vue     // 儿子1
         └── Son2.vue     // 儿子2
      

      在父组件Parent.vue中使用儿子组件;

      下面是普通用法

      父组件如下:

      <template>
        <div>
          父组件:{{mny}}
          <Son1 :mny="mny" @input="change"></Son1>
        </div>
      </template>
      <script>
      import Son1 from "./Son1";
      export default {
        data() {
          return { mny: 100 };
        },
        components: {
          Son1
        },
        methods: {
          change(mny) {
            console.log("App change");
            this.mny = mny;
          }
        }
      };
      </script>
      

      子组件如下: 子组件触发父组件方法,通过回调的方式修改的内容传递给父组件

      <template>
        <div>
          <h1>Hello, Son1!{{mny}}</h1>
          <button @click="$emit('input',200)">变</button>
        </div>
      </template>
      
      <script>
      export default {
        props: {
          mny: {
            type: Number
          }
        }
      };
      </script>
      

      二 $emit 触发

      下面是同步父子组件的数据,语法糖的写法;

      一个是.sync, 一个是v-model,这两种写法只需要提供值即可;

      子模块可以使用'update:xxx' 的语法或者 "$emit('input',200)"这种用法;

      .sync 写法

      这种写法,

      父组件用法:提供值即可,不需要有处理的方法;使用<Son1 :mny.sync="mny"></Son1>

      子组件用法:<button @click="$emit('update:mny',200)">变</button> 使用 'update:mny' 的语法;


      父组件

      <template>
        <div>
          父组件:{{mny}}
          <!-- 1.普通传值 -->
          <!-- <Son1 :mny="mny" @input="change"></Son1> -->
      
          <!-- 2.sync -->
          <Son1 :mny.sync="mny"></Son1>
        </div>
      </template>
      <script>
      import Son1 from "./Son1";
      export default {
        data() {
          return { mny: 100 };
        },
        components: {
          Son1
        }
      };
      </script>
      

      子组件

      <template>
        <div>
          <h1>Hello, Son1!{{mny}}</h1>
          <!-- 1.普通传值 -->
          <!-- <button @click="$emit('input',200)">变</button> -->
      
          <!-- 2.sync -->
          <button @click="$emit('update:mny',200)">变</button>
        </div>
      </template>
      
      <script>
      export default {
        props: {
          mny: {
            type: Number
          }
        }
      };
      </script>
      

      v-model

      父组件:提供值即可,不需要有处理的方法;使用<Son1 v-model="mny"></Son1>

      子组件:父级传的值只能通过固定的value来接受,触发只能触发input事件,<button @click="$emit('input',200)">更改{{value}}</button>

      <template>
        <div>
          父组件:{{mny}}
          <!-- 1.普通传值 -->
          <!-- <Son1 :mny="mny" @input="change"></Son1> -->
      
          <!-- 2.sync -->
          <!-- <Son1 :mny.sync="mny"></Son1> -->
      
          <!-- 3.v-model -->
          <Son1 v-model="mny"></Son1>
        </div>
      </template>
      <script>
      import Son1 from "./Son1";
      export default {
        data() {
          return { mny: 100 };
        },
        components: {
          Son1
        }
      };
      </script>
      
      <template>
        <div>
          <h1>Hello, Son1:{{value}}</h1>
          <!-- 1.普通传值 -->
          <!-- <button @click="$emit('input',200)">变</button> -->
      
          <!-- 2.sync -->
          <!-- <button @click="$emit('update:mny',200)">变</button> -->
      
          <!-- 3.v-model -->
          <button @click="$emit('input',200)">更改{{value}}</button>
        </div>
      </template>
      <script>
      export default {
        props: {
          // mny: {
          //   type: Number
          // }
          value: {
            // 3.v-model 接收到的属性名只能叫value
            type: Number
          }
        }
      };
      </script>
      

      三。$parent、$children

      父模块 引用 子模块子模块 引用 孙模块…..;

      这种情况孙模块可以通过$parent来触发父模块

      <!-- 子模块引用孙模块 -->
      <Grandson1 :value="value"></Grandson1>
      
      <!-- 孙模块 -->
      <template>
          <div>
              <h1>Hello, Grandson1==== {{value}}</h1>
              <button @click="$parent.$emit('input',200)">更改</button>
          </div>
      </template>
      
      <script>
          export default {
              props: {
                  value: {
                      type: Number
                  }
              }
          };
      </script>
      

      如果层级很深那么就会出现 $parent.$parent….. 我们可以封装一个 $dispatch 方法向上进行派发 既然能向上派发那同样可以向下进行派发

      $dispatch

      自定义dispatch, 向上派发

      Vue.prototype.$dispatch = function $dispatch(eventName, data) {
        let parent = this.$parent;
        while (parent) {
          parent.$emit(eventName, data);
          parent = parent.$parent;
        }
      };
      

      $broadcast

      自定义broadcast, 向下进行派发

      Vue.prototype.$broadcast = function $broadcast(eventName, data) {
        const broadcast = function () {
          this.$children.forEach((child) => {
            child.$emit(eventName, data);
            if (child.$children) {
              $broadcast.call(child, eventName, data);
            }
          });
        };
        broadcast.call(this, eventName, data);
      };
      

      四。$attrs、$listeners

      当批量拿属性和方法的时候(比如子组件批量向下传从父级接受的属性 / 方法),可以使用 $attrs$listeners来拿

      $attrs

      $attrs批量向下传入属性

      $listeners批量向下传入方法

      <Son2 name="anbang" age="29" @click="()=>{this.mny=500}"></Son2>
      
      <!-- son2 -->
      <template>
        <div>
          <h1>Hello {{$attrs.name}}, Son2 {{$attrs}}</h1>
          <Grandson2 v-bind="$attrs" v-on="$listeners"></Grandson2>
        </div>
      </template>
      <script>
      import Grandson2 from "./Grandson2";
      export default {
        components: {
          Grandson2
        }
      };
      </script>
      
      <!-- Grandson2 -->
      <template>
        <div>
          <h2>Hello, Grandson2{{$attrs}}</h2>
          <button @click="$listeners.click()">更改</button>
        </div>
      </template>
      

      五。Provide & Inject

      父级模块暴露自己,然后在子模块注入父级数据

      注意:父级模块暴露自己,只能子孙模块注入;非子孙模块不用侏儒

      Provide 在父级中暴露数据 Inject : 在任意子组件中可以注入父级数据

      <!-- parent 模块暴露 -->
      provide() {
          return {
              parentMsg: "父亲 Parent123"
          };
      }
      
      <!-- son1 模块暴露 -->
        provide() {
          return {
            sonMsg: "son1Msg 信息"
          };
        }
      
        <!-- Grandson1模块引用 -->
        inject: ["parentMsg", "sonMsg"]
      
      inject: ["parentMsg"] // 会将数据挂载在当前实例上
      

      六。Ref 使用

      获取组件实例

      <Grandson2 v-bind="$attrs" v-on="$listeners" ref="anbang"></Grandson2>
      mounted() { // 获取组件定义的属性
        console.log(this.$refs.anbang.name);
      }
      

      七。EventBus

      EventBus 又称为事件总线。在 Vue 中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的灾难,因此才需要更完善的 Vuex 作为状态管理中心,将通知的概念上升到共享状态层次。

      用于跨组件通知 不复杂的项目可以使用这种方式,跨组件通信复杂的就用 Vuex 吧

      Vue.prototype.$bus = new Vue();
      

      Son2 组件和 Grandson1 相互通信

      <!-- Son2 -->
       mounted() {
        this.$bus.$on("my", data => {
         console.log(data);
        });
       },
      
      <!-- Grandson1 -->
      mounted() {
        this.$nextTick(() => {
         this.$bus.$emit("my", "我是Grandson1");
        });
       },
      

      八。Vuex 通信

      https://www.fullstackjavascript.cn/vuex.png

      目录
      目录