Vue2.0 Notes - Component 3

Communication between non-parent and child components

Communication is also required between two components that are not in a parent-child relationship. In simple scenarios, an empty Vue instance can be used as the event bus.

This sentence is the original words of the official website. Let's look at the description and examples of the official website. The method of communication is still the way of triggering and listening events , which is the same element that the child passes data to the parent component. That is, the $emit method and the $on method. Let's look at this example in detail.
Example:

//空的Vue实例
var emptyVm = new Vue();

var vm = new Vue({
    el:'#app',
    components:{
        'xiao-x':xiao_x,
        'xiao-y':xiao_y,
        'xiao-z':xiao_z
    }
});

var xiao_x={
    template:'<div><p>组件x:{{name}}</p><button @click="send">传递数据</button></div>',
    data:function(){
        return {
            name:'xiao',
            username:'yao'
        }
    },
    methods:{
        send(){
            emptyVm.$emit('xiao-x',this.name);
        }
    }
}
var xiao_y={
    template:'<div><p>组件y:{{age}}</p><button @click="send">传递数据</button></div>',
    data:function(){
        return {
            age:18
        }
    },
    methods:{
        send(){
            emptyVm.$emit('xiao-y',this.age);
        }
    }
}

var xiao_z={
    template:'<p>组件z:{{name}},{{age}}</p>',
    data:function(){
        return {
            name:'',
            age:''
        }
    }
}

<div id="app">
    <xiao-x></xiao-x>
    <xiao-y></xiao-y>
    <xiao-z></xiao-z>
</div>

Run the instance, we have all the preparations ready.
As for the templates of x and y, because I don't want to write such a high-length code, I just squeeze a little bit, and then click the button to trigger, and then monitor in z.

But it should be noted that you must listen first and then trigger before you can listen, otherwise of course you won't be able to receive it. So the monitoring must be before the trigger execution.

Code:

//x组件的事件方法
methods:{
    send(){
        emptyVm.$emit('xiao-x',this.name);
    }
}
//y的事件方法
methods:{
    send(){
        emptyVm.$emit('xiao-y',this.age);
    }
}
//z,在挂载组件模板实例之后就进行监听,所以需要用的生命周期钩子函数
mounted(){//模板挂载之后执行
    emptyVm.$on('xiao-x', function(name){
        vm.$children[2].name=name;
    });
    emptyVm.$on('xiao-y',age =>{
        this.age=age;
    });
}

Okay, so and so and so, and so on. Run the case and click the button to display it.

Next, explain the code:

  • First of all, the three components are pulled out and written separately. No problem, just declare a variable and assign the object to it.
  • Then there is the template problem. I squeezed a piece alone. If there is a lot of code, I should write it separately.
  • The button click event triggers these two events, give it parameters, write the event name on the other side, and add the callback function.
  • Then, if you want to monitor, it must be before the trigger, when is the earliest, after the mount, so the entire $on monitor, the callback function keeps up with the actual parameters, just fine.

Explain two questions:

1. That's why you want an empty Vue instance:

The main thing is to create an empty instance as a transit station, and then it can be implemented through the two functions of $emit and $on. Why, because these two methods are to trigger the current instance/listen to the events of the current instance, so you need a A common instance, so make an empty instance.

2. The callback problem of the $on event method:
For example, the first listener to name, if you directly this.name=name, do you think it will be wrong. There must be something wrong with writing it this way, but it will not report an error. It's just that the assignment is wrong, print this this, and find that this is an instance of emptyVm through the method of the data attribute in an instance , because this in the callback function is the new this, pointing to emptyVm. So you need to get the component instance of z to copy, so you can get the child instance through $children to assign value. Of course, this $children may be problematic, because the official said that it does not guarantee the order, and I am not too sure.
So you need to use the second, arrow way, which doesn't create a new this in the function.
The format of the arrow function is: argument list=>{//operation content}

slot content distribution

The original meaning is, the slot, the meaning of the slot.
What's the use, let's take a look at the following example.
Example:

<div id="app">
    <my-xiao></my-xiao>
</div>

<template id="xiao">
    <div>
        {{arr.join(' ')}}<br/>
    </div>
</template>

components:{
    'my-xiao':{
        template:'#xiao',
        data:function(){
            return {
                name:'xiao',
                arr:['what','are','you','doing']
            }
        }
    }
}

This example doesn't look very good, but you will find that the <my-xiao> tag is empty. Do you want to add some text, but no matter how you add it, it will be replaced by the template.
1.
At this time, it is time to use the slot. It uses the <slot></slot> tag to display it. Just put it in the template as any value. It should be noted that the slot is also a component. , built-in .

<div id="app">
    <my-xiao>空空如也 —— 任然</my-xiao>
</div>

<template id="xiao">
    <div>
        {{arr.join(' ')}}<br/>
        <slot></slot><!-- 代替标签内的文字 -->
    </div>
</template>
//或者,当内有内容时显示默认的值
<template id="xiao">
    <div>
        {{arr.join(' ')}}<br/>
        <slot>只有在没有要分发的内容时才会显示。</slot>
    </div>
</template>

2. You can add any code in the <my-xiao> tag, such as the commonly used ul and li. It will also be displayed.

<my-xiao>
        <ul>
            <li>111</li>
            <li>222</li>
            <li>333</li>
            <li>444</li>
        </ul>
</my-xiao>

3. You can specify where an element is displayed in the template through <slot></slot>

<my-xiao>
    <ul slot="one">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>
    <p slot="QianSiXian">你褴褛我彩绘 并肩行过山与水</p>
</my-xiao>

<template id="xiao">
    <div>
        <slot name="QianSiXian"></slot>
        {{arr.join(' ')}}<br/>
        <slot name="one"></slot>
    </div>
</template>

You can set the slot attribute for the element and set a value at will, just specify the name by name in the slot tag.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324738164&siteId=291194637