This is the sixth day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021.

preface

Vue study notes in the content of the blog in the last chapter we preliminary understanding of the component (7) component, and learned how to define the global component and local components, the previous content only to the components of a simple introduction, not in-depth understanding of the components of other mechanisms, this blog will bring you a deep understanding of the other knowledge of components, component check, Component communication and so on.

Objective in this chapter

  • Learn simple validation of components
  • Learn to pass data from parent to child
  • Learn how to pass data from a child to a parent

The parent component passes data to the child component

The way a parent component passes data to a child component is extremely simple, just using props to pass data.

  • Syntax: props[‘ property 1’, ‘property 2’,…]

I found a picture for you to look at

In vue. js, the parent-child component relationship can be summarized as props Down, events up. The parent component passes data down to the child component through props, and the child component sends messages to the parent component through Events

  • A simple parent component passes information to its children
<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>The parent component passes information to the child component</title>
    </head>
    <body>
        <div id="app">
            <my-content :title='title' :content='content'></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">Let the vm = new Vue ({el: '# app, data: {title:' title ', content: 'content'}, the methods: {}, computed: {}, components:{ 'myContent':{ props:['title','content'], template:`<div>
                            <h1>{{title}}</h1>
                            <p>{{content}}</p>
                        </div>`}}})</script>
    </body>
</html>
Copy the code

The results of

Display title and content, the simplest parent component to child components to pass information we have implemented, but there are other small knowledge points we have not explained, and the later development is to use vuE-CLI to achieve the parent component to child components to transfer data.

So this will be covered in the next blog post. For those of you who don’t know how to build vue-CLI with WebStorm, there will be many subsequent posts that will use vue-CLI components.

Instead of simply importing vue.js files, it is highly recommended that you learn to build vue-CLI projects.

Conclusion: The parent component passes data to the child component using props

  • Props passes the entire object

Suppose the object in the parent component has multiple properties, and we need to pass each one. Do we need to bind each one?

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Props passes multiple properties</title>
    </head>
    <body>
        <div id="app">
            <my-content :title="attr.title" :content1="attr.content1" :content2="attr.content2"></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">Let vm=new Vue({el:'#app', data:{attr:{title:' #app', content2:' #app',}}, methods:{}, computed:{ }, components:{ 'myContent':{ props:['title','content1','content2'], template:'<div><h4>{{title}}</h4><span>{{content1}}</span><span>{{content2}}</span></div>'}}})</script>
    </body>
</html>
Copy the code

Now what this example shows is that there are many properties in an object, now there are only three properties. When our parent component binds properties, we need to bind three properties. If it’s 100 or 1000, isn’t the tag of the binding component very long?

If you’re working with a colleague, your colleagues will be skeptical of the length of the code, so to solve this problem we’ll rewrite the code as follows.

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Props passes multiple properties</title>
    </head>
    <body>
        <div id="app">
            <my-content  v-bind="attr"></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">Let vm=new Vue({el:'#app', data:{attr:{title:' #app', content2:' #app',}}, methods:{}, computed:{ }, components:{ 'myContent':{ props:['title','content1','content2'], template:'<div><h4>{{title}}</h4><span>{{content1}}</span><span>{{content2}}</span></div>'}}})</script>
    </body>
</html>
Copy the code

Here we use V-bind to package the entire object and pass it along, which greatly reduces code redundancy.

  • Data must be a function

Why does data have to be a function? This point was not mentioned in the last blog post. Now let’s discuss it. This case is enough to illustrate.

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Data must be a function</title>
    </head>
    <body>
        <div id="app">
            <my-content></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            Vue.component('myContent', {data: {msg:'hello world'
                },
                template:'<span>{{msg}}</span>'});let vm=new Vue({
                el:'#app'
            })
        </script>
    </body>
</html>
Copy the code

Results:

The console shows the warning given by vue.js that data must be a function. Ok, since data must be a function, let’s do what it says. Let’s see what happens.

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Data must be a function</title>
    </head>
    <body>
        <div id="app">
            <my-content></my-content>
            <my-content></my-content>
            <my-content></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            var data={
                count:1
            }
            Vue.component('myContent', {data:function(){
                    return data;
                },
                template:'<button @click="count+=1">{{count}}</button>'});let vm=new Vue({
                el:'#app'
            })
        </script>
    </body>
</html>
Copy the code

Now, our data is a function, but also to solve the problem of a new problem appeared again, click on any button to find the value of the other buttons will change, it is because we refer to the same object, we know that the object is a reference, so in order to change this kind of circumstance, We let each component have its own internal state without interfering with other components.

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Data must be a function</title>
    </head>
    <body>
        <div id="app">
            <my-content></my-content>
            <my-content></my-content>
            <my-content></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            Vue.component('myContent', {data(){
                    return{
                        count:1}},template:'<button @click="count+=1">{{count}}</button>'});let vm=new Vue({
                el:'#app'
            })
        </script>
    </body>
</html>
Copy the code

Results:

We use returns in data to return new objects, so that each component has its own state and does not affect other components.

Component verification

Component verification literally means that the parent component verifies the information transmitted by the parent component to the child component. On the one hand, the child component verifies the information transmitted by the parent component. On the other hand, the verification of the data transmitted by others can also be restricted when used by others.

Vue.component('example', {
  props: {
    // Base type detection (' null 'means any type can be used)
    propA: Number.// Multiple types
    propB: [String.Number].// Must be a string
    propC: {
      type: String.required: true
    },
    // Numbers, with default values
    propD: {
      type: Number.default: 100
    },
    // The default value of array/object should be returned by a factory function
    propE: {
      type: Object.default: function () {
        return { message: 'hello'}}},// Customize the validation function
    propF: {
      validator: function (value) {
        return value > 10}}}})Copy the code

The type of optional:

  • Sting

  • Number

  • Boolean

  • Function

  • Object

  • Array

  • The sample a

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Component validation example 1</title>
    </head>
    <body>
        <div id="app">
            <my-content :name="name" :age="age" :sex="sex"></my-content>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">Let the vm = new Vue ({el: '# app, data: {name: "xiao Ming, age: 18, sex:' male '}, the methods: {}, computed: {}, components:{ 'myContent':{ props:{ name:{ type:Number, required:true, }, age:{ type:Number, default:20, }, Sex :{type:String, default:' female '}}, template:'<div><span>{{name}}</span><span>{{age}}</span><span>{{sex}}</span></div>'}}})</script>
    </body>
</html>
Copy the code

Results:

Vue. Js: name = Number; vue = String; vue = Number;

The name attribute is also required to be passed, required: true, and the default value of sex is given. When we do not pass sex, the default value of sex in the child component is female. Therefore, this component verification greatly improves data security.

  • Example 2
<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Validation of components example two</title>
    </head>
    <body>
        <div id="app">
            <my-content name=Himalaya :size="8848" :is-boy="false" address="Tibet, China"></my-content>
        </div>
        <script type="text/template" id="template1">
            <div>Name:{{name}}Height:{{size}}Is it a boy?{{isBoy}}Location:{{address}}Weight:{{weight.ton}}One hundred million tons of</div>
        </script>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            Vue.component('myContent', {template:'#template1'.props: {name: {type:String./ / type
                        required:true.// Mandatory
                    },
                    size:Number.// specify an integer
                    isBoy:Boolean.// Specify a Boolean value
                    age: [Number.String].// Multiple types
                    address: {type:String.default:'China'.validator:function(value){
                            return value.indexOf('China') > =0}},weight: {type:Object.default:function(){
                            return {ton:999999999}}},}})let vm=new Vue({
                el:'#app'.data:{
                    
                },
                methods:{
                    
                },
                computed: {}})</script>
    </body>
</html>
Copy the code

Results:

The child component passes data to the parent

We know that the parent component is using props to pass data to the child component, but what if the child component wants to pass data back? That’s custom events! Each Vue instance implements the Events Interface, that is:

  • use$on(eventName)Listen for an event
  • use$emit(eventName)Triggering event

Let’s take a step-by-step look at passing data from a child to its parent. We’ll start with a very simple example that requires that when we change the count of the child, the count of the parent also needs to change.

  • The child components implement the functionality
<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>The child component passes data to the parent</title>
    </head>
    <body>
        <div id="app">
            <my-content :count="count"></my-content>Parent component count:<span>{{count}}</span>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app'.data: {count:1
                },
                methods:{
                    
                },
                computed:{
                    
                },
                components: {'myContent': {data(){
                            return{
                                ownCount:this.count
                            }
                        },
                        props: ['count'].template:{{ownCount}}'.methods: {handleClick(){
                                this.ownCount++; }}}}})</script>
    </body>
</html>
Copy the code

We pass the count value from the parent to the child, and the count value in the child changes when clicked, but this only changes the value of the child, not the count in the parent.

  • Pass information to the parent component

To send a message to the parent, we need the child to notify the parent, which then does the corresponding processing, and to notify the parent we need to use this.$emit(‘ event name ‘, value) for I.

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>The child component passes data to the parent</title>
    </head>
    <body>
        <div id="app">
            <my-content :count="count" @add="handleAdd"></my-content>Parent component count:<span>{{count}}</span>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app'.data: {count:1
                },
                methods: {handleAdd(count){
                        this.count=count; }},computed:{
                    
                },
                components: {'myContent': {data(){
                            return{
                                ownCount:this.count
                            }
                        },
                        props: ['count'].template:{{ownCount}}'.methods: {handleClick(){
                                this.ownCount+=10;
                                this.$emit('add'.this.ownCount); }}}}})</script>
    </body>
</html>
Copy the code

Results:

We add this.$emit() to notify the parent component when the child clicks the button, and then pass in the event that needs to be registered and the value that changes each time. The parent component registers the event and value that the child passes in, and then replaces the value from the parent component with that from the child.

  • Optimize the child component for passing information to its parent

We can actually let the parent control the change in count in the child, so let’s say that every time we increment the child by 10, let’s do a little example

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>The child component passes data to the parent</title>
    </head>
    <body>
        <div id="app">
            <my-content :count="count" @add="handleAdd" v-bind="info"></my-content>Parent component count:<span>{{count}}</span>
            <button @click="handleClick">Click on the</button>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app'.data: {count:1.info: {name:'male'.age:18}},methods: {handleAdd(count){
                        this.count=count;
                    },
                    handleClick(){
                        this.info.name='woman'}},computed:{
                    
                },
                components: {'myContent': {data(){
                            return{
                                ownCount:this.count
                            }
                        },
                        props: ['count'.'name'.'age'].template:Name: '< div > < span > {{name}} < / span > < br / > child component count: < span > {{ownCount}} < / span > < button @ click = "handleClick" > add < / button > < / div >'.methods: {handleClick(){
                                this.ownCount+=10;
                                this.$emit('add'.this.ownCount); }}}}})</script>
    </body>
</html>
Copy the code

Results:

When we click the button, we find that the name passed from the parent component to the child component changes, so we just change the value of count in the parent component, and the value of count in the child component changes as well

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>The child component passes data to the parent</title>
    </head>
    <body>
        <div id="app">
            <my-content :count="count" @add="hanldeAdd"></my-content>Count in the parent component<span>{{count}}</span>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app'.data: {count:1
                },
                methods: {hanldeAdd(count){
                        this.count+=count; }},computed:{
                    
                },
                components: {'myContent': {data(){
                            return{
                                //ownCount=this.count;}},props: ['count'].template:{{count}}< button@click ="handleClick">add'.methods: {handleClick(){
                                this.$emit('add'.10)}}}}})</script>
    </body>
</html>
Copy the code

Now that we are done with the simple communication between parent and child components, let’s make a task list to consolidate our knowledge of the previous communication between parent and child components

$emit(‘ event name ‘, value)

Task list

<! DOCTYPEhtml>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Task list</title>
    </head>
    <body>
        <div id="app">Task:<input type="text" v-model="newTask" @keyup.enter="addNew" placeholder="Please enter the task you want to complete." />
            <ul>
                <li is="todoImte" v-for="(item,index) of tasks" :title="item" @remove="removeItem(index)"></li>
            </ul>
        </div>
        <script src=".. /js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            Vue.component('todoImte', {props: ['title'].template:"<li>{{title}}<button @click='$emit("remove")'>X</button></li>"
            });
            let vm=new Vue({
                el:'#app'.data: {newTask:' '.tasks: ['Buy a book'.'Write a blog'.'Eat with a friend']},methods: {addNew(){
                        this.tasks.unshift(this.newTask);
                        this.newTask=' ';
                    },
                    removeItem(index){
                        if(confirm('Are you sure you want to delete? ')) {this.tasks.splice(index); }}},computed: {}})</script>
    </body>
</html>
Copy the code

Results:

This.$emit() tells the parent component to execute the corresponding method. In the task list, we can add or remove the task list, and there is no component communication involved. Second, when deleting the task list, the child component notifies the parent component that the task needs to be deleted, and then passes the index of the task to be deleted. The parent component deletes the task according to the index passed.

conclusion

The parent component passes information to the child component (via this.$emit), and the child component passes information to the parent component (via this.$emit). This is a simple tutorial, but I think this is just the beginning. In the next blog post we will cover component communication in VUe-CLI. After all, this is the focus and component communication is just getting started. Feel free to comment below and let’s talk.