zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

Vue父子组件的通信

2023-04-18 16:08:22 时间

父子组件通信方式

一 父组件向子组件通过props传递数据

在组件中,使用选项props来声明需要从父级接收到的数据。 props的值有两种方式: 方式一:字符串数组,数组中的字符串就是传递时的名称。 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

Prop 是你可以在组件上注册的一些自定义 attribute。 当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。

1. props值为数组时候

为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop列表中:

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问data中的值一样。

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来,在这里我们直接用k-v对显示了值,而没有进行v-bind的动态绑定(下面有介绍):

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

然而在一个典型的应用中,你可能在 data 里有一个博文的数组:

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

并想要为每篇博文渲染一个组件:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>

如上所示,你会发现我们可以使用 v-bind 来动态传递 prop。这在我们一开始不清楚要渲染的具体内容,比如从一个 API 获取博文列表的时候,是非常有用的。

2. props值为对象时候

通常我们希望每个 prop 都有指定的值类型。这时,我们可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型

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

3. 关于props值为对象时候,我们可以对传入的数据做校验或者说验证

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。

3.1.在props中我们可以传一个值做一个对象元素传入,对其做三个限定.如下如代码中的name
  • type 约定该元素类型
  • default 约定默认值(如果父组件不传入值的话将直接使用默认值)
  • required 约定是否要求必须传入(如果要求了父组件没有传入则会报错)
props: {
    title:String,
       propB: [String, Number],
    name:{
            type:String,
            default:"zyh",
            required:true
            }
        }
3.2 我们可以对传入的值约定多个可能类型

propB: [String, Number]

3.如果我们要求传入的数据为对象或者数组,那么默认值需要用工厂函数获取

 // 带有默认值的对象
  propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    }

二 子传父---通过监听子组件事件传递数据和信号给父组件

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。 举个例子,如果触发一个 camelCase 名字为的事件:this.$emit('myEvent') 则监听这个名字的 kebab-case 版本是不会有任何效果的: <my-component v-on:my-event="doSomething"></my-component> 不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或 property 名,所以就没有理由使用 camelCase 或 PascalCase 了。

并且v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent将会变成 v-on:myevent——导致 myEvent不可能被监听到。

因此,Vue官方推荐始终使用 kebab-case 的事件名。

自定义事件的流程:
  • 在子组件中,通过$emit来触发事件。
  • 在父组件中,通过v-on来监听子组件事件。

一个传递加减信号的demo

自定义组件的 v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的model 选项可以用来避免这样的冲突:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

现在在这个组件上使用 v-model 的时候:

<base-checkbox v-model="lovingVue"></base-checkbox> 这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox>触发一个 change事件并附带一个新的值的时候,这个 lovingVue 的 property 将会被更新。

注意你仍然需要在组件的 props 选项里声明 checked 这个 prop。

关于子组件向父组件传参数量问题

$emit传递一个参数时

子组件:
this.$emit('closeChange',false);
父组件:
<posilCom @closeChange="closeCom($event)"></posilCom>
closeCom(msg) {
    this.msg = msg;
}

$emit传递多个参数时

子组件:
this.$emit('closeChange',false,true);
父组件:
<posilCom @closeChange="closeCom(arguments)"></posilCom>
closeCom(msg) {
    this.msg1 = msg[0];
    this.msg2 = msg[1];
}