# 组件化开发2

# Prop

# Prop 的大小写

因为 HTML 的属性名是大小写不敏感的,所以浏览器会解释为小写字符,当使用 DOM 中的模板时,需要使用 kebab-case 命名来调用组件。

<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
Vue.component("blog-post", {
  // 在 JavaScript 中是 camelCase 的
  props: ["postTitle"],
  template: "<h3>{{ postTitle }}</h3>"
});

# Prop 类型

通常我们希望每个 prop 都有指定的值类型,这是可以对象形式列出 prop

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

# 传递静态或动态 Prop

静态

<blog-post title="My journey with Vue"></blog-post>

动态 v-bind

<blog-post v-bind:post="post"></blog-post>

传入一个对象的所有property

<blog-post v-bind="post"></blog-post>

如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的 v-bind

post: {
  id: 1,
  title: 'My Journey with Vue'
}

# 单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级的 prop 的更新会向下流动到子组件中,反之则不行。

重要提示

注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或者对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件中的状态,这时我们可以考虑对传入子组件的值进行拷贝

# Prop 验证

我们可以为组件的 prop 指定验证要求,例如知道这些类型,如果有一个需求没有满足,Vue 就会在控制台警告

Vue.component("my-component", {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: "hello" };
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ["success", "warning", "danger"].indexOf(value) !== -1;
      }
    }
  }
});

类型检查

String Number Boolean
Array Object Date
Function Symbol

# 自定义组件的v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。但是有时可能会将value用于不同目的,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)"
    >
  `
});
<base-checkbox v-model="lovingVue"></base-checkbox>

现在lovingVue的值会传入checked,同时当<base-checkbox>触发一个 change 事件并附带一个新的值是,这个 lovingVue 的property将会被更新