vue组件通信

本文详细讲解了Vue中Props传递值、$refs调用子组件方法、子组件调用父组件以及使用$parent/$children、$attrs/$listeners和Vuex进行组件间通信的方法。还介绍了$emit和$on的事件派发机制,以及provide/inject在多层组件间的传递。
摘要由CSDN通过智能技术生成

Props :父组件传递值给子组件,子组件接收值,传递undefined/null无效

$refs:父组件调用子组件方法

子组件调用父组件方法:

  1. $parent / $children:访问父 / 子实例
  2. this.$emit('方法',‘参数’)
  3. this.方法 需要确保父组件有此方法,可以进行判断

隔代组件通信

  1. $attrs/$listeners
  2. provide / inject

适用于 父子、隔代、兄弟组件通信 EventBus ($emit / $on)

都适用Vuex

事件派发Vue.prototype.$xxxx = xxxx

Props使用方式

  1. 子组件接收父组件参数 当传入undefined 以及null 则不会显示
  2. props 可自定义类型 如传递的值与类型不符合则会报错
  3. 支持类型:String, Number, Boolean, Function, Object, Array, Symbol

父组件

<template>
  <div id="elementA">
    <index2
      ref="index2"
      :value="value"
      :list="list"
      :listValue="listValue"
      :listNumber="listNumber"
    ></index2>
  </div>
</template>
<script>
import index2 from "./index2";
export default {
  name: "elementA",
  components: { index2 },
  data() {
    return {
      value: "undefined", //无效
      list: "",
      listValue: "数据", //有效
      listNumber: 10, //有效
    };
  },
};
</script>

子组件 第一种获取方式

<template>
  <div id="elementB">
    {{ value }}
    {{ list }}
    {{ listValue }}
    {{ listNumber }}
  </div>
</template>
<script>
export default {
  //默认接收params
  //props: ["value", "list", "listValue"],
  //设置类型与默认值
  props: {
    value: {
      type: [String, Number], //多种类型
      default: "默认值", //基础类型
    },
    list: {
      type: String,
      required: true, //必填项
    },
    //函数返回对象
    listValue: {
      type: String,
      default: () => {
        return { message: "测试" }; //返回对象
      },
    },
    // 自定义验证函数
    listNumber: {
      validator: function (value) {
        return value < 100;
      },
    },
  },
  mounted() {
    console.log(this.value, this.list, this.listValue); //undefined 数据 10
  },
};
</script>

父组件调用子组件方法

父组件

<template>
  <div id="elementA">
    <button @click="a()">父组件调用子组件方法</button>
    <elementB ref="elementB"></elementB>
  </div>
</template>
<script>
import elementB from "./elementB";
export default {
  name: "elementA",
  components: { elementB },

  methods: {
    a() {
      this.$refs.elementB.a("父组件调用子组件方法");
    }
  }
};
</script>

子组件

<template>
  <div id="elementB">
  </div>
</template>
<script>
export default {
  name: "elementB",
  methods: {
    a(val) {
      alert(val);
    },
  }
};
</script>

子组件调用父组件方法

  • this.$parent
  • this.$emit
  • this
  • this.$children

父组件

<template>
  <div id="elementA">
    <button @click="a()">父组件调用子组件方法</button>
    <elementB  @A="A" :B="B" ></elementB>
  </div>
</template>
<script>
import elementB from "./elementB";
export default {
  name: "elementA",
  components: { elementB },
  methods: {
    a(){
        //获取自组建的数据 是一个数组
        conosle.log(this.$children[0].test)
    },
    b() {
      alert("子组件调用父组件方法1");
    },
    A() {
      alert("子组件调用父组件方法2");
    },
    B() {
      alert("子组件调用父组件方法3");
    }
  }
};
</script>

子组件

<template>
  <div id="elementB">
    <button @click="b">子组件调用父组件方法1</button>
    <button @click="B">子组件调用父组件方法2</button>
    <button @click="C">子组件调用父组件方法3</button>
  </div>
</template>
<script>
export default {
  name: "elementB",
  data(){
      return{
          test:'test'
      }
  }
  methods: {
    b() {
      this.$parent.b();
    },
    B() {
      this.$emit("A");
    },
    C() {
      if (this.B) {
        this.B();
      }
    }
  }
};
</script>

provide与inject多层组件传递,(官网不建议修改)

<template>
  <div id="test">
    <provideInject>
    </provideInject>
  </div>
</template>
<script>
import provideInject from "./provideInject/provideInject";
export default {
  //第一种
  //单独传数据
  // provide: {
  //   abcd: "abc"
  // },
 
  //第二种
  //传一个实例
  provide() {
    return {
      abcd: this
    };
  },
  components: { provideInject },//子组件
};
</script>

