# Vue组件选项props

# prop命名约定

对于props声明的属性来说,在父级HTML模板中,属性名需要使用中划线写法

var parentNode = {
  template: `
  <div class="parent">
    <child my-message="message1"></child>
    <child my-message="message1"></child>
  </div>`,
  components: {
    'child': childNode
  }
};
  • 🎳子级props属性声明时,使用小驼峰或者中划线写法都可以;
  • 🔮子级模板使用从父级传来的变量时,需要使用对应的小驼峰写法
var childNode = {
  template: '<div>{{myMessage}}🔮</div>',
  props:['myMessage'] // 🎳
}
var childNode = {
  template: '<div>{{myMessage}}🔮</div>',
  props:['my-message'] // 🎳
}

# prop 类型🎭

# 字符串数组形式

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

# 指定名称和类型

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

# prop 验证📯

可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue会发出警告。

要指定验证规格,需要用对象的形式,而不能用字符串数组

props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    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 value > 10
    }
}

type

type 可以是下面原生构造器

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

# 自定义type类型

额外的,type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。

例如,给定下列现成的构造函数:来验证 author prop 的值是否是通过 new Person 创建的。

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
props: {
    author: Person
}

# 静态props

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。 要让子组件使用父组件的数据,需要通过子组件的props选项

子组件要显式地用 props 选项声明它期待获得的数据

var childNode = {
  template: '<div>{{message}}</div>',
  props:['message']
}
<!-- 父组件中使用子组件并传递 message 给子组件 -->
<child message="hello world!"></child>

# 动态props

prop 可以通过 v-bind 动态赋值 每当父组件的数据变化时,该变化也会传导给子组件

<!-- 动态赋予一个变量的值 -->
<blog-post :title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
  :title="post.title + ' by ' + post.author.name"
></blog-post>

# 传入一个数字

<!-- 即便 `100` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post :likes="100"></blog-post>

<!-- 如果直接 likes = "100" 子组件收到的则是字符串100 -->

<!-- 用一个变量进行动态赋值。-->
<blog-post :likes="post.likes"></blog-post>

# 传入一个布尔值

<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-post is-published></blog-post>

<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post :is-published="false"></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post :is-published="post.isPublished"></blog-post>

# 传入一个数组

<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post :comment-ids="[234, 266, 273]"></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post :comment-ids="post.commentIds"></blog-post>

# 传入一个对象

<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post
    :author="{
        name: 'Veronica',
        company: 'Veridian Dynamics'
}"
></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post :author="post.author"></blog-post>

# 传入一个对象的所有属性

TIP

如果你想要将一个对象的所有 属性 都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。

例如,对于一个给定的对象 post

post: {
    id: 1,
    title: 'How to lenarn Vue?'
}
<blog-post v-bind="post"></blog-post>

等价于以下模板

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

# 单向数据流

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解

另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着不应该在子组件内部改变 prop。如果这么做了,Vue 会在控制台给出警告。

WARNING

这里有两种常见的试图变更一个 prop 的情形

  • 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data property 并将这个 prop 用作其初始值:
 


 



props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

WARNING

但是,定义的局部变量counter只能接受initialCounter的初始值,当父组件要传递的值发生变化时,counter无法接收到最新值

  • 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
  • 更加妥帖的方案是,使用变量储存prop的初始值,并使用 watch 来观察 prop的值的变化。发生变化时,更新data中变量的值
props:['childMsg'],

data(){
    return{
      temp:this.childMsg
    }
},

watch:{
    childMsg(){
      this.temp = this.childMsg //  this.childMsg 由父组件传递的值
    }
}
Last Updated: 12/28/2022, 10:52:19 PM