Vue framework 2.0 Basics (5) components and communication between components

Component: a reusable Vue instance with a name and accepts the same option objects, such as data, computed, watch, methods, and life cycle hooks. The only exception is options specific to root instances like el.

Function: components can be reused any number of times. Each component maintains itself independently. Because every time a component is used, a new instance of it is created.

A component template can only have one root element.

//The following situations are not allowed

Vue.component('my-component', {
  template: `<div>This is a partial custom component, which can only be used in the current Vue Used in instances</div>
            <button>hello</button>`
})

data in component must be a function?

Because the object type variables in JS actually store the reference of the object, when there are multiple such components, the data will be shared, resulting in the change of data in one component and the change of data in other components.
Using a function that returns an object, a new object will be created every time the component is used, so there will be no problem of sharing data.
Summary: different objects are generated through functions, and the changes of attributes will no longer affect each other

Vue.component('my-component', {
   data:function(){
          return {
              name:'Lee'
          }
  },
})


Component name:
Use kebab case (DASH split naming): when defining a component with dash split naming, you must also use this method when referencing this custom element.

Vue.component('my-component-name', { /* ... */ })

Use pascalcase: when defining a component with an uppercase name, both naming methods can be used when referring to this custom element.

Vue.component('MyComponentName', { /* ... */ })


Definition of global components

Component ---- component (i.e. object)

Vue.component("mynav",{
    template:"<ul><li>home page</li><li>my</li></ul>"
})

Note: when defining a component, the data attribute in it must be functional programming to return an independent number each time the component is called.

Definition of local components
//1. Create component

//Locally registered components can only be used in the current Vue instance.
let mynav={
    template:"<p>This is a navigation</p>",
    data(){
        return{
            
        }
    },
    methods:{},
    watch:{},
    computed:{},
    
}

//2. Register components

const app=new Vue({
    el:'#app',
  components:{
      mynav
  }
})

*Note: when naming components for hump, use - connection when using components to write labels. For example, when defining a component, myIpt should be written as < My IPT > < / my IPT >

How to use local component
Let's look at the usage:

<!-- Dynamic components by vm Instance `componentId` property control -->
<component :is="componentId"></component>

Let's take an example:

<body>
    <div id="app">
        <!-- Another way to introduce components -->
        <component :is="current"></component>
    </div>
    <script src="../../node_modules/vue/dist/vue.js"></script>
    <script>
        let home = {
            template: '<div>home</div>'
        }
        let about = {
            template: '<div>about</div>'
        }

        const app = new Vue({
            el: '#app',
            data: {
                current: about
            },
            components: {
                home, about
            }
        })
    </script>

</body>

Nesting of components

<body>
    <div id="app">
        <father></father>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
     let son = {
            template: '<div>son</div>'
        }
        let father = {
            template: '<span>father<son></son></span>',
            components: {
                son
            }
        }
     
        const app = new Vue({
            el: '#app',
            components: {
                father
            }
        })

    </script>
</body>

Note: the nested child component declaration of the component must be placed in front of the parent component, and the child component must be declared in the parent component

Communication between components
Parent to child communication

The parent component passes data to the child component through Props:
To use props, first write the element to be transferred in the child tag of the parent component, and then receive it in the child component through props, which is equivalent to a data value. However, note that this value cannot be changed here because it is given by the parent component.

Use props in the child component to receive the data passed by the parent component. The name in props is consistent with the attribute name defined by the parent component

However, if you want to modify the value passed by the parent component in the child component without "polluting" the parent component, you can define a variable mydata in the child component to receive fatherData data, and use watch to monitor the changes of fatherData data.

Vue child components accept the data passed by the parent component through the props attribute.

Because HTML features are case insensitive, attribute values should be separated and named with dashes when passing them.

<body>
    <div id="app">
        <father></father>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
     let son = {
            template: '<div>son {{m}}</div>',
            // props: ['m '], / / props: two ways to write, object and array
            props:{
                m:{
                    // type:Number, / / specify the type of the value
                    // default:300, / / default value
                    required:true      //Must the parent component write this m property
                }
            }
        
        }
        let father = {
            template: '<span>father<son :m="money" ></son></span>',
            components: {
                son
            },
            data(){
                return{
                    money:100
                }
            }
        }
     
        const app = new Vue({
            el: '#app',
            components: {
                father
            }
        })

    </script>
</body>

Child to parent communication
Custom events

/ / subcomponent publishing event

this.$emit('more') Publish event

/ / parent component registration event

@more='handler()' //handler is a function body


Let's look at the detailed code:

<body>
    <div id="app">
        <father></father>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
     let son = {
            template: '<div>son {{m}} <button @click="add">Click Add</button> </div>',
            // props: ['m'],
            props:{
                m:{
    
                    required:true
                }
            },
            methods: {
                add(){
                    this.$emit('add')  //Publish an add
                }
            },
        
        }
        let father = {
            template: '<span>father<son :m="money" @add="add"></son></span>',  //The son tag receives add and triggers the following functions.
            components: {
                son
            },
            data(){
                return{
                    money:100
                }
            },
            methods:{
                add(){
                    this.money+=100
                }
            }
           
        }
     
        const app = new Vue({
            el: '#app',
            components: {
                father
            }
        })

    </script>
