Vue Part II: component based learning

Posted by Vball on Fri, 24 Dec 2021 12:40:56 +0100

In large-scale application development, the page can be divided into many parts. Often different pages have the same parts. For example, there may be the same head navigation.
However, if each page is developed independently, it will undoubtedly increase the cost of our development. Therefore, in order to improve code reuse, we will split the reusable part of the page into independent components, and then share these components on different pages to avoid repeated development.

First component case

There are the following requirements: you need to define multiple buttons to record the number of clicks on the page. We can do this by using what we learned before:

<div id="app">
    <button @click="increment1">You ordered me{{count1}}Once, I remember</button>
    <button @click="increment2">You ordered me{{count2}}Once, I remember</button>
</div>

<script >
    const vm = new Vue({
        el:"#app",
        data:{
            count1:0,
            count2:0
        },
        methods:{
            increment1(){
                this.count1++;
            },
            increment2(){
                this.count2++;
            }
        }
    })
</script>

Note: different buttons must operate different attributes. If the same attribute is used, the clicks of multiple buttons will be accumulated together. If the number of buttons requires more, the code cannot be reused in this way, which affects the development efficiency, and the code is not easy to maintain.

Solution: code that needs to be reused can be defined as components and reused through components.
1. Register components

<script >
     Vue.component("button-counter",{
         template:"<button @click='increment'>You ordered me{{count}}Once, I remember</button>",
         data:function(){
             return {
                 count:0
             }
         },
         methods:{
             increment(){
                 this.count++;
             }
         }
     })
</script>
  • Register components through the component method
  • The first parameter represents the component name
  • The second parameter represents the composition of the component. The component is essentially a Vue instance, which can be defined: data, methods, etc
  • When a component is defined, it is not bound to any page element, so there is no el attribute. However, the template attribute is added to extract html fragments
  • data must be a function, which will be explained later

2. Use components

<div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
</div>
  • Just use the component name as a label
    3. Create vue instance
<div id="app">
    <!-- 2 Use components -->
    <button-counter></button-counter>
    <button-counter></button-counter>    
</div>

<script >
    //1 register components
    Vue.component("button-counter",{
        template:"<button @click='increment'>You ordered me{{count}}Once, I remember</button>",
        data:function(){
            return {
                count:0
            }
        },
        methods:{
            increment(){
                this.count++;
            }
        }
    })
    //3 Create vue instance
    const vm = new Vue({
        el:"#app"
    })
</script>
  • Because the component will be used many times, when defining the component, the syntax requires that data must be a function and return a new object each time.
  • Components are to be used in Vue instances, so you must finally create Vue instances.

There are two other points to note:

  • If the component name consists of multiple words, multiple words are all lowercase according to the specification, and - connection is used, such as button counter. If you use the hump command method, such as buttonCounter, you also need to add -.
  • The template in the component can only have one root tag, for example, there is only one div root tag in the instance. If there is another div of the same level, an error will be reported.
template:"<div><button>Button</button><br></div>"                  //yes
template:"<button @click='increment'>You ordered me{{count}}Once, I remember</button>"    //yes
template:"<div><button>Button<button></div><div></div>"           //Error, 2 div root Tags

Component registration method

There are two ways to register components: global registration and local registration

1. Global registration

Globally registered components can be used in different Vue instances. The syntax is as follows:

<script>
	Vue.component("Component name",{
        template:"Multiplexed html fragment",
        data:function(){
            return {...}//return object, similar to data when creating Vue instances
        },
        methods:{
            //As when defining Vue instances, it is used to define functions
        }
    })
</script>

The first case is global registration, which will not be demonstrated here.

2. Partial registration

Once registered globally, it means that even if you no longer use this component in the future, it will still be loaded with the loading of Vue. Therefore, for some components that are not used frequently, we will use local registration. Add the option components in the Vue instance. The syntax is as follows:

