Communication between components

Communication between components

The custom component needs to have a root element

Data of parent and child components cannot be shared

Components can have data, methods, computed…, but data must be a function

props pass data

The scope of the component instance is isolated, the parent component cannot directly use the data of the child component, nor can the child component directly use the data of the parent component

When the parent component uses the child component in the template, it can pass data to the child component

 <bbb money="2"></bbb>

Subcomponents can only be used after they are received through the props property

'bbb':{
    props:['money']
}

If the key name is '-' when the parent component passes the attribute to the child component, the child component is written as a small camel mode when it receives it

  <bbb clothes-logo='amani' clothes-price="16.58"></bbb>
  props:['clothesLogo','clothesPrice']   子组件模板中:{{clothesLogo}}

We can use v-bind to dynamically bind prop to the data of the parent component. Whenever the data of the parent component changes, the change will also be transmitted to the child component

Example 1:

<body>
    <div id="app"> 
        <father></father>
    </div>
    
    <template id="father">
        <div>
            <p>这是father组件!---> {{pMsg}}</p>
            <son :p-msg="pMsg"></son>
        </div>
    </template>
</body>


<script src="./base/vue.js"></script>
<script>
    // 父组件给子组件传递数据的时候,
    //子组件需要利用props的属性来确定自己的预期数据
    //中间有-   需要写出驼峰的形式来接收
    //如果儿子没有通过props属性接受传递过来的数据,则数据会以自定义属性的方式,放在儿子最外层的根元素上面
    

    //为什么组件中的data必须是一个函数返回对象的形式?
    //目的是让每一个实例可以维护一份被返回对象的独立的拷贝 (每个组件使用到的数据地址不一样)
    //内部必须要返回一个对象的写法,这样就可以保证每个组件里面用到的数据对象都是唯一的。

    //组件之间的作用域是相互独立的,组件的数据默认只能组件的模板里面使用。

    // var json = {pMsg:"hello father"}
    Vue.component("father",{
        template:"#father",
        data:function(){
            return {
                pMsg:"hello father"
            }
        },
        components:{
            son:{
                template:"<div>这是son子组件... {{pMsg}}</div>",
                props:["pMsg"] //接受父组件传递来的属性
            }
        }
    })

    let vm = new Vue({
        el: '#app',
        data:{
            msg:"hello app!"
        }
    })


 
</script>

Example 2:

example:

<body>
    <div id="app">
        <father></father>
    </div>
   
    <template id="father">
        <div>
            <input type="text" v-model="sky">
            <son :sky="sky"></son>
        </div>
    </template>
    <template id="son">
        <div>
            <input type="text" v-model="color">
            <div class="box" :style="{background:ownColor}"></div>
        </div>
    </template>
  
</body>
<script src="./base/vue.js"></script>

<script>
    //父组件可以通过v-bind来为子组件传递数据,当父组件的数据改变的时候,
    //子组件接收到的数据也会改变
    new Vue({
        el:"#app",
        components:{
            father:{
                template:"#father",
                data(){
                    return {
                        sky:"sky"
                    }
                },
                components:{ //声明父组件的子组件
                    son:{
                        template:"#son",
                        props:["sky"], //接收父组件传递来的数据  <son :sky="sky"></son>
                        data(){ //让每个组件拥有一份被返回对象的独立的拷贝
                            return {
                               color:"blue" 
                            }
                        },
                        computed:{
                            ownColor(){ //props和data里面的数据,必须要通过this才可以访问到
                                return this.sky + this.color
                            }
                        }
                    }
                }
            }
        }
    })
    
    

</script>

Insert picture description here

Unidirectional data flow

Prop is unidirectionally bound: when the properties of the parent component change, it will be passed to the child component, but the reverse will not. This is to prevent the child component from inadvertently modifying the state of the parent component to prevent the application data flow from becoming incomprehensible.

In addition, every time the parent component is updated, all props of the child component are updated to the latest values. This means that you should not change props inside subcomponents. If you do this, Vue will give a warning in the console.

Examples:

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <input type="text" v-model="message">
            <son :message="message"></son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>这是子组件</p>
            <input type="text" v-model="message">
        </div>
    </template>

</body>
<script src="./base/vue.js"></script>

<script>

    Vue.component("father",{
        template:"#father",
        data(){
            return {
                message:"hello world"
            }
        }
    })

    Vue.component("son",{
        template:"#son",
        props:["message"]
    })


    new Vue({
        el:"#app"
    })

</script>

Effect: The
Insert picture description here
correct method should rely on the application type of address delivery:

<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <input type="text" v-model="message.value">
            <son :message="message"></son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>这是子组件</p>
            <input type="text" v-model="message.value">
        </div>
    </template>

</body>
<script src="./base/vue.js"></script>

<script>

    //Vue/React单向数据流的体现:数据只能从父级组件流向子级组件
    //实现父子间的数据共享,依靠的就是应用类型的地址传递
    Vue.component("father",{
        template:"#father",
        data(){
            return {
                // message:"hello world"
                message:{  //子组件这边的话改的是里面的内容,没有对引用类型的地址进行更改。
                    value:"hello world"
                }
            }
        }
    })

    Vue.component("son",{
        template:"#son",
        props:["message"]
    })


    new Vue({
        el:"#app"
    })

</script>

effect:
Insert picture description here

Note that in JavaScript, objects and arrays are reference types, pointing to the same memory space. If prop is an object or array, changing it inside the child component will affect the state of the parent component. message: {val: ""}

prop verification

We can specify validation rules for the component's prop. If the incoming data does not meet the requirements, Vue will issue a warning. This is very useful for developing components for others to use

Verification is mainly divided into: type verification, mandatory verification, default setting, custom verification

props:{
    //类型验证:
    str:String,
    strs:[String,Number],
    //必传验证
    num:{
        type:Number,
        required:true
    },
    //默认数据
    bool:{
        type:Boolean,
        // default:true,
        default:function(){
            return true
        }
    },
    //自定义验证函数
    //props:["nums"]
    props:{
        nums:{
            type:Number, //[Number,String,Boolean,Array]
            validator: function (value) {
                return value %2 == 0
            }
        }
    }
}

When the parent component passes data to the child component, the child component does not receive, the data will be mounted on the root node of the child component template

slot

Vue provides a way to integrate the content of the parent component and the template of the child component: content distribution, through the slot slot to achieve

Insert picture description here

Anonymous slot

When using a child component in a parent component, write the content inside the child component tag. Can be used in the template of the subcomponent

<div id="app">
    <hello>
        <div>联通卡</div>
        <div>移动卡</div>
    </hello>
</div>

<template id="hello">
    <div>
    	<slot></slot>
    </div>
</template>
Named slot

We can set the slot attribute for multiple contents written by the parent component in the child component tag, and place the corresponding slot in the template of the child component by using the slot tag with the name attribute.

<div id="app">
    <hello>
        <div slot="a">联通卡</div>
        <div slot="b">移动卡</div>
    </hello>
</div>

<template id="hello">
    <div>
        <slot name="a"></slot>
        <slot name="b"></slot>
    </div>
</template>
New version 2.6+ supports v-slot

When v-slot is used, it needs to be in the template tag, everyone should pay attention to this point

<hello>
    <template v-slot:a>
        <div>联通卡</div>
    </template>
    <template v-slot:b>
        <div>移动卡</div>
    </template>
</hello>


<template id="hello">
    <div>
        <slot name="a" ></slot>
        <slot name="b" ></slot>
    </div>
</template>

Accept the named slot of props

<div id="app">
    <hello>
        <template v-slot:a>
        	<div>联通卡</div>
        </template>
        <template v-slot:b="info">
        	<div>移动卡 {{info.msgb}}</div>
        </template>
    </hello>
</div>

<template id="hello">
    <div>
        <slot name="a" ></slot>
        <slot name="b" :msgb="msg"></slot>
    </div>
</template>


 Vue.component("hello",{
     template:"#hello",
     data(){
         return {
         	msg:"你好"
         }
     }
 })

Communication between components

i. Passing values ​​from parent and child components ( props down, events up )

Insert picture description here
ii. Property verification props: {name: Number} Number, String, Boolean, Array, Object, Function, null (unlimited type)

iii. Ref

​ this.$refs.child

Insert picture description here

iv. Event bus

Var bus = new Vue ()

* Monitoring during the mounted life cycle

Insert picture description here

扩展
What is the use of v-once on components?

Render elements and components only once . Subsequent re-rendering, the element / component and all its child nodes will be treated as static content and skipped. This can be used to optimize update performance.

<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>

<!-- 有子元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>

<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>

<!-- `v-for` 指令-->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>
Can v-model be used for component communication?

Yes. Using the v-model instruction on the component is equivalent to binding the value attribute and monitoring input events.

transition

Vue provides a variety of different application transition effects when inserting, updating, or removing DOM.

Insert picture description here

Vue provides a transition component to help us achieve the transition effect, based on adding the corresponding class name for the dom at the specified time when the control element is hidden

And we only need to write the corresponding css style in these class names

In the transition of entering / leaving, there will be 6 class switches (v represents the value of the name attribute of the transition).

v-enter: defines the start state of the transition. It takes effect when the element is inserted and is removed in the next frame.

v-enter-active: defines the state of the transition. It plays a role in the entire transition of the element, takes effect when the element is inserted, and is removed after the transition / animation is completed. This class can be used to define the transition process time, delay and curve functions.

v-enter-to: Version 2.1.8 and above define the end state of the transition. It takes effect after the element is inserted into a frame (at the same time the v-enter is deleted), and is removed after the transition / animation is completed.

v-leave: Define the start state of leaving the transition. It takes effect when the leaving transition is triggered and is removed in the next frame.

v-leave-active: defines the state of the transition. It plays a role in the entire transition process of the element, takes effect immediately after leaving the transition is triggered, and is removed after the transition / animation is completed. This class can be used to define the transition process time, delay and curve functions.

v-leave-to: Version 2.1.8 and above define the end state of leaving the transition. It takes effect one frame after leaving the transition is triggered (at the same time v-leave is deleted), removed after the transition / animation is completed.

(1) Single element / component transition
  • css transition
  • css animation
  • Combined with animate.css animation library
<transition
    leave-active-class="animated fadeOut"
    enter-active-class="animated slideInLeft">
    <p v-if="isShow" class="box"></p>
</transition>

Examples:

    <!-- <link rel="stylesheet" href="./base/animate.css"> -->
<style>
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }

    /*abc-enter abc-enter-to*/
    .abc-enter{ /*进入开始的时候*/
        opacity: 0; 
    }
    .abc-enter-to{ /*进入过程结束的时候*/
        opacity: 1;
    }
    .abc-leave{ /*离开开始的时候*/
        opacity: 1;
    }
    .abc-leave-to{ /*离开过程结束的时候*/
        opacity: 0;
    }
    .abc-enter-active,.abc-leave-active{
        transition:all 3s;
    }
    
</style>
<body>
    <div id="app">
        <aaa></aaa>
    </div>


    <template id="aaa">
        <div>  
            <button @click="isShow=!isShow">toggle</button> 
            <transition name="abc">
                <div v-if="isShow" class="box"></div>
            </transition>
        </div>
    </template>
</body>
<script src="./base/vue.js"></script>

<script>

    //transition组件主要的作用就是可以给元素在某些特定的时刻添加上特定的类名
    //transition  template 不会被渲染出来
    Vue.component("aaa",{
        template:"#aaa",
        data(){
            return {
                isShow:false
            }
        }
    })

    new Vue({
        el:"#app"
    })

</script>
(2) Transition of multiple elements

When the elements with the same tag name are switched, you need to set a unique value through the key attribute to allow Vue to distinguish them, otherwise Vue will only replace the content inside the same tag for efficiency.

(3) List transition (set key)

Different from transition, it will be presented as a real element: the default is a span element. You can also change to other elements through the tag feature.

Provide a unique key attribute value

(4) Transition mode
in-out: 新元素先进行过渡,完成之后当前元素过渡离开

out-in: 当前元素先进行过渡,完成之后新元素过渡进入
<body style="overflow: hidden;">
    <div id="app">
        <button @click="type='aaa'">A</button>
        <button @click="type='bbb'">B</button>
        <transition
            enter-active-class="animated slideInLeft"
            leave-active-class="animated slideOutRight"
            mode="out-in"
        >
            <component :is="type"></component>
        </transition>
    </div>
</body>
<script src="./base/vue.js"></script>

<script>
    // 利用component标签来代替某一个组件,设置is属性为真正组件的名字
    //transition组件默认是进入和离开同时发生。
     //vue中对于transition提供了过渡模式
    //in-out:新元素先进行过渡,完成之后当前元素过渡离开
    //out-in:当前元素先进行过渡,完成之后新元素过渡进入。
    new Vue({
        el:"#app",
        data(){
            return {
                type:"aaa"
            }
        },
        components:{
            "aaa":{
                template:"<h1>AAAAAAAAAAAAAAA</h1>"
            },
            "bbb":{
                template: "<h1>BBBBBBBBBBBBBBB</h1>"
            }
        }
    })

</script>

effect:
Insert picture description here

Published 31 original articles · Liked4 · Visits 1001

Guess you like

Origin blog.csdn.net/qq_43942185/article/details/105060250