12-父子组件数据传递 & 深入Prop & 非 Prop特性

Prop:
向子组件传递数据,在组件上注册的自定义特性
当值传递给 prop 特性的时候,Prop就变成组件实例的属性

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

/* 在父组件传递 props */
<div>
  <blog-post title="My journey with Vue"></blog-post>
</div>

通过事件向父级组件发送消息:
调用 $emit() 方法向父级组件触发事件
$emit() 第一个参数为事件名,第二个参数为传入的参数

/* 子组件:通过 $emit('enlarge', arg ) 派发事件 */
<button @:click="$emit('enlarge', 0 )">Enlarge text</button>

/* 父组件: 通过 v-on监听子组件发布的事件和传入的参数 */
<blog-post @:enlarge="getDate"></blog-post>
methods: {
  getDate( arg ) { /* 监听的回调接收的参数 */
    1 + arg
  }
}

============================ 深入 Prop ============================

Prop 的大小写 (camelCase vs kebab-case):
在 JS 中是 camelCase;
在 HTML 中是 kebab-case

  /* 在JS中是camelCase */
  Vue.component('blog-post', {
    props: ['postTitle'], 
    template: '<h3>{{ postTitle }}</h3>'
  });

  <!-- 在 HTML 中是 kebab-case 的 -->
  <blog-post post-title="hello!"></blog-post>

传递静态或动态 Prop: 任何类型的值都可以传给一个 prop

  /* 静态传递 Prop */
  <blog-post title="My journey with Vue"></blog-post>

  /* 动态传递Prop */
  <blog-post :title="post.title"></blog-post>

  /* 动态传递表达式的值 */
  <blog-post :title="post.title + ' by ' + post.author.name"></blog-post>

传入一个数字

  /* v-bind 告诉 Vue 这是 JS 表达式 */
  <blog-post :likes="42"></blog-post>

  /* 用变量动态赋值 */
  <blog-post :likes="post.likes"></blog-post>

传入一个布尔值

  /* prop 没有值的情况下,默认为 true */
  <blog-post is-published></blog-post>

  /* false 是静态的仍然要 v-bind 告诉 Vue 这是 JS 表达式 */
  <blog-post :is-published="false"></blog-post>

  /* 用变量动态赋值 */
  <blog-post v-bind:is-published="post.isPublished"></blog-post>

传入一个数组

  /* 即便数组是静态的,仍要 `v-bind` 告诉 Vue 这是一个 JS 表达式 */
  <blog-post :comment-ids="[234, 266, 273]"></blog-post>

  /* 用变量行动态赋值 */
  <blog-post :comment-ids="post.commentIds"></blog-post>

传入一个对象

  /* 即便对象是静态的仍要 v-bind 告诉 Vue 这是一个 JS 表达式 */
  <blog-post :author="{ name: 'Veronica', company: 'Dynamics' }"></blog-post>

  /* 用变量行动态赋值 */
  <blog-post :author="post.author"></blog-post>

传入一个对象的所有属性: 将对象的所有属性都作为 prop 传入,使用不带参数的 v-bind

  post: { id: 1, title: 'My Vue' }
  <blog-post v-bind="post"></blog-post>

单向数据流

1、父子 prop 之间形成了一个单向下行绑定,父级 prop 的更新会向下流动到子组件中,但是反过来则不行,防止子组件意外改变父级组件的状态,导致数据流向难以理解
2、每次父级组件更新时,子组件中所有的 prop 都将会刷新为最新的值
3、对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态

定义一个本地的 data 属性并将这个 prop 用作其初始值

  props: ['initialCounter'],
    data() {
      return {
        counter: this.initialCounter  /* 拷贝一个 props 副本 */
      }
  }

使用 prop 的值来定义一个计算属性

  props: ['size'],
  computed: {
    normalizedSize() {
      /* 字符串操作时,new String() 会返回一个新的值, 这样并不会改变传递的 Prop */
      return this.size.trim().toLowerCase() 
    }
  }

PropType:类型检查
type 可以是原生JS中类型的任意一种, 也可以是一个自定义的构造函数,通过 instanceof 来进行检查确认

String Number Boolean
Array Object Date
Function Symbol

  /* type可以是一个自定义的构造函数 */
  function Person (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }

  Vue.component('blog-post', {
    props: {
      author: Person
    }
  })

Prop 验证: 指定验证数据类型
prop 在实例创建之前验证,实例属性 data、computed在 defaultvalidator 函数中不可用

  Vue.component('my-component', {
    props: {

      propA: Number,                /* 基础的类型检查 (`null` 匹配任何类型) */
      propB: [String, Number],      /* 多个可能的类型 */
      propC: {                      /* required 必填的字符串 */
        type: String,
        required: true
      },
      propD: {                      /* default 带有默认值的数字 */
        type: Number,
        default: 100
      },
      propE: {                      /* default 带有默认值的对象 */
        type: Object,
        default: function () {      /* 对象或数组默认值必须从工厂函数获取 */
          return { message: 'hello' }
        }
      },

      propF: {                      /* validator 自定义验证函数 */
        validator(value) {
          return ['success', 'warning', 'danger'].indexOf(value) !== -1
        }
      }
    }
  })

对象或数组默认值必须从工厂函数获取

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

非 Prop 的特性: prop 传向一个组件时, 该组件并没有相应 prop 定义的特性

禁用特性继承
如果不希望组件的根元素继承特性,可以在组件的选项中设置 inheritAttrs: false;适合配合实例的 $attrs 属性

  Vue.component('base-input', {
    inheritAttrs: false,  /* 禁用特性 */
    props: ['label', 'value'],
    template: `
      <label>
        {{ label }}
        <input
          v-bind="$attrs"  	/* 配合 $attrs */
          v-bind:value="value"
          v-on:input="$emit('input', $event.target.value)"
        >
      </label>
    `
  })
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值