Communication between components required by Vue. js every day

Source: Internet
Author: User
Vue. js requires communication between components every day and has some reference value. If you are interested, what are components?

Component is one of the most powerful functions of Vue. js. Components can expand HTML elements and encapsulate reusable code. At a higher level, a component is a custom element, and the Vue. js compiler adds special features to it. In some cases, components can also be in the form of native HTML elements and can be extended with the is feature.

Use Components

Register

As mentioned before, we can use Vue. extend () to create a component constructor:

Var MyComponent = Vue. extend ({// option ...})

To use this constructor as a component, you need to use 'vue. component (tag, constructor) '** to register **:

// Global Register component, tag for my-componentVue.component ('My-component', MyComponent)

For custom label names, Vue. js does not require W3C rules (lower case, and contain a short bar), although it is better to follow this rule.

After the component is registered, it can be customized in the parent instance Module . Make sure that the component is registered before the root instance is initialized:

// Define var MyComponent = Vue. extend ({template :'

A custom component!

'}) // Register Vue. component ('My-component', MyComponent) // create the root instance new Vue ({el:' # example '})

Rendering:

A custom component!

Note that the component template replaces the custom element. The custom element serves only as a mount point. You can use the instance option replace to determine whether to replace.

Partial Registration

You do not need to register each component globally. The component can only be used in other components and registered with the instance option components:

Var Child = Vue. extend ({/*... */}) var Parent = Vue. extend ({template: '...', components :{//
 
  
Can only be used in the parent component template 'my-component': Child }})
 

This encapsulation also applies to other resources, such as commands, filters, and transitions.

Register syntactic sugar

To make the event simpler, you can directly input the option object instead of the constructor to the Vue. component () and component options. Vue. js automatically calls Vue. extend ():

// Expand and register Vue. component ('My-component', {template: 'In one step :'

A custom component!

'}) // You can also do this for local registration var Parent = Vue. extend ({components: {'my-component': {template :'

A custom component!

'}}})

Component options

Most options for passing in the Vue constructor can also be used in Vue. extend (), but there are two special cases: data and el. Imagine if we simply pass an object as a data option to Vue. extend ():

var data = { a: 1 }var MyComponent = Vue.extend({ data: data})

The problem is that all instances of 'mycomponent' will share the same 'data' object! This is basically not what we want. Therefore, we should use a function as the 'data' option to let this function return a new object:

var MyComponent = Vue.extend({ data: function () { return { a: 1 } }})

Similarly, the 'El' option must be a function when used in 'vue. extend.

Template Parsing

The Vue template is a DOM template, which uses a browser native parser instead of a self-implemented one. Compared with the string template, the DOM template has some advantages, but it must be a valid HTML segment. Some HTML elements have restrictions on what elements can be placed in them. Common restrictions:
• A cannot contain other interaction elements (such as buttons and links)
• Ul and ol can only directly contain li
• Select can only contain option and optgroup
• The table can only contain thead, tbody, tfoot, tr, caption, col, and colgroup.
• Tr can only directly contain th and td

In practice, these restrictions may lead to unexpected results. Although it may work in simple cases, you cannot rely on custom components to expand the results before browser verification. For example ... Not a valid template, even if the my-select component is expanded....

Another result is that custom tags (including custom elements and special tags, such , , ) Cannot be used in ul, select, table, and other labels with restrictions on internal elements. Custom labels placed inside these elements will be outside the mentioned elements, so rendering is incorrect.

The is feature should be used for custom elements:

 
 

''Cannot be used in''. You should use '','
You can have multiple '':

 
 
     Even row 
   
     Odd row 
   

Props

Use Props to transmit data

The scope of the component instance is isolated. This means that the data of the parent component cannot be directly referenced in the template of the Child component. You can use props to send data to sub-components.

"Prop" is a field of component data and is expected to be passed down from the parent component. The sub-component must explicitly declare props with the props option:

Vue. component ('child ', {// declare props: ['msg'], // prop can be used in the template // you can use 'this. msg 'set template: '{msg }}'})

Then input a common string to it:

Camper vs horizontal bars

HTML features are case insensitive. When the prop name in the form of camelCase is used as a feature, it needs to be converted to kebab-case (separated by a short horizontal line ):

Vue.component('child', { // camelCase in JavaScript props: ['myMessage'], template: '{{ myMessage }}'}) 
 
 

Dynamic Props

Similar to binding HTML features to an expression with v-bind, you can also bind dynamic Props to the data of the parent component with v-bind. Each time the data of the parent component changes, it is also transmitted to the child component:


The abbreviated Syntax of 'v-bind' is generally simpler:

Literal syntax vs. Dynamic syntax

A common mistake for beginners is to use the literal syntax to pass values:



Because it is a literal prop, its value is passed down with the string '"1"' instead of the actual number. To pass an actual JavaScript number, you need to use dynamic syntax to calculate its value as a JavaScript expression:

Prop binding type

Prop is one-way binding by default: When the attributes of the parent component change, it will be transmitted to the child component, but in turn will not. This is to prevent the child component from inadvertently modifying the status of the parent component-which makes the data flow of the application hard to understand. However, you can also use the. sync or. once binding modifier to explicitly force two-way or one-time binding:

Comparison Syntax:

 
  
 
  
 
 

Two-way binding synchronizes the msg attribute of the Child component back to the parentMsg attribute of the parent component. After a single binding is created, it does not change after synchronization.

Note that if prop is an object or array, it is passed by reference. Modifying it within a child component affects the status of the parent component, no matter which binding type is used.

Prop Verification

The component can specify verification requirements for props. This is useful when components are used by others because these verification requirements constitute the component's API and ensure that others use the components correctly. In this case, the props value is an object that includes verification requirements:

Vue. component ('example ', {props: {// basic type detection ('null' means any type) propA: Number, // multiple types (1.0.21 +) propM: [String, Number], // required and String: {type: String, required: true}, // Number, with the default value propC: {type: Number, default: 100}, // The default value of the Object/array should be returned by a function propD: {type: Object, default: function () {return {msg: 'hello '}}}, // specify this prop as a two-way binding // If the binding type is incorrect, a warning propE: {twoWay: true} will be thrown. // The Custom verification function propF: {validator: function (value) {return value> 10 }}, // Conversion function (New in 1.0.12) // convert the value propG: {coerce: function (val) before setting the value) {return val + ''// convert the value to a string}, propH: {coerce: function (val) {return JSON. parse (val) // convert a JSON string to an object }}}})

Type can be the following native constructor:
• String
• Number
• Boolean
• Function
• Object
• Array

Type can also be a custom constructor that uses instanceof for detection.

When prop verification fails, Vue rejects setting this value on the child component. If you are using a development version, a warning is thrown.

Parent-Child component communication

Parent chain

The child component can access its parent component with this. $ parent. The descendant of the root instance can use this. $ root to access it. The parent component has an array this. $ children that contains all its child elements.

Although any instance on the parent chain can be accessed, child components should avoid directly relying on the data of the parent component and use props to transmit data explicitly as much as possible. In addition, it is very bad to modify the status of the parent component in the child component, because:
1. This allows the parent component to be closely coupled with the child component;

2. It is difficult to understand the status of the parent component only by looking at the parent component. Because it may be modified by any sub-component! Ideally, only the component itself can modify its status.

Custom events

The Vue instance implements a Custom Event interface for communication in the component tree. This event system is independent of the native DOM Event and has different usage.

Each Vue instance is an event trigger:
• Use $ on () to listen to events;

• Use $ emit () to trigger an event on it;

• Use $ dispatch () to dispatch events, which bubble along the parent chain;

• Broadcast events with $ broadcast (), which are passed down to all future generations.

Unlike DOM events, Vue events automatically stop bubbling after the callback is triggered for the first time during the bubble process, unless the callback explicitly returns true.

Simple Example:

 
  
   
  Dispatch Event
  
 

Messages: {messages | json }}

// Register the sub-component // dispatch the current message to Vue. component ('child ', {template:' # child-template', data: function () {return {msg: 'hello'}, methods: {policy: function () {if (this. msg. trim () {this. $ dispatch ('child-msg ', this. msg) this. msg = ''}}}) // initialize the parent component // push the event into an array var parent = new Vue ({el: '# events-example', data: {messages: []}, // when creating an instance, the 'events' option simply calls '$ on' events: {'child-msg ': function (msg) {// The 'it' in the Event Callback is automatically bound to the instance registered with this. messages. push (msg )}}})

Use v-on to bind custom events

The above example is very good, but the code of the parent component cannot intuitively see where the "child-msg" event comes from. It would be better if we declare the event processor where the template neutron component is used. For this reason, the sub-component can use v-on to listen to custom events:


This makes it clear that when the child component triggers the 'child-msg' event, the 'handleit' method of the parent component will be called. All codes that affect the status of the parent component are placed in the 'handleit' method of the parent component. Child components only focus on trigger events.
Sub-component index

Despite props and events, you sometimes need to directly access child components in JavaScript. Therefore, you can use v-ref to specify an index ID for the child component. For example:

Var parent = new Vue ({el: '# parent'}) // access the sub-component var child = parent. $ refs. profile

When v-ref and v-for are used together, ref is an array or object that contains the corresponding child components.

Distribute content using Slot

When using components, you often need to combine them like this:

  

Note:
1. The component does not know what its mount point will contain. The content of the mount point is determined by the parent component.

2. A component may have its own template.

To enable component combination, We need to mix the content of the parent component with the template of the Child component. This processing is called content delivery (or "transclusion", if you are familiar with Angular ). Vue. js implements a content delivery API, referring to the draft of the current Web component specification, using special The element is used as the slot of the original content.

Compilation Scope

Before going deep into the content delivery API, we should clarify the scope of content compilation. Assume that the template is:


{Msg }}

Should msg be bound to the data of the parent component or the data bound to the child component? The answer is the parent component. The component scope is simply described as follows:

The content of the parent component template is compiled within the parent component scope. The content of the Child component template is compiled within the child component scope.
A common error is trying to bind a command to the sub-component attributes/methods in the parent component template:


Assuming that someChildProperty is a sub-component property, the above example will not work as expected. The parent component template should not know the status of the child component.

If you want to bind commands in a child component to the root node of a component, do the following in its template:

Vue. component ('child-component ', {// valid, because the template is in the correct scope :'

Child

', Data: function () {return {someChildProperty: true }}})

Similarly, the distribution content is compiled within the parent component scope.

Single Slot

The content of the parent component will be discarded unless the child component template contains . If the sub-component template has only one non-feature slot, the entire content of the parent component will be inserted to the place where the slot is located and replaced with it.

The tag content is considered as the rollback content. The rollback content is compiled within the scope of the Child component. This rollback content is displayed when the host element is empty and there is no content for insertion.

Assume that the my-component has the following template:

This is my component! If no content is distributed, it displays me.

Parent component template:

This is some original content


This is some more original content



Rendering result:

This is my component!

This is some original content

This is some more original content

Named Slot

The element can use a special feature name to configure how to distribute content. Multiple slots can have different names. The named slot matches the elements in the content fragment with corresponding slot features.

There can still be an anonymous slot, which is the default slot and serves as a slot for rollback where Matching content fragments cannot be found. If no default slot exists, the content fragments that cannot be found will be discarded.

For example, assume that we have a multi-insertion component whose template is:

Parent component template:

  
  

One

Two

Default A

Rendering result:

One

Default A

Two

When combining components, the content delivery API is a very useful mechanism.

Dynamic Components

Multiple components can use the same mount point and dynamically switch between them. Use Reserved Element, dynamically bound to its is feature:

New Vue ({el: 'body', data: {currentView: 'home'}, components: {home :{/*... */}, posts :{/*... */}, archive :{/*... */}}})
  
  
 

Keep-alive

If you keep the switched component in the memory, you can retain it or avoid re-rendering. To do this, you can add a keep-alive command parameter:



Activate hook

Some asynchronous operations may be required before switching components. To control the switching duration, add the activate hook to the cut-in component:

Vue.component('activate-example', { activate: function (done) { var self = this loadDataAsync(function (data) {  self.someData = data  done() }) }})

Note that the 'activate' hook only applies to the process of dynamic component switching or static component initialization rendering, and does not apply to the process of manual insertion using the instance method.
Transition-mode

The transition-mode feature is used to specify how two dynamic components are transitioned.

By default, the smooth transition from entry to exit is performed. This feature can specify two other modes:
• In-out: the new component first enters the transition phase. After the transition is completed, the current component is transitioned out.

• Out-in: the current component is transitioned out first, and the new component enters after the transition is completed.

Example:

 
 . Fade-transition {transition: opacity. 3 s success;}. fade-enter,. fade-leave {opacity: 0 ;}

Miscellaneous

Components and v-

Custom components can directly use v-for like common elements:

However, data cannot be transmitted to components because the scope of components is isolated. To pass data to components, props should be used:

V-for = "item in items"
: Item = "item"
: Index = "$ index">

The reason that the item is not automatically injected into the component is that this causes the component to be closely coupled with the current v-. Explicitly declare where the data comes from and where the component can be reused.

Compile reusable components

Remember whether to reuse components is good when writing components. One-time components are closely coupled with other components, but reusable components should define a clear public interface.

The Vue. js component API comes from three parts: prop, event, and slot:
• Prop allows external environments to transmit data to components;

• Events allow components to trigger actions in the external environment;

• Slot allows the external environment to insert content into the component's view structure.

Using the short Syntax of v-bind and v-on, the template indentation is clear and concise:

: Foo = "baz"
: Bar = "qux"
@ Event-a = "doThis"
@ Event-B = "doThat">


Hello!


Asynchronous component

In large applications, we may need to split the applications into small pieces and download them from the server only when necessary. To make things easier, Vue. js allows you to define a component as a factory function and dynamically parse the definition of the component. Vue. js only triggers factory functions when the component needs to be rendered, and caches the results for subsequent re-rendering. For example:

Vue.component('async-example', function (resolve, reject) { setTimeout(function () { resolve({  template: '

I am async!

' }) }, 1000)})

The factory function receives a resolve callback and is called when it receives the component definition downloaded from the server. You can also call reject (reason) to indicate loading failure. Here, setTimeout is only for demonstration. It is up to you to determine how to obtain components. We recommend that you use the Webpack code splitting function in combination:

Vue. component ('async-webpack-example ', function (resolve) {// This special require syntax tells webpack // Automatically splits the compiled code into different blocks, // these blocks will be automatically downloaded using ajax requests. Require (['./my-async-component'], resolve )})

Resource naming conventions

Some resources, such as components and commands, are displayed in the template in the form of HTML features or HTML custom elements. Because the names of HTML features and tags are not case sensitive, it is not convenient to use kebab-case instead of camelCase for resource names.

Vue. js supports resource names in the form of camelCase or PascalCase, and automatically convert them into kebab-case (similar to the naming convention of prop) in the template ):

// In the component definition, components: {// use camelCase to register myComponent :{/*...*/}}
 
 ES6 object literal abbreviation is OK: // PascalCaseimport TextBox from '. /components/text-box '; import DropdownMenu from '. /components/dropdown-menu '; export default {components: {// write in the template
 
  
And
  
   
TextBox, DropdownMenu }}
  
 

Recursive component

A component can call itself recursively in its template. However, it can only be called if it has the name option:

Var StackOverflow = Vue. extend ({name: 'stack-overflow', template :'

'+ // Call itself recursively' '+'

'})

The above component will cause an error "max stack size exceeded", so make sure that recursive calls have termination conditions. When you use Vue. component () to register a global component, the component ID is automatically set to the component name option.

Segment instance

When the template option is used, the content of the template replaces the Mount element of the instance. Therefore, the top-level element of the Recommendation template is always a single element.

Do not write the template as follows:

Root node 1


Root node 2

We recommend that you write this statement:


I have a single root node!

Node 1


Node 2


In the following situations, the instance is converted into a fragmented instance:
1. The template contains multiple top-level elements.
2. The template only contains plain text.
3. The template contains only other components (other components may be part instances ).
4. The template contains only one element instruction, such Or vue-router's .
5. The template root node has a flow control command, such as v-if or v-.

In these cases, the instance has an unknown number of top-level elements, which treat its DOM content as fragments. The fragment instance still correctly renders the content. However, it does not have a root node. Its $ el points to an anchor node, that is, an empty text node (in development mode, it is a comment node ).

But more importantly, the non-Flow Control commands on component elements, non-prop features and transitions will be ignored because there is no root element for binding:




Of course, the fragment instance is useful, but it is better to give the component a root node. It ensures the correct conversion of commands and features on component elements, and the performance is slightly better.

Inline Template

If a child component has the inline-template feature, the component regards its content as its template rather than as its distribution content. This makes the template more flexible.


These are compiled as the component's own template


Not parent's transclusion content.


However, inline-template makes the template scope hard to understand and cannot cache the template compilation results. The best practice is to use the template option to define a template within the component.

The above is all of the content in this article. I hope it will be helpful for everyone's learning and support for PHP's Chinese Web.

For more articles about communication between components required by Vue. js every day, please follow the PHP Chinese network!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.