Vue 组件通信

155 阅读2分钟

一、组件的 props

props 是组件的自定义属性,组件的使用者可以通过props 把数据传递到子组件内部,供子组件内部进行使用。

props 的作用:父组件通过 props向子组件传递要展示的数据。

子组件接受父组件传递过来的值

<template>
  <div>
    <p>名言: {{ witticism }}</p>
    <p>作者:{{ author }}</p>
  </div>
</template>

<script>
export default {
  name: "MyProp",
  
  props: ["witticism", "author"], //通过定义props属性 接受传递过来的值
};
</script>

<style lang="less" scoped></style>

父组件传值

 //App.vue 
 <template>
  <div>
    <h1>App 根组件</h1>
    <hr />
    
    //3.使用组件
    <my-props
      :witticism="info.witticism"  //动态绑定  传入一个静态值
      :author="'source' + info.author" //动态绑定  传入一个动态赋值
    ></my-props>
  </div>
</template>

 <script>
 //1.引入组件 
 import MyProps from "./components/props/props.vue";

 export default {
   name: "App",
   data() {
     return {
       info: {
         witticism: "山前山后各有哀愁,有风无风都不自由",
         author: "网络",
       },
     };
   },
   components: {
     MyProps, //2.注册组件
   },
 };
 </script>

在封装vue组件时,可以把动态的数据项声明为 props 自定义属性。

props 类型: 如果希望每个 prop 都有指定的值类型。可以以对象形式列出 props

props: { 
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object, 
callback: Function,
contactsPromise: Promise // or any other constructor }

可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。

propC: 
{ 
   type: String, 
   required: true 
},

二、自定义事件

在封装组件时,为了让组件的使用者可以监听到组件内状态的变化,此时需要用到组件的自定义事件。

  1. 声明自定义事件
  2. 触发自定义事件
  3. 监听自定义事件

自定义组件封装的自定义事件,必须事先在 emits 节点中声明,不同于组件和 props,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。

这里借用两张Pink老师的图:

父向子:

fgoz.png

上代码

   //子组件
<template>
  <div>
    <p>count的值是:{{ number }}</p>
  </div>
</template>

<script>
export default {
  name: "MyCount",
  props: ["number"], //通过props 接受父组件传过来的数据 number=父组件的count
};
</script>

 <style lang="less" scoped></style>

父组件

App.vue
<template>
  <div>
    <h1>App 根组件----------{{ count }}</h1>
    <button @click="count += 1">+1</button>
    <hr />

    <!-- 通过v-bind绑定 实现父向子传递数据 -->
    <my-count v-bind:number="count"></my-count>
  </div>
</template>

<script>
import MyCount from "./Count.vue";
export default {
  name: "MyApp",
  data() {
    return {
      count: 0,
    };
  },
  components: {
    MyCount,
  },
};
</script>

 <style lang="less" scoped></style>
 

子向父

zgof.png 在组件上使用v-model指令, 组件内外数据同步更新

 <template>
  <div>
    <p>count的值是:{{ number }}</p>
    <button @click="add">+1</button>
  </div>
 </template>

<script>
export default {
  name: "MyCount",
  props: ["number"], //通过props 接受父组件传过来的数据
  emits: ["update:number"], //自定义事件名称 
  methods: {
    add(e) {
    //触发自定义事件
      this.$emit("update:number", this.number + 1);
      conslog.log('自定义事件被触发了---触发的值是:', e);
    },
  },
};
</script>

<style lang="less" scoped></style>

在 emits 节点下声明的自定义事件,可以通过this.$emit('自定义事件的名称')方法进行触发,在调用this.$emit()方法触发自定义事件时,可以通过第2个参数为自定义事件传参

父组件

 //App.vue
 <template>
  <div>
    <h1>App 根组件----------{{ count }}</h1>
    <button @click="count += 1">+1</button>
    <hr />

    <!-- 通过v-model绑定 实现双向传递数据  -->
    <my-count v-model:number="count"></my-count>
  </div>
</template>

<script>
import MyCount from "./Count.vue";
export default {
  name: "MyApp",
  data() {
    return {
      count: 0,
    };
  },
  components: {
    MyCount,
  },
};
</script>
 <style lang="less" scoped></style>

三、将原生事件绑定到组件

想要在一个组件的根元素上直接监听一个原生事件。(例如自己封装了一个button按钮样式,在父组件中被应用,当按钮触发时需要监听button的原生事件,但实际过程中监听的是当前环境下的事件,会默认为该事件是父组件下面的)。

解决,有三种方法

  • 使用native修饰符
  • 使用$emit分发事件
  • 使用$listeners 官网不易理解 看下这里

将原生事件绑定到组件

四、.sync 修饰符

sync 修饰符可以实现子组件与父组件的双向绑定,并且可以实现子组件同步修改父组件的值。 之所以称为修饰符,其实它是一个语法糖,优化简化了代码的复杂性。

sync修饰符看这里