子组件:

<template>
  <div>
  </div>
</template>
<script>
export default {
  inject: ["abcd"],
  mounted() {
    console.log(this.abcd); //第一种  输出abc
    console.log(this.abcd); //第一二中 输出实例
  },
};
</script>

 总线模式:创建监听 事件派发回调:

Vue.prototype.$xxxx = xxxx

卡槽:

  • 匿名插槽    
  • 具名插槽  
  • 作用于插槽

父组件:

<template>
  <div id="test">
      <provideInject>
      <!-- 默认 -->
      <template v-slot:default></template>
      <template v-slot:content></template>
      <!-- slotName自定义名称 -->
      <template v-slot:content2="slotName">{{slotName.abcde}}</template>
    </provideInject>
  </div>
</template>

<script>
import { test, test2 } from "@/api";
import { mapState, mapActions } from "vuex";
import provideInject from "./provideInject/provideInject";
export default {
  components: { provideInject },
};
</script>

自组件:

<template>
  <div>
    <!-- 匿名插槽 -->
    <div>
      <slot>123</slot>
    </div>
    <!-- 具名插槽 -->
    <div>
      <slot name="content">456</slot>
    </div>
    <!-- 作用于插槽 -->
    <div>
      <slot name="content2" abcde="abcde"></slot>
    </div>
  </div>
</template>

mixins

新建个mixins文件 对应分别建立usemixins.vue 与index.js文件

index.js

export default {
    methods: {
        textMixins() {
            alert(2)
        }
    }
}

usemixins.vue

<template>
  <div>
    <button @click="aa()">使用mixins</button>
  </div>
</template>
<script>
import launch from "./index";
export default {
  mixins: [launch],
  methods: {
    aa() {
      this.textMixins();
    }
  }
};
</script>>

$attrs/$listeners

  • $attrs接收属性值,如果用props接收过则不会先输出,class,style不会输出(接收v-bind的值)
  • $listeners接受事件方法 基于@xxx=xxx  

父组件

<template>
  <div class="one">
    <one :n="1" :m="2" class="aa" text="12" :hander="hander" @click="hander2">arrts/Listnen</one>
  </div>
</template>

<script>
import one from "./1";
export default {
  components: { one },
  methods: {
    hander() {},
    hander2() {}
  }
};
</script>

子组件

<template>
  <div class="one">1</div>
</template>
<script>
export default {
  created() {
    console.log(this.$attrs, this.$listeners);
    //$attrs接收属性值,如果用props接收过则不会先输出,class,style不会输出(接收v-bind的值)
    //$listeners接受事件方法 基于@xxx=xxx
    //$attrs: {m: 2, text: "12", hander: ƒ}   $listeners:{click: ƒ}
  },
};
</script>

$on $emit

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

监听自定义事件

<template>
  <div>
    <el-button type="primary" @click="aa">点击1</el-button>
  </div>
</template>
<script>
export default {
  methods: {
    aa() {
      this.$emit("aaa", "点击事件!");
    }
  },
  mounted() {
    this.$on("aaa", val => {
      console.log(val);
    });
  }
};
</script>

多个监听

<template>
  <div>
    <el-button type="primary" @click="a">点击2</el-button>
    <el-button type="primary" @click="b">点击3</el-button>
  </div>
</template>

<script>
export default {
  methods: {
    a() {
      this.$emit("aa", "点击事件!");
    },
    b() {
      this.$emit("bb", ["点击2", "点击3"]);
    }
  },
  mounted() {
    this.$on("aa", val => {
      console.log(val);
    });
    this.$on("bb", (...val) => {
      console.log(val);
    });
    this.$on(["aa", "bb"], () => {
      console.log(666);
    });
  }
};
</script>

跨组件通信new Vue

实现功能  父组件 中的left 页面按钮点击后改变右边组建内容

父组件

<template>
  <div>
    <left />
    <right />
  </div>
</template>
<script>
import left from "./left";
import right from "./right";
export default {
  components: {
    left,
    right
  }
};
</script>

utils文件

import Vue from 'vue'
let utils = new Vue()
export default utils

左边组件

<template>
  <section>
    <el-button type="primary" @click="aa">点击</el-button>
  </section>
</template>
<script>
import utils from "./utils";
export default {
  methods: {
    aa() {
      utils.$emit("aaa", "点击事件!");
    }
  }
};
</script>

右边组件

<template>
  <section>{{ name }}</section>
</template>
<script>
import utils from "./utils";
export default {
  data() {
    return {
      name: "aa默认值"
    };
  },
  mounted() {
    utils.$on("aaa", info => {
      this.name = info;
    });
  }
};
</script>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值