<script>
	const vm = new Vue({
        el:"selector",
        data:{
            //attribute
        },
        components:{
            //Register local components
            "Component name":{
                template:"Multiplexed html fragment",
                data:function(){
                    return {...}//return object, similar to data when creating Vue instances
                },
                methods:{
                    //As when defining Vue instances, it is used to define functions
                }
            }
        }
    });
</script>

Example:

<div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>    
</div>
<script>
    const vm = new Vue({
        el:"#app",
        components:{
            "button-counter":{
                template:"<button @click='increment'>You ordered me{{count}}Once, I remember</button>",
                data:function(){
                    return {
                        count:0
                    }
                },
                methods:{
                    increment(){
                        this.count++;
                    }
                }
            }
        }
    })

</script>

3. Registration optimization

Optimization 1: separate component parameters into variables
When there are many registered components in the Vue instance, the code of the Vue instance will become very bloated, which is not conducive to code management. At this time, the Vue instance parameters can be extracted into variables.

<script>
    const buttonCounter = {
        template:"<button @click='increment'>You ordered me{{count}}Once, I remember</button>",
        data:function(){
            return {
                count:0
            }
        },
        methods:{
            increment(){
                this.count++;
            }
        }
    };

    const vm = new Vue({
        el:"#app",
        components:{
            "button-counter":buttonCounter
        }
    })

</script>

Note: during component registration, if the component name has the same name as the component variable name, it can also be abbreviated:

components:{ buttonCounter:buttonCounter }
//= = > write only one directly
buttonCounter components: {buttonCounter}

Optimization 2: extract html fragments into template tags
When the html fragment in the template is complex, it is very troublesome to directly define the html fragment in the component parameters. At this time, the html fragment can be extracted into a special template tag.

<template id="bc">
    <!-- Prompt again: template There must also be only one root label in the label -->
    <button @click='increment'>You ordered me{{count}}Once, I remember</button>
</template>
<script>
    const buttonCounter = {
        template:"#bc",
        data:function(){
            return {
                count:0
            }
        },
        methods:{
            increment(){
                this.count++;
            }
        }
    };

    const vm = new Vue({
        el:"#app",
        components:{
            "button-counter":buttonCounter
        }
    })

</script>

4. Components and is attributes (understand)

When using components in HTML tags, there are some limitations of HTML itself. For example, only specific sub tags can appear in table, ul and select. If components are used in these tags, the components cannot be displayed correctly. Solution: use the is attribute

<div id="app">
    <h4>Directly in table Used in table-body assembly</h4>
    <table border="1">
        <thead>
            <tr>
                <th>id</th>
                <th>name</th>
                <th>age</th>
                <th>gender</th>
            </tr>
        </thead>
		<!-- Direct use components-->
        <table-body></table-body>
    </table>
    <h4>stay table Passed in is Attribute use table-body assembly</h4>
    <table border="1">
        <thead>
            <tr>
                <th>id</th>
                <th>name</th>
                <th>age</th>
                <th>gender</th>
            </tr>
        </thead>
		<!-- adopt is Property usage component -->
        <tbody is="table-body"></tbody>
    </table>
</div>
    
<template id="table-body">
    <tbody>
        <tr v-for="u in users" :key="u.id">
            <td>{{u.id}}</td>
            <td>{{u.name}}</td>
            <td>{{u.age}}</td>
            <td>{{u.gender}}</td>
        </tr>
    </tbody>
</template>

<script>
    const tableBody = {
        template:"#table-body",
        data(){
            return {
                users: [
                    {"id":1, "name": "Xiao Ming", "age": 13, "gender": "male"},
                    {"id":2, "name": "Xiao Hong", "age": 13, "gender": "female"},
                    {"id":3, "name": "Little green", "age": 4, "gender": "male"}
                ]
            }
        }
    }

    const vm = new Vue({
        el:"#app",
        components:{
            "table-body":tableBody
        }
    })
</script>

Topics: Javascript Vue Vue.js html