• 组件间数据传递


    一、 组件间数据传递

      1、 父子组件之间的规则

        1、 在一个组件内部定义另一个组件,称为父子组件

        2、子组件只能在父组件内部使用

        3、默认情况下,子组件无法访问父组件中的数据,父组件也无法访问子组件中的数据,每个组件实例的作用域是独立的

      2、组件间数据传递 (通信)

        1、子组件访问父组件的数据

          步骤1:父组件在调用子组件时,绑定子组件想要获取的父组件中的数据

          步骤2:在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据   

        2、总结:

          父组件通过props向下传递数据给子组件

          组件中的数据共有三种形式:data、props、computed

        3、父组件访问子组件的数据

          在子组件中使用vm.$emit(事件名,数据)触发一个自定义事件,事件名自定义

          父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据  。

        4、总结

          子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件

        5、示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>父子组件及组件间数据传递</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
        <div id="itany">
            <my-hello></my-hello>
        </div>
        
        <template id="hello">
            <div>
                <h3>我是hello父组件</h3>
                <h3>访问自己的数据:{{msg}},{{name}},{{age}},{{user.username}}</h3>
                <h3>访问子组件的数据:{{sex}},{{height}}</h3>
                <hr>
    
                <my-world :message="msg" :name="name" :age="age" @e-world="getData"></my-world>//子组件只能在父组件中使用,不能跨辈分使用,且父组件在调用子组件时,绑定子组件想要获取的父组件中的数据,即父组件给子组件传值
            </div>
        </template>
    
        <template id="world">
            <div>
                <h4>我是world子组件</h4>
                <h4>访问父组件中的数据:{{message}},{{name}},{{age}},{{user.username}}</h4>//子组件不能直接的访问父组件中的数据,组件之间数据都是独立的,但是通过props就可以了
                <h4>访问自己的数据:{{sex}},{{height}}</h4>
                <button @click="send">将子组件的数据向上传递给父组件</button>//父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据  。
            </div>
        </template>
    
        <script>
            var vm=new Vue({ //根组件
                el:'#itany',
                components:{
                    'my-hello':{  //父组件
                        methods:{
                            getData(sex,height){
                                this.sex=sex;
                                this.height=height;
                            }
                        },
                        data(){
                            return {
                                msg:'网博',
                                name:'tom',
                                age:23,
                                user:{id:9527,username:'唐伯虎'},
                                sex:'',
                                height:''
                            }
                        },
                        template:'#hello',
                        components:{
                            'my-world':{ //子组件
                                data(){
                                    return {
                                        sex:'male',
                                        height:180.5
                                    }
                                },
                                template:'#world',
                                // props:['message','name','age','user'] //简单的字符串数组,接受父组件传递过来的数据
                                props:{ //也可以是对象,允许配置高级设置,如类型判断、数据校验、设置默认值
                                    message:String,//指定传递过来的message必须是个字符串,类型限制,限制条件可以是字面量
                                    name:{
                                        type:String,  //指定类型和数据校验,限制条件可以是对象,required:true表示必须要有name值,
                                        required:true
                                    },
                                    age:{
                                        type:Number, 
                                        default:18,    //自定义默认值
                                        validator:function(value){    //自定义校验规则,年龄必须大于0
                                            return value>=0;        
                                        }
                                    },
                                    user:{
                                        type:Object,
                                        default:function(){ //对象或数组的默认值必须使用函数的形式来返回
                                            return {id:3306,username:'秋香'};
                                        }
                                    }
                                },
                                methods:{
                                    send(){
                                        // console.log(this);  //此处的this表示当前子组件实例
                                        this.$emit('e-world',this.sex,this.height); //使用$emit()触发一个事件,子组件发送数据给父组件
                                    }
                                }
                            }
                        }
                    }
                }
            });    
        </script>
    </body>
    </html>
    View Code

    二、单向数据流

      1、props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来,即父组件修改自身数据影响子组件,但子组件不能修改父组件数据。

      2、不允许子组件直接修改父组件中的数据,否则报错。

        解决方式:

          方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据

            方式2:如果子组件想修改数据并且同步更新到父组件,两个方法:

            a.使用.sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持)需要显式地触发一个更新事件

            b.可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐

      3、示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>单向数据流</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
        <div id="itany">
            <h2>父组件:{{name}}</h2>
            <input type="text" v-model="name">
            <h2>父组件:{{user.age}}</h2>
    
            <hr>
    
            <my-hello :name.sync="name" :user="user"></my-hello>//父组件给子组件绑定这个name属性,如果子组件的name发送改变允许父组件的name也随之发送改变
        </div>
        
        <template id="hello">
            <div>
                <h3>子组件:{{name}}</h3>
                <h3>子组件:{{user.age}}</h3>
                <button @click="change">修改数据</button>
            </div>
        </template>
    
        <script>
            var vm=new Vue({ //父组件
                el:'#itany',
                data:{
                    name:'tom',
                    user:{  //包装成一个对象
                        name:'zhangsan',
                        age:24
                    }
                },
                components:{
                    'my-hello':{ //子组件
                        template:'#hello',
                        props:['name','user'],
                        data(){
                            return {
                                username:this.name //方式1:将数据存入另一个变量中再操作
                            }
                        },
                        methods:{
                            change(){
                                // this.username='alice';
                                // this.name='alice';
                                // this.$emit('update:name','alice'); //方式2:a.使用.sync,需要显式地触发一个更新事件
                                this.user.age=18;
                            }
                        }
                    }
                }
            });    
        </script>
    </body>
    </html>
    View Code



    三、非父子组件间的通信

      1、通信方法:非父子组件间的通信,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件

        2、通信流程:

        1、 var Event=new Vue(); //空的Vue实例作为中央事件总线

        2、Event.$emit(事件名,数据);//触发事件

        3、Event.$on(事件名,data => {});//监听事件

      3、示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>非父子组件间的通信</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
        <div id="itany">
            <my-a></my-a>
            <my-b></my-b>
            <my-c></my-c>
        </div>
    
        <template id="a">
            <div>
                <h3>A组件:{{name}}</h3>
                <button @click="send">将数据发送给C组件</button>
            </div>
        </template>
    
        <template id="b">
            <div>
                <h3>B组件:{{age}}</h3>
                <button @click="send">将数组发送给C组件</button>
            </div>
        </template>
        
        <template id="c">
            <div>
                <h3>C组件:{{name}},{{age}}</h3>
            </div>
        </template>
    
        <script>
            //定义一个空的Vue实例
            var Event=new Vue();
            //A,B,C表示的是对象,注意对象和组件之间的区别
            var A={
                template:'#a',
                data(){
                    return {
                        name:'tom'
                    }
                },
                methods:{
                    send(){
                        Event.$emit('data-a',this.name);//$emit用来触发事件,
                    }
                }
            }
            var B={
                template:'#b',
                data(){
                    return {
                        age:20
                    }
                },
                methods:{
                    send(){
                        Event.$emit('data-b',this.age);
                    }
                }
            }
            var C={
                template:'#c',
                data(){
                    return {
                        name:'',//初始化数据
                        age:''
                    }
                },
                mounted(){ //在模板编译完成后执行
                    Event.$on('data-a',name => {//$on用来监听事件。=>表示的是回调函数,在回调函数内部不会产生新的this,和普通function函数有本质区别,尤其是在this上的区别
                        this.name=name;
                        // console.log(this);
                    });
    
                    Event.$on('data-b',age => {
                        this.age=age;
                    });
                }
            }
    
            var vm=new Vue({
                el:'#itany',
                components:{
                    'my-a':A, //本质就是一个对象
                    'my-b':B,
                    'my-c':C
                }
            });    
        </script>
    </body>
    </html>
    View Code

    四、 slot内容分发

       1、本意:位置、槽

       2、作用:用来获取组件中的原内容

      3、示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>slot内容分发</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
        <div id="itany">
            <!-- <my-hello>wbs17022</my-hello> -->/单一slot
            <my-hello>
                <ul slot="s1"> //多个slot
                    <li>aaa</li>
                    <li>bbb</li>
                    <li>ccc</li>
                </ul>
                <ol slot="s2">
                    <li>111</li>
                    <li>222</li>
                    <li>333</li>
                </ol>
            </my-hello>
        </div>
    
        <template id="hello">
            <div>
                <slot name="s2"></slot>//多slot用法
                <h3>welcome to itany</h3>
                <!-- <slot>如果没有原内容,则显示该内容</slot> -->单slot用法
                <slot name="s1"></slot>
            </div>
        </template>
    
        <script>
    
            var vm=new Vue({
                el:'#itany',
                components:{
                    'my-hello':{
                        template:'#hello'
                    }
                }
            });    
        </script>
    </body>
    </html>
    View Code
  • 相关阅读:
    AcWing 838. 堆排序
    AcWing 240. 食物链
    Sublime下载地址
    【转载】Java 8 Optional的正确姿势
    【SpringBoot】通过server.servlet.context-path设置应用的上下文路径
    【java/Lamda】List.stream().collect(Collectors.toMap(Emp::getId, a->a,(k1,k2)->k2))的意义
    Prometheus修改数据保留时间
    Atitit BLE 协议栈 艾提拉总结 目录 1. ——关于BLE的一些基本概念——
    Atitit 高并发设计实践 艾提拉著 目录 1. 并发的实现俩中模式 并发角度来看 基于事件触发vs线程的 1 2. 负载均衡 1 2.1. 云服务模型paas caas faas+http
    Atitit 锁的不同层级 app锁 vm锁 os锁 硬件锁 目录 1. 在硬件层面,CPU提供了原子操作、关中断、锁内存总线的机制 1 1.1. test and set指令 1 1.2. 锁内
  • 原文地址:https://www.cnblogs.com/xuanan/p/7858384.html
Copyright © 2020-2023  润新知