vue.js learning notes (II) component development
1, Component development
The idea of component development: divide complex problems into many small problems. If we put all the logical processing in the page together, it will be very complex and not conducive to subsequent management and expansion. If we split a page into small function blocks, and each function block completes its own independent functions, then the management and maintenance of the whole page will become easier
1.1 basic steps for component use
Three steps for using components: (Vue 2.x is actually not used at the beginning, but is the foundation)
- Create component constructor: call Vue.extend()
- Register component: call Vue.component()
- Use component: used within the scope of Vue instance

(1)Vue.extend()
- Calling Vue.extend() creates a component constructor
- Usually, when creating a constructor, the passed in template represents the template of our custom component, which is the HTML code to be displayed where the component is used
(2)Vue.component()
- Register the component constructor as a component and give it a component label name
- Parameters passed: the tag name of the registered component and the component constructor
(3) Use components
The component must be mounted under a Vue instance, otherwise it will not take effect

1.2 global and local components
// Registered component (global component, which means it can be used under multiple Vue instances) Vue.component('cpn',cpnC); //Global component const app = new Vue({ el:'#app', data: { message:'Hello' }, components: { //The tag name when cpn uses the component cpn: cpnC //Local component } })
1.3 parent and child components
// Create the first component constructor (subcomponent) const cpnC1 = Vue.extend({ template:` <div> <h2>xxxx</h2> <p>hhhh</p> </div> ` }); // Create a second component constructor (parent component) const cpnC2 = Vue.extend({ template:` <div> <h2>xxxx</h2> <p>hhhh</p> <cpn1></cpn1> </div> `, components: { cpn1: cpnC1 } }); // root component const app = new Vue({ el:"#app", data: { message: 'How do you do' }, components: { cpn2: cpnC2 } })
1.4 grammar sugar (important, the previous writing is no longer used)
1.4.1 register global components
Vue.component('cpn1',{ template:` <div> <h2>xxxx</h2> <p>hhhh</p> </div> ` });
Note: cpn1 is wrapped in single or double quotation marks
1.4.2 register local components
const app = new Vue({ el:"#app", data: { message: 'How do you do' }, components: { 'cpn2': { template:` <div> <h2>xxxx</h2> <p>hhhh</p> </div> ` } } })
Note: cpn2 is enclosed in single or double quotation marks
1.5 separate writing method of component template
<!-- 1.script Label, note that the type must be text/x-template --> <script type="text/x-template" id="cpn"> <div> <h2>xxxx</h2> <p>hhhh</p> </div> </script> // Register global components <script> Vue.component('cpn', { template: '#cpn' }) </script>
1.6 data accessed vue by components
- Component is the encapsulation of a separate function module. This module has its own HTML and its own data attributes
- Components cannot directly access data in Vue instances
1.6.1 storage of component data
- Component objects also have data attributes (or methods and other attributes), but the data attribute must be a function, that is, data (). Reason: the function returns its own objects and will not affect each other.
- This function returns an object with data stored inside
<div id="app"> <my-cpn></my-cpn> </div> <template id="myCpn"> <div>Message:{{message}}</div> </template> <script> const app = new Vue({ el:"#app", components: { 'my-cpn': { template: "#myCpn", data() { return { message: 'hello world' } } } } }) </script>
1.7 communication between parent and child components
Background: we know that the scope of component instances is isolated. This means that you cannot (and should not) directly reference the data of the parent component or Vue instance within the template of the child component. However, in development, some data often needs to be transferred from the upper layer to the lower layer. For example, in the page, a lot of data is requested from the server, and some of the data is not displayed by the whole large component, but by the following sub components. At this time, the sub component will not send a network request again, but directly let the large component (parent component) pass the data to the small component (sub component)
1.7.1 communication method between parent and child components
- The parent component passes data to the child component through props
- The child component sends information to the parent component through the event events
- Summary: props down, events up

1.7.2 basic usage of props (parent component passes information to child component)
There are two ways for parent components to transfer data to child components: dynamic and static
1. Static props
The child component should explicitly declare the data it expects with the props option. Static props can pass values by adding properties to the placeholder of the child component in the parent component
<div id="app"> <child-cpn :message="message"></child-cpn> </div> <template id="childCpn"> <div>Message:{{message}}</div> </template> <script> const app = new Vue({ el:"#app", data: { message: 'hello' }, components: { 'child-cpn': { template: "#childCpn", props: ['message'] } } }) </script>
Process of props delivery:
- Initialize data in Vue instance
- Initializing props in subcomponents
- < child CPN: message="message" > < / child CPN > passes the data in data to props through: message="message" (message in double quotation marks is the bound data variable)
- Display the data in props in the subcomponent

2. Dynamic props
In the template, to dynamically bind the data of the parent component to the props of the child template is similar to binding to any ordinary HTML feature, that is, * * v-bind** Whenever the data of the parent component changes, the change will also be transmitted to the child component

3. Two expressions of props value
- String array: the string in the array is the name when passing
const cpn = { template: '#cpn', props:['cmovies','cmessage'] }
- Object: you can set the type of object when it is transferred, or set the default value, etc
const cpn = { template: '#cpn', props: { // 1. Type restrictions // cmovies: Array, // cmessage: String //2. Or provide some default values cmessage: { type: String, default: 'hhhhh', required: true //This means that the value must be passed, otherwise an error will be reported } // When the type is an object or array, the default value must be a function cmovies: { type: Array, default() { return [] } } } }
4. Naming conventions in props
- For the attribute declared by props, the attribute name needs to be written in the middle dash in the parent HTML template, and hump is not supported
var parentNode = { template: ` <div class="parent"> <child my-message="aaa"></child> <child :my-message="message"></child> </div>`, components: { 'child': childNode } };
- When the child props attribute is declared, it can be written in small hump or middle dash; When the child template uses the variables passed from the parent, it needs to use the corresponding small hump writing method
var childNode = { template: '<div>{{myMessage}}</div>', //The child template uses the variables passed from the parent: use the small hump writing method props:['myMessage'] // When the child props attribute is declared, it can be written in small hump or middle dash // Or props: ['My message '] }
5. props verification
Object writing is required for type verification of props
The supported data types for validation are:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
When there is a custom constructor, custom types are also supported
Vue.component('my-component', { props: { //Basic type check ('null 'matches any type) propA: Number, // Multiple possible types propB: [String, Number], // Required string propC: { type: String, required: true }, // Number with default value propD: { type: Number, default: 100 }, // Objects with default values propE: { type: Object, // Object or array defaults must be obtained from a factory function default: function() { return { message: 'hello'} } }, // Custom validation function propF: { validator: function(value) { return ['success','warning','danger'].indexOf(value) !== -1; } } } })
1.7.3 son to father
Method: complete by customizing events
Custom event flow:
- In the subcomponent, $emit() is used to trigger the event
- In the parent component, listen for child component events through v-on (@)
<!-- Parent component template --> <div id="app"> <cpn @itemClick="cpnClick"></cpn> // Listening to sub component events: trigger the cpnClick event after itemClick </div> <!-- Subcomponent template --> <template id="childCpn"> <div> <button v-for="item in cactegories" @click="btnClick(item)"> {{item.name}} </button> </div> </template> <script> // Subcomponents const cpn = { template: '#cpn', data() { return { categories:[ {id: 'aaa', name: '1'}, {id: 'bbb', name: '2'}, {id: 'ccc', name: '3'}, {id: 'ddd', name: '4'} ] } }, methods: { // Custom events for subcomponents btnClick(item) { // Launch event this.$emit('item-click',item) } } } // Parent component const app = new Vue({ el:"#app", data: { message: 'hello' }, components: { cpn }, methods: { //Parent component receives events cpnClick(item) { console.log('cpnClick'); } } }) </script>

Case: implement two buttons + 1 and - 1, and click to modify counter. When the operation process is completed in the child component and the display is handed over to the parent component, you need to pass the counter in the child component to a property of the parent component, such as total
<div id="app"> <cpn :number1="num1" :number2="num2" @num1change="num1change" @num2change="num2change"> </cpn> </div> <!-- Subcomponent template --> <template id="cpn"> <div> <h2>props:{{number1}}</h2> <h2>data:{{dnumber1}}</h2> <input type="text" v-model="dnumber1"> <h2>props:{{number2}}</h2> <h2>data:{{dnumber2}}</h2> <input type="text" v-model="dnumber2"> </div> </template> <script> // Subcomponents const cpn = { template: '#cpn', data() { return { dnumber1:this.number1, dnumber2:this.number2 } }, methods: { // Custom events for subcomponents num1Input(event) { //Assign value in input to dnnumber this.dnumber1 = event.target.value; this.$emit('num1change',this.dnumber1) this.dnumber2 = this.dnumber1 *100; this.$emit('num2change',this.dnumber2) } num2Input(event) { //Assign value in input to dnnumber this.dnumber2 = event.target.value; this.$emit('num2change',this.dnumber2) this.dnumber2 = this.dnumber2 /100; this.$emit('num1change',this.dnumber1) } } } // Or use watch to listen for attribute changes const cpn = { template: '#cpn', data() { return { dnumber1:this.number1, dnumber2:this.number2 } }, watch: { dnumber1(newvalue) { this.dnumber2 = newvalue * 100; this.$emit('num1change',newvalue); }, dnumber2(newvalue) { this.dnumber1 = newvalue / 100; this.$emit('num2change',newvalue); } } } // Parent component const app = new Vue({ el:"#app", data: { num1:1, num2:0 }, components: { cpn: { template: '#cpn', props: { number1: Number, number2: Number } } }, methods: { num1change(value) { this.num1 = parseFloat(value) }, num2change(value) { this.num2 = parseFloat(value) } } }) </script>
Note: do not directly bind num1 and num2 to change the value. Write a value when changing the data

1.8 access mode of parent-child components
- Parent component accesses child components: use $children or $refs
- Child components accessing parent components: Using** p a r e n t ∗ ∗ ( interview ask root group piece Time can use parent * * (available when accessing the root component) parent * *
1.8.1 parent component accessing child components
this.$children is an array type that contains all child component objects

1.8.2 child component accessing parent component
<template id="cpn"> <div> <h2>hhh</h2> <button @click="btnClick"></button> </div> </template> <script> const app = new Vue({ el:"#app", data:{ message:'hhh' } components: { cpn: { template: '#cpn', data() { return { name:'I am cpn Component name' } }, components: { ccpn: { template: "#ccpn", methods: { btnClick() { //1. Access parent component $parent console.log(this.$parent); console.log(this.$parent.name); //2. Access the root component $root console.log(this.$root); console.log(this.$root.message); } } } } } } }) </script>