</body>

Communication between sibling components
Create a Vue instance of the event car and publish and subscribe through it.

<body>
    <div id="app">
        <brother1></brother1>
        <bro-ther2></bro-ther2>  //Pay attention to the writing of the component label named hump
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
        const eventBus = new Vue()
        let brother1 = {
            template: '<span @click="changecolor">111</span>',
            methods:{
                changecolor(){
                    eventBus.$emit('green')   //Release green through the event car
                }
            }

        }
        let broTher2 = {
            template: '<span :style={color:color}>222</span>',
            created(){
                eventBus.$on('green',()=>{  //Subscribe to the green event through the event car and execute the callback function to assign color
                this.color='green'
                })
            },
            data(){
                return{
                    color:''
                }
            }
        }
        const app = new Vue({
            el: '#app',
            components: {
                brother1,
                broTher2
            }
        })
    </script>
</body>

Intergenerational communication
Method used: provide inject

<body>
    <div id="app">
        <grand-father></grand-father>

    </div>

    <!-- Writing of each template -->
    <template id="son">
        <div>
            Son
            {{msg}}
        </div>
    </template>

    <template id="father">
        <div>
            Father
            <son></son>
        </div>
    </template>
    <template id="grandFather">
        <div>
            grandFather
            <father></father>
        </div>
    </template>

    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
        let son = {
            template: '#son',
            inject:['msg']   //inject receive

        }
        let father = {
            template: '#father',
            components: {
                son
            }
        }
        let grandFather = {
            template: '#grandFather',
            components: {
                father
            },
            provide:{
                msg:"Intergenerational communication"  //provide
            }

        }

        const app = new Vue({
            el: '#app',
            components: {
                grandFather
            }
        })
    </script>
</body>


PubSub plug-in realizes the communication between any components
Similarly, you can use a third-party plug-in: PubSub to achieve the same operation

pubsub. Subscribe
pubsub.publish() publish

<body>
    <div id="app">
        <brother1></brother1>
        <brother2></brother2>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/PubSub"></script>
    <script>
        const eventBus = new Vue();
        const pubsub = new PubSub();
        let brother1 = {
            template: '<span @click="changeGreen" :style={color:color}>brother1</span>',
            methods: {
                changeGreen() {
                    pubsub.publish('green')
                }
            },
            data() {
                return {
                    color: ''
                }
            },
            created() {
                pubsub.subscribe('red', () => {
                    this.color = 'red'
                })
            }
        }
        let brother2 = {
            template: '<span :style={color:color}  @click="changeRed">brother2</span>',
            created() {
                pubsub.subscribe('green', () => {
                    console.log(111);
                    this.color = 'green';
                })
            },
            data() {
                return {
                    color: ''
                }
            },
            methods: {
                changeRed() {
                    pubsub.publish('red')
                }
            }

        }
        const app = new Vue({
            el: '#app',
            components: {
                brother1,
                brother2
            }
        })
    </script>
</body>


Mutual access of parent and child components
Parent access child
Using the ref method, bind components with ref to obtain bound components.  

<body>
    <div id="app">
<father></father>

    </div>

    <!-- Writing of each template -->
    <template id="son">
        <div v-show='isShow'>
            Son
        </div>
    </template>

    <template id="father">
        <div>
            Father
            <son ref="myson"></son>
            <button @click="change">Show or hide</button>
        </div>
    </template>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
        let son={
            template:'#son',
            methods: {
                changeColor(){
                   return this.isShow=!this.isShow
                }
            },
            data(){
                return{
                    isShow:false
                }
            }
        }
//When ref is added to the component, the Vue instance is obtained

        let father={
        template:'#father',
        components:{
            son
        },
        methods:{
change(){
    console.log(this.$refs.myson)
    this.$refs.myson.changeColor()
}
        }
        }

    const app=new Vue({
            el:'#app',
            components:{
                father
            }
        })
    </script>
</body>

Child access parent
$parent method to access the parent component.

<body>
    <div id="app">
        <father></father>

    </div>
    <!-- Writing of each template -->
    <template id="son">
        <div >
            Son
            <button @click="get">Click me to get the attributes of the parent element</button>
        </div>
        
    </template>

    <template id="father">
        <div>
            Father
            <son></son>
   
        </div>
    </template>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
        let son = {
            template: '#son',
            methods: {
                get(){
                    console.log(this.$parent.money)  //$parent access parent component
                }
            },
       
        }
  

        let father = {
            template: '#father',
            components: {
                son
            },
            data(){
                return{
                    money:111234
                }
            }
           
        }

        const app = new Vue({
            el: '#app',
            components: {
                father
            }
        })
    </script>
</body>

Summary:
Common usage scenarios can be divided into three categories:

Parent-child communication: the parent transmits data to the child through props, and the child transmits data to the parent through events ($emit); You can also communicate through the parent chain / child chain ($parent / $children); ref can also access component instances; provide / inject API; $ attrs/$listeners

Brother communication: Bus; Vuex

Cross level communication: Bus; Vuex; provide / inject API, $attrs/$listeners

Keywords: Javascript Front-end Vue.js

Added by keveen on Mon, 21 Feb 2022 15:47:12 +0200