Component development of vue.js learning notes

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:

  1. Initialize data in Vue instance
  2. Initializing props in subcomponents
  3. < 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)
  4. 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>

Tags: Javascript Front-end Vue Vue.js

Posted on Fri, 22 Oct 2021 20:41:14 -0400 by wilhud