Component systems are another important concept for Vue because it is an abstraction that allows us to build large applications from small, independent, and often reusable components. If you think about it, almost any type of application interface can be abstracted as a component tree:


Vue.component('todo-item', {// Todo-item components now accept a // "prop", similar to a custom attribute. // This prop is named todo. props: ['todo'], template: '<li>{{ todo.text }}</li>' })Copy the code

The sub-unit is well decoupled from the parent unit through the PROP interface.

Vue components provide some important functionality that pure custom elements

do not, most notably cross-component data flow, custom event communication, and build tool integration.

First, basic components

  1. Components are reusable Vue instances with a name that receive the same options as new Vue, such as Data, computed, Watch, Methods, and lifecycle hooks. The only exceptions are root instance-specific options like EL.
  2. Because every time you use a component, a new instance of it is created.
  3. A component’s data option must be a function
  4. Component registration types: global and local

Two, local components

A locally registered component is not available in its children

Suitable for business components

Copy the code

Global components

  1. use

    Vue.component('my-component-name', { // ... Options... })Copy the code
  2. Automated global registration of the underlying components

  3. Global registration

    • Webpack used inrequire.context Global registration
    • src/main.jsGlobal import in
  4. Note: The behavior of global registration must occur before the root Vue instance (via new Vue) is created

Component parameters

  1. No specified type
    props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
    Copy the code
  2. Each prop has a specified value type
    props: {
        title: String,
        likes: Number,
        isPublished: Boolean,
        commentIds: Array,
        author: Object,
        callback: Function,
        contactsPromise: Promise // or any other constructor
    }
    Copy the code
  3. Pass in different types of props
  • Pass in a Boolean value

    <! -- means' true ', including cases where the prop has no value. --> <blog-post is-published></blog-post> <! -- Even if 'false' is static, we still need 'v-bind' to tell Vue --> <! This is a JavaScript expression, not a string. --> <blog-post v-bind:is-published="false"></blog-post>Copy the code
  • Pass in all properties of an object

    If you want to pass in all of an object’s properties as prop, you can use v-bind with no arguments (instead of V-bind :prop-name). For example, for a given object post:

    <blog-post v-bind="post"></blog-post>Copy the code

Prop validation

5. Parameter transfer between components

  1. Unidirectional data flow

    All prop forms a one-way downlink binding between their parent prop: updates to the parent prop flow down to the child, but not the other way around. This prevents accidental changes in the state of the parent component from the child, which can make the data flow of your application difficult to understand.

    Additionally, every time the parent component changes, all prop in the child component will be refreshed to the latest value. This means that you should not change a prop inside a child component. If you do, Vue will issue a warning in the browser console.

    There are two common cases of trying to change a prop:

    • This prop is used to pass an initial value; This child component next wants to use it as a local prop data. In this case, it is best to define a local data Property and use this prop as its initial value:
    props: ['initialCounter'],
        data: function () {
                return {
                counter: this.initialCounter
            }
        }
    Copy the code

    This prop is passed in as a raw value and needs to be converted. In this case, it is best to use the value of this prop to define a calculated property:

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

PS: Note that in JavaScript objects and arrays are passed in by reference, so for a prop of an array or object type, changing the object or array itself in a child component will affect the state of the parent component.

  1. Props to verify
Vue.component('my-component', {props: {// Basic type checking (' null 'and' undefined 'will pass any type verification) propA: Number, // multiple possible types propB: [String, Number], // Required String propC: {type: String, required: true}, // Numbers with default values propD: {type: Number, default: 100}, // Object with default values propE: {type: Object, // Object or array default values must be obtained from a factory function default: function () {return {message: 'hello'}}}, // custom validation function propF: {validator: Function (value) {// This value must match one of the following strings: return ['success', 'warning', 'danger'].indexof (value)! == -1}}}})Copy the code

PS Note: Those prop are validated before a component instance is created, so instance properties (such as data, computed, and so on) are not available in default or Validator functions.

  1. Type checking

Type checking Type can be one of the following native constructors:

String
Number
Boolean
Array
Object
Date
Function
Symbol
Copy the code

In addition, type can be a custom constructor and checked with instanceof. For example, given the following ready-made constructor:

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
Copy the code

You can use:


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

To verify that the value of author Prop was created by new Person.

  1. The Attribute of the Prop
    • Imagine a template like this: To customize a theme for our date picker plug-in, we might add a special class name like this:

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

      In this case, we define two different class values:

      Form-control, which is set in the component’s template

      Date-picker-theme-dark, which is passed in from the component’s parent. For most attributes, the value supplied externally to the component replaces the value set internally by the component. So if you pass type=”text” it will replace type=”date” and break it! Fortunately, the class and style attributes are a little smarter, and the values on both sides are merged to get the final value: form-control date-picker-theme-dark.

    • Disabling Attribute Inheritance

      If you don’t want the component’s root element to inherit attributes, you can set inheritAttrs: false in the component’s options. Such as:

      Vue.component('my-component', {
          inheritAttrs: false,
          // ...
      })
      Copy the code

      This is especially useful with the instance’s $attrs property, which contains the attribute name and value passed to a component, for example:

      {
          required: true,
          placeholder: 'Enter your username'
      }
      Copy the code

      With inheritAttrs: false and $attrs, you can manually determine which element these attributes will be assigned to. This is often used when writing basic components:

      Vue.component('base-input', {
          inheritAttrs: false,
          props: ['label', 'value'],
          template: 
              ` <label>
              {{ label }}
              <input
                  v-bind="$attrs"
                  v-bind:value="value"
                  v-on:input="$emit('input', $event.target.value)" >
              </label>`
      })
      Copy the code

      Note that the inheritAttrs: false option does not affect the style and class bindings.

      This pattern allows you to use base components more like raw HTML elements, without worrying about which element is the real root element:

      <base-input
          v-model="username"
          required
          placeholder="Enter your username"
          >
      </base-input>
      Copy the code