I. Component classification

Vue components can be roughly divided into two types: basic components and business components

The basic component is just the most basic component, which does not involve any business, such as the component provided by Element. In the system, it can be used for a specific function, and is also the basis for business components or other components to realize personalized requirements.

Business component is to realize some specific business existence, business is one of the main considerations of its design and implementation, it often depends on the basic components to achieve;

Whether the basic components or business components, have a common is reusable, extensible, if not reusable, expansion, we must consider the necessity of design.

Two, component composition

I think there are three things to consider when designing a component:

  • The template

    Component is the view, is an essential part of, that is to say, the component was eventually render into what style is users concerned about one thing, the requirements of product design, in addition to the basic view is we need to advance written, we also need to provide scalable slot slot, this part of the content of the view should be determined by the user.

  • data

    For a component, the processing of data is a core part. Since VUE is a data-driven view, the final shape of the template is influenced by the data, and the communication between components changes the data first. Therefore, it is a test of a developer’s ability to handle the data inside a component.

  • The event

    Generally speaking, the business component is to some extent will depend on the basic components to implementation, and business components and can be applied to various pages, in order to better meet the implementation of the business, the component must be provided to the user specific event is used to communicate with each other, in this case, the user is not the user itself, but with it has a hierarchy of components or half brother components, What they communicate is content is data, and that’s important. From the performance of the page, the process of interaction, once upon a time the point of view, and the realization of the business is user man-made to operate page, triggering the inside of the component, activate the communication between the components, so as to achieve the change of the data, finally get valuable data is passed to the backend, for all kinds of deconstruction, analysis, processing and storage.

Three, a simple component implementation

1. Basic parent-child component communication

A component can be used by other components to form parent components. In general, parent components communicate like this:

  • The child component accepts data from the parent through the props property
  • The parent component listens for events emitted by the child component via the $emit method to fetch data from the child component

However, some scenarios want to be able to communicate data with child components in a bidirectional data binding mode in the parent component, so VUE provides the Model option to define bidirectional data binding data using PROP, and the emitted custom events that pass the value up using Event.

But one thing to note:

  • The values defined by prop need to be defined in props as well

Of course, there are many other ways to communicate between components, which will be covered in a future article.

Let’s implement the simplest input component based on the input element. This example comes from the official VUE documentation

<template>
  <label>
    {{ label }}
    <input
      type="input"
      :value="value"
      @input="$emit('input', $event.target.value)"
    >
  </label>
</template>

<script>

export default {
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    label: {
      type: String,
      default: ''
    },
    value: {
      type: String,
      default: ''
    }
  },
};
</script>

<style></style>
Copy the code

In the example above, the value value is two-way data binding. The event that passes the value up is input. What is the timing of the input event? Is the native event input supported by the element, so you only need to listen for the input event, that is, when the user inputs, the event input is triggered and the value is passed up to the parent component. Any change in the value of the bidirectional data binding to the child component in any scenario in the parent component can be synchronized to the child component.

2. Events in the component

The above mentioned “custom events” and “native events”, the following distinction is made, but first, the following

  • Native events

    Native events involve a lot of content, AND I have written a separate article to introduce it. For details, you can refer to javascript event flow, event handlers, and event types

  • Custom events

    An event is a browser action or a user action, and a function that responds to an event is an event handler. An event handler (event listener) must be written in the code to do some business logic in response to a user click. How is an HTML event handler implemented in a native event? Each event supported by an element can be specified using an HTML feature with the same name as the corresponding event handler. The value of this feature is executable javascript code. In general, we define this value as a function to implement some business logic in the function body. This function is our custom event. In VUE, event handlers are implemented in the same way as HTML event handlers, so custom events in VUE components should be understood.

Bind native components to components

Sometimes when I write a component like a card and I want to click on the card to implement some business logic, it’s natural to write code like this:

<base-card v-on:click.native="onClick"></base-card>
Copy the code

This is possible in most cases with the. Native modifier, because listening for an event on a component is actually listening directly on the root element of a component, which is usually a div, which supports native click events for most HTML elements.

However, if you listen for the input event of a div, this will not respond. Because the div tag does not support the input events, from this point, if you write the components of the root element is not support a certain native events, you passed. Native modifier listen to native component events is of no effect, if you don’t know the reason, you will be very trouble, because it does not produce any error.

To solve this problem, analyze specific scenarios, such as the above example:

input-label.vue

<template>
  <label>
    {{ label }}
    <input
      type="input"
      :value="value"
	  @input="$emit('input', $event.target.value)"
    >
  </label>
</template>

<script>

export default {
  props: {
    label: {
      type: String,
      default: ''
    },
    value: {
      type: String,
      default: ''
    }
  },
};
</script>

<style></style>


<input-label @focus.native="input"></input-label>
Copy the code

This does not work because the label element does not support the focus event. However, if you listen for a specific element in a child component and emit custom events, this is not used in the parent component. The native modifier can be used to listen for custom events emitted by the child component. Why is that? Because the real place on the page where the user operates is in the area of the input box, this is perfectly fine in terms of how the child communicates with the parent.

<template>
  <label>
    {{ label }}
    <input
      type="input"
      :value="value"
      @focus="$emit('focus')"
    >
  </label>
</template>

<script>

export default {
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    label: {
      type: String,
      default: ''
    },
    value: {
      type: String,
      default: ''
    }
  },
};
</script>

<input-label @focus="onFocus"></input-label>
Copy the code

So the trouble is, if I want to listen for multiple native events when the parent uses a child component as per the solution above wouldn’t I want to listen for multiple native events in the child component and fire custom events at the same time?

The Vue provides a $Listeners property, which is an object containing all listeners that work on the component. If V-on =”$listeners” point all event listeners to a particular child of the component. When you use the component again, you can listen for events supported by a particular element in the component. The $Listeners contain all listeners supported by that element. In addition, no modifiers are required. Native can listen.

<template> <label> {{ label }} <input type="input" :value="value" v-on="$listeners" > </label> </template> <script> export default { props: { label: { type: String, default: '' }, value: { type: String, default: '' } }, }; </script> <style></style> <input-label @input="onInput" label=" click "></input-label> <input-label @focus="onFocus"></input-label>Copy the code

At this point, listening can be implemented, and the child components do not need to emit custom events.

Similarly, Vue provides $attrs Property, which is an object containing all attributes applied to the component, with v-bind=”$attrs” to point all attributes to a particular child element of the component. When using this component, you can directly bind this property to pass values without defining props inside the component to receive values.

In fact, V-on =”$listeners” and V-bind =”$attrs” are very useful for component encapsulation, not only for a particular element of a component, but also for child components. For example, if we want to repackage a component based on the Element component and use all the listeners and properties of the existing element component, we don’t need to props the properties or $emit the original listeners. Such as:

<template> <el-date-picker type="date" clearable format="yyyy/MM/dd" value-format="yyyy-MM-dd" v-bind="$attrs" V-on ="$listeners" ></el-date-picker> </template> <script> /** * Easy date picker * - Specifies the same date formatting rules */ export default {}; </script>Copy the code

When using this double-wrapped component, you can use all the properties and listeners provided by the el-date-picker directly.