Vue.js-data transfer between components (1)

The relationship structure of page components is a tree structure composed of many components. There are two relationships between components: parent-child relationship and non-parent-child relationship. Almost any type of application interface can be abstracted as a component tree.

The parent-child relationship between components refers to the relationship between two components directly connected by a line in the component tree, and the remaining relationships are all classified as non-parent-child relationships.

1. Data transfer between parent and child components

1. The father passes data to the child

  • When the parent component calls the child component, the data to be passed is bound to the child component label in the manner of attribute binding.
  • In the child component object, use the props option to declare the acquired data to intercept the binding properties, that is, to receive the data from the parent component.

Method: attribute binding + data interception

First, define the parent component hello and the child component world. The data variable names in the parent component are msg, name, age, and the variable names in the child component are message, name, age. When calling the child component in the parent component hello, use the method of ": child component data="parent component data"" to bind the properties.

<template id="hello">
        <div>
            <h3>我是hello父组件</h3>  
            <h3>访问自己的数据:{
   
   {msg}},{
   
   {name}},{
   
   {age}}</h3> 
            <hr>
            <!-- 属性绑定方式 -->
            <my-world :message="msg" :name="name" :age="age"></my-world>
        </div>
 </template>

Then, declare the acquired data in the props option in the sub-component object to perform property interception.

   components:{
        'my-hello':{
            template:'#hello',
       		data(){
                return {
                    msg:xx,
                    name:xx,
                    age:xx,
                }
            },
            components:{
                'my-world':{
                    template:'#world',
                    // props: ['message','name','age'] // 简单的字符串数组
                    props:{
                        message:{
                            type:String
                        },
                        name:{
                            type:String,
                            required:true,
                        },
                        age:{
                            type:Number,
                            default:18,
                            validator:function(value){ // 参数value为传递的数据
                                if(value<0 || value>100){
                                    alert('年龄无效');
                                }
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }

2. The child passes data to the parent

When the parent component calls the child component, it listens to the custom event triggered by the child component, that is, the parent component observes the child component at all times to see if it has data to pass, and defines a callback method in the parent component object to receive data.

Method: event monitoring + event triggering

Use the form of $emit (event name, data) in the child component object to trigger a custom event and pass data to the parent component.

<template id="hello">
        <div>
            <h3>我是hello父组件</h3>  
            <h3>访问自己的数据:{
   
   {msg}},{
   
   {name}},{
   
   {age}}</h3> 
            <hr>
            
            <!-- 监听子组件触发的自定义事件 -->
            <my-world @e-world="get" @update-sex="updateSex"></my-world>
        </div>
 </template>

When the parent component hello calls the child component, the custom events e-world and update-sex (name custom) are triggered. In the child component, the data is passed in the way of this.$emit('e-world',this.sex,this.height), and the method get(sex,height) is defined in the parent component to receive the data.

new Vue({
        el:'#app',
        // 提供要向后代组件传递的数据
        provide:{
            hobby:'game',
            weight:150
        },
        components:{
            'my-hello':{ // 父组件
                template:'#hello',
                data(){
                    return {
                        sex:null,
                        height:null
                    }
                },
                methods: {
                    get(sex,height){
                        // console.log(sex,height);
                        this.sex = sex;
                        this.height = height;
                    },
                    updateSex(sex){
                        this.sex = sex;
                    }
           
                },
                components:{
                    'my-world':{ // 子组件
                        template:'#world',
                        data(){
                            return {
                                sex:'male',
                                height:180.5
                            }
                        },
                        methods: {
                            send(){
                                // 使用$emit()触发自定义事件
                                this.$emit('e-world',this.sex,this.height);
                            }
                        },
                        mounted() {
                            // 当组件挂载完成后,主动将数据传递给父组件
                            this.$emit('e-world',this.sex,this.height);
                        },
                        watch: { // 监视子组件数据的变化,当数据发生变化时触发$emit更新父组件中的数										据
                            sex:function(newValue){
                                this.$emit('update-sex',newValue);
                            }
                        },
                    }
                }
            }
        });

Two, non-parent and child components pass data

1. Ancestors pass data to descendants

Ancestors pass data to descendants using dependency injection (dependency injection):

  • Use provide/inject to achieve
  • Use the provide option in the ancestor component to provide a data object that can be injected into its descendants
  • Use the inject option in the descendant component to inject a string array to receive data
new Vue({
   // 祖先组件使用provide
   provide:{
            hobby:'game',
            weight:150
    },
    components:{
        components:{
    		// 后代组件使用inject接收祖先组件传递的数据
            inject:['hobby']
		}
    }
    	
});

2. Transfer data between adjacent components

The communication between non-parent and child components can be realized through the Central Event Bus , also known as the Event Center. In fact, it is to use a Vue instance that can be accessed in all components, and use it to monitor events and trigger events. The grandfather above can also use the central event bus to pass data to future generations.

Method: event monitoring + event triggering

Different from the child component passing data to the parent component, the use of the central event bus generally uses the root component root to monitor and trigger events.

Define component A, pass the data name to component C, use this.$root.$emit('data-a',this.name) to trigger a custom event and send data.

Vue.component('CompA',{
        template:'#a',
        data(){
            return {
                name:'tom'
            }
        },
        beforeMount() {
            console.log('组件A。。。。。beforeMount');
        },
        mounted() {
            console.log('组件A。。。。。mounted');
            // console.log(this.$root); // 获取根实例Root
            this.$root.$emit('data-a',this.name);
        },
        methods: {
            send(){
                // 触发根实例上的自定义事件,发送数据
                this.$root.$emit('data-a',this.name);
            }
        },
    });

In component C, use this.$root.$on('data-a',name =>{ this.name = name}) to monitor custom events and receive data. Note that the arrow function must be used to receive the name here. If the arrow function is not used, the this of this.name will represent the root instance, which is the event source. The arrow function is used to represent this component C.

Vue.component('CompC',{
        template:'#c',
        data(){
            return {
                name:null,
                age:null
            }
        },
        beforeMount() {
            console.log('组件C。。。。。beforeMount');
            // 监听根实例上的自定义事件,接收数据
            this.$root.$on('data-a',name => {
                // console.log(name);
                // this.name = name;
                // console.log(this); // 如果不使用箭头函数,则此处的this表示Root实例,表示事件源
                this.name = name;
            });
            this.$root.$on('data-b',age => {
                this.age = age;
            });
        },
    });

The Central Event Bus method of implementing data transfer is not only suitable for non-parent-child components, but also between parent-child components. But we generally don't do this. When using Event Bus, the event is bound to the root component so that other components can also get data.

Guess you like

Origin blog.csdn.net/weixin_39006917/article/details/108252857