Vue组件-父子组件传递数据

2020-07-28  本文已影响0人  Angel_6c4e

一.父子组件

1.什么是父子组件?
 就是在组件中又定义了其他组件
 其实局部组件就是最简单的子组件,因为把Vue实例看做一个大的父组件
 在Vue中的局部组件就相当于大组件中的小组件,这就是最简单的局部组件

2.如何定义其他父子组件
 自定义组件可以使用data,可以使用methods,当然自定义组件还可以使用components
 如果把创建的Vue实例对象当做父组件,那么在Vue实例对象中创建的局部组件components就是子组件;如果在局部组件中再次创建components就是孙子组件,此时的Vue实例对象就相当于爷爷组件,在Vue实例对象中创建的局部组件components就是父组件;

<div id="app">
    <abc></abc>
</div>

<template id="father">
    <div>
        <p>我是父组件</p>
        <def></def>
    </div>
</template>
<template id="son">
    <div>
        <p>我是子组件</p>
    </div>
</template>

<script>
    //创建Vue的实例对象
    let vue = new Vue({
        el:"#app",
        data:{ },
        methods:{},
        computed:{  },
        //专门用于定义局部组件
        components:{
            "abc":{
                template: "#father",
                components:{
                    "def":{
                        template: "#son"
                    }
                }
            }
        }
    });
</script>

二.父组件向子组件传递数据(data)

1.如何传递数据
 1.1在父组件中通过v-bind传递数据
   传递格式 v-bind:自定义接收名称 = "要传递数据"
 1.2在子组件中通过props接收数据
    接收格式 props: ["自定义接收名称"]

<div id="app">
   <father></father>
</div>
<template id="father">
   <div>
       <!--注意点: 组件是可以使用自己的数据的-->
       <p>{{name}}</p>
       <p>{{age}}</p>
       <!--这里将父组件的name通过parentname传递给了子组件-->
       <son :parentname="name" :abc="age"></son>
   </div>
</template>
<template id="son">
   <div>
       <!--这里通过parentname使用了父组件传递过来的数据-->
       <p>{{parentname}}</p>
       <p>{{abc}}</p>
   </div>
</template>
<script>
// 父组件
   Vue.component("father", {
       template: "#father",
       data: function(){
         return {
             name: "yaxi",
             age: 20
         }
       },
       // 子组件
       components: {
           "son": {
               template: "#son",
               // 这里通过parentname接收了父组件传递过来的数据
               props: ["parentname", "abc"]
           }
       }
   });
   let vue = new Vue({
       el: '#app',
       data: { },
       methods: { },
       computed: { },
       components: {}
   });
</script>

三.父组件向子组件传递方法(methods)

1.如何传递方法
 1.1在父组件中通过v-on传递方法
   传递格式 v-on:自定义接收名称 = "要传递方法"
 1.2在子组件中自定义一个方法
 1.3在自定义方法中通过 this.$emit('自定义接收名称');触发传递过来的方法

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
        <button @click="say">我是按钮</button>
        <!--这里通过parentsay将父组件的say方法传递给子组件-->
        <son @parentsay="say"></son>
    </div>
</template>
<template id="son">
    <div>
        <button @click="sonFn">我是按钮</button>
    </div>
</template>

<script>
    // 父组件
    Vue.component("father", {
        template: "#father",
        methods: {
            say(){
                alert("2541873074@qq.com")
            }
        },
        // 子组件
        components: {
            "son": {
                template: "#son",
                methods:{
                    sonFn(){
                      this.$emit("parentsay");
                    }
                }
            }
        }
    });

    let vue = new Vue({
        el: '#app',
        data: {   },
        methods: { },
        computed: { },
        components: {  }
    });
</script>

四.子组件向父组件传递数据(data)

1.如何将子组件数据传递给父组件
 父组件先传递一个方法给子组件,子组件调用这个方法的时候传递参数给父组件,传递参数就是传递数据

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
        <button @click="say">我是按钮</button>
        <!--这里通过parentsay将父组件的say方法传递给子组件-->
        <son @parentsay="say"></son>
    </div>
</template>
<template id="son">
    <div>
        <button @click="sonFn">我是按钮</button>
    </div>
</template>

<script>
    // 父组件
    Vue.component("father", {
        template: "#father",
        methods: {
            //data:接受从子组件传递的参数
            say(data){
                console.log(data);
            }
        },
        // 子组件
        components: {
            "son": {
                template: "#son",
                methods:{
                    sonFn(){
                        /*
                         this.$emit的第一个参数:需要调用的函数名称
                         this.$emit的后续的参数:给调用的函数传递的参数
                         */
                        this.$emit("parentsay","鱿小鱼");
                    }
                }
            }
        }
    });
 
    let vue = new Vue({
        el: '#app',
        data: {},
        methods: {},
        computed: {},
        components: {}
    });
</script>

五.组件中的命名注意点

1.注册组件的时候使用“驼峰命名”,使用组建的时候转换成“短横线分割命名”
例如:注册时:myFather -- 使用时:my-father
2.在传递参数的时候如果想使用“驼峰名称”,那么就必须写“短横线分割命名”
例如:传递时:parent-name="name" -- 接受时:props["parentName"]
3.在传递方法的时候不同使用“驼峰名称”,只能使用“短横线分割命名”
例如:传递时:@parent-say="say" -> 子组件的methods中:this.$emit("parent-say");

六.数据和方法的多级传递

在Vue中如果儿子想使用爷爷的数据,必须一层一层向下传递
在Vue中如果儿子想使用爷爷的方法,必须一层一层向下传递

<div id="app">
    <grandfather></grandfather>
</div>
<template id="grandfather">
    <div>
        <p>{{name}}</p>
        <button @click="say">我是按钮</button>
        <father :gfname="name" @gfsay="say"></father>
    </div>
</template>
<template id="father">
    <div>
        <p>{{gfname}}</p>
        <button @click="fatherFn">我是按钮</button>
        <son :fname="gfname" @fsay="fatherFn"></son>
    </div>
</template>
<template id="son">
    <div>
        <p>{{fname}}</p>
        <button @click="sonFn">我是按钮</button>
    </div>
</template>

<script>
    // 爷爷组件
    Vue.component("grandfather", {
        template: "#grandfather",
        data:function(){
            return{
                name:"yaxi"
            }
        },
        methods:{
            say(){
                console.log("我是爷爷的方法");
            }
        },
        // 爸爸组件
        components: {
            "father": {
                template: "#father",
                props:["gfname"],
                methods:{
                    fatherFn(){
                       this.$emit("gfsay");
                    }
                },
                //儿子组件
                components:{
                    "son":{
                        template:"#son",
                        props:["fname"],
                        methods:{
                            sonFn(){
                                this.$emit("fsay");
                            }
                        }
                    }
                }
            }
        }
    });

    let vue = new Vue({
        el: '#app',
        data: {},
        methods: {},
        computed: { },
        components: {}
    });
</script>

注意点:
1.如果想要在子组件中使用父组件中的数据,那么必须通过父组件传递
2.如果想要在子组件中使用祖先组件中的数据, 那么就必须一 层一 层的传递
3.兄弟组件之间不能直接传递数据,如果兄弟组件之间想要传递数据,那么就必须借助父组件
虽然通过借助父组件能够实现兄弟组件之间的数据传递,但是这种方式非常的复杂,非常的不推荐
那么当前在企业开发中我们遇到了两个问题:
1.如果想要在子组件中使用祖先组件中的数据,那么就必须一层一层的传递(非常麻烦)
2.兄弟组件之间不能直接传递数据,如果兄弟组件之间想要传递数据,那么就必须借助父组件(非常麻烦)
解决方案:使用Vuex


七.匿名插槽和具名插槽

1.默认情况下是不能在使用子组件的时候,给子组件动态添加内容,如果想在使用子组的时候,给子组件动态添加内容,那么就必须使用插槽
 <slot></slot>标签就是插槽,以后使用者可以根据自己的需求来填补;
注意点
  插槽可以指定默认数据,如果使用者没有填补插槽,那么就会显示默认数据,如果使用者填补了这个插槽,就会利用使用者填补的数据替换整个默认数据;
  插槽可以指定名称,默认情况下如果没有指定名称,我们就称之为匿名函数;
  默认情况下有多少个匿名插槽,我们填充的数据就会被拷贝多少份,导致了所有插槽中填充的内容都是一样的

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
        <!--需求:在使用子组件的时候给子组件动态的添加一下内容-->
       <son>
            <div>我是追加的内容1</div>
            <div>我是追加的内容2</div>
            <div>我是追加的内容3</div>
       </son>
    </div>
</template>
<template id="son">
    <div>
        <div>我是头部</div>
        <!--匿名插槽的特点:有多少个匿名插槽,填充的数据就会拷贝几份
                            虽然我们可以指定多个匿名插槽,但企业开发中推进只写一个匿名插槽
        -->
        <slot>我是默认数据</slot>
        <div>我是底部</div>
    </div>
</template>
效果:

2.如果我们想给不同的插槽中填充不同的内容怎么办呢?  这个时候就可以使用具名插槽
具名插槽的使用:
  通过插槽的name属性给插槽指定名称
  在使用时可以通过slot=" name"方式,指定当前内容用于替换哪个插槽
  注意点:如果没有指定要替换哪个插槽中的内容,则不会被替换
  注意点: slot 属性在Vue2.6中已经被废弃,Vue2. 6之后使用v-slot指令替代slot属性

div id="app">
    <father></father>
</div>
<template id="father">
    <div>
       <son>
            <!--通过slot属性告诉Vue,当前的内容是要填充到哪一个插槽中的-->
            <div slot="one">我是追加的内容1</div>
            <div slot="one">我是追加的内容111</div>
            <div slot="two">我是追加的内容2</div>
            <div slot="two">我是追加的内容222</div>
       </son>
    </div>
</template>
<template id="son">
    <div>
        <div>我是头部</div>
        <slot name="one">我是one默认数据</slot>
        <slot name="two">我是two默认数据</slot>
        <div>我是底部</div>
    </div>
</template>
效果:

八.v-slot指令和作用域插槽

1.什么是v-slot指令?
  v-slot指令是Vue2. 6中用于替代slot属性的一个指令
  在Vue2.6之前,我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽
  从Vue2.6开始,我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽
  注意点: v-slot指令只能用在template标签上,#可以使用#号替代v-slot指令

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
       <son>
           <template #one>
               <div>我是追加的内容1</div>
               <div>我是追加的内容11</div>
           </template>
           <template #two>
               <div>我是追加的内容2</div>
               <div>我是追加的内容22</div>
           </template>
       </son>
    </div>
</template>
<template id="son">
    <div>
        <div>我是头部</div>
        <slot name="one">我是one默认数据</slot>
        <slot name="two">我是two默认数据</slot>
        <div>我是底部</div>
    </div>
</template>
效果:

2..什么是作用域插槽
  作用域插槽就是带数据的插槽就是让父组件在填充子组件插槽内容时也能使用子组件的数据
3.如何使用作用域插槽
  3.1在slot中通过v-bind:数据名称='数据名称”方式暴露数据
  3.2在父组件中通过<template slot-scope=" 作用域名称">接收数据
  3.2.1在父组件中还可以通过<template v-slot:插槽名称=" 作用域名称">接收数据匿名插槽的名称是default
  3.2.2在父组件中也可以通过<template #插槽名称=" 作用域名称">接收数据在子组件中指定插槽名称 name="插槽名称"
4.作用域插槽的应用场景:子组件提供数据,父组件决定如何渲染

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
       <son>
          <!--slot-scope="abc" 接受子组件插槽暴露的数据-->
          <!--
                <template slot-scope="abc">
                    <li v-for="(value,index) in abc.names">{{value}}</li>
                </template>
            -->
            <!--
               <template v-slot:default="abc">
                    <li v-for="(value,index) in abc.names">{{value}}</li>
               </template>
            -->
           <template #one="abc">
               <li v-for="(value, index) in abc.names">{{value}}</li>
           </template>
       </son>
    </div>
</template>
<template id="son">
    <div>
        <div>我是头部{{name}}</div>
        <!--将子组件中的names通过names暴露给父组件-->
        <slot name="one" v-bind:names="names">我是默认数据{{names}}</slot>
        <div>我是底部</div>
    </div>
</template>
<script>
    // 父组件
    Vue.component("father", {
        template: "#father",
        //子组件
        components: {
            "son": {
                template: "#son",
                data:function () {
                    return{
                        names:["zs","ls","ww","zl"]
                    }
                }
            }
        }
    });
 let vue = new Vue({
        el: '#app',
});
</script>
效果:
上一篇下一篇

猜你喜欢

热点阅读