Vue.js知识库(四):组件注册、Prop

组件全局注册、局部注册、Prop使用和Prop验证。
252阅读 · 2020-8-25 23:59发布

组件名称

创建组件名时建议遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。

Vue.component('my-component-name', { /* ... */ })

定义组件名称方式一:kebab-case(短横线分隔命名)

Vue.component('my-component-name', { /* ... */ })

定义组件名称方式二:PascalCase(首字母大写命名)

Vue.component('MyComponentName', { /* ... */ })

全局注册

通过Vue.component注册的组件属于全局注册,它可以在任何新创建的Vue根实例(new Vue)中使用。(子组件中的内部也可以互相使用)

<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })

new Vue({ el: '#app' })

局部注册

components中注册的组件为局部注册,只允许在注册的组件中使用(子组件中也不可用)。在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写。

// 局部注册
new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

// 子组件中注册
var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'component-a': ComponentA
  },
  // ...
}

// 简写
import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  },
  // ...
}

Prop

Prop的大小写

Prop中如果使用camelCase (驼峰命名法) ,使用时需要使用kebab-case (短横线分隔命名) 。

<div id="example">
    <alert-box post-title="abc">
      Something bad happened.
    </alert-box>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('alert-box', {
      template: `
        <div class="demo-alert-box">
          <strong>Error!</strong>
          <slot></slot>
          {{postTitle}}
        </div>
      `,
      props:['postTitle']
    })
    var data = {
        todoValue:''
    }
    var vm = new Vue({
        el: '#example',
        data: data
    })
</script>

传递值给Prop

静态赋值

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

动态赋值

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

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

传入数字

<blog-post v-bind:likes="42"></blog-post>
<blog-post v-bind:likes="post.likes"></blog-post>

传入布尔值

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

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

传入数组

<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>

传入对象

<blog-post
  v-bind:author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
></blog-post>
<blog-post v-bind:author="post.author"></blog-post>

传入一个对象的所有属性

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

// 上面等同于下面
<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

单向数据流

通常需要避免子组件中改变传入的值后,父组件中的值也跟着改变。如果有需要改变prop值的场景,可以使用一下两种方式。

子组件中定义data接收prop

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

使用计算属性

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

指定Prop类型

可以指定组件中prop属性的类型,如果传入的类型不匹配,控制台中会报错。

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

可以使用以下类型:

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

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
      }
    }
  }
})

可以使用自定义构造函数来验证。

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
Vue.component('blog-post', {
  props: {
    author: Person
  }
})

非Prop的Attribute操作

如果传入组件的属性,没有对应的prop,则这些attribute会被添加到这个组件的根元素上。(组件可以接受任意的 attribute)

重复的Attribute

  • 如果是class和style,会将传入的值进行合并。
  • 如果非class和style,外部的值会替换掉组件内部设置好的值。

代码示例

// bootstrap-date-input的内容
<input type="date" class="form-control">

<bootstrap-date-input
  data-date-picker="activated"
  class="date-picker-theme-dark"
></bootstrap-date-input>

//最终class="form-control date-picker-theme-dark"