Vue 父组件和子组件

目录

1、父组件和子组件

2、父子组件通信 — 父传子props

3、父子组件通信 — 子传父(自定义事件)

4、为什么组件 data 必须是函数


1、父组件和子组件

组件树可以显示出组件和组件之间存在的层级关系,而其中一种非常重要的关系就是父子组件的关系,下面看一下代码是如何形成这种层级关系的:

<div id="app">
    <cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
    const myComponent1 = Vue.extend({        //创建第一个组件构造器(子组件)
        template:`
            <div>
                <h2>组件标题1</h2>
                <p>我是组件中的一个段落内容,嘻嘻</p>
            </div>`
    });
    const myComponent2 = Vue.extend({       //创建第二个组件构造器(父组件)
        template:`
            <div>
                <h2>组件标题2</h2>
                <p>我是组件中的一个段落内容,嘿嘿</p>
                <cpn1></cpn1>               //组件中使用组件,形成父子组件
            </div>`,
        components:{                        //组件2中注册局部组件1
            cpn1:myComponent1
        }
    });
    let vm = new Vue({
        el:'app'
        components:{                        //注册私有组件,仅可以在当前vue实例下使用
            cpn2:myComponent2 
        }
    })
</script>

2、父子组件通信 — 父传子props

子组件是不能直接引用父组件或者 Vue 实例的数据的。但是在开发中,往往一些数据确实需要从上层传递下层:比如在一个页面中,我们从服务器请求到了很多的数据,其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示,这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

如何进行父子组件间的通信?Vue 官方提到:通过 props 向子组件传递数据,通过事件向父组件发送消息

下面看一下父子组件中传递是怎样传递 data 数据的, vue 充当父组件

<div id="app">
    <cpn v-bind:childmovies="movies"></cpn>    //将父组件的数据绑定给子组件,注意v-bind不支持驼峰标识
</div>
<template id="cpn">
    <div>
        <ul><li v-for="item in childmovies"></li></ul>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template:'#cpn',
        //props:['childmovies'],    //通过props声明用来接收父组件要传递给子组件的变量
        props:{
            childmovies:Array,    //类型限制
            default:(){           //可以声明默认值
                return []
            }
        }
        data(){
            return {}
        }
    }
    let vm = new Vue({
        el:'app',
        data:{
            movies:['111','222','333']
        },
        components:{
            cpn:cpn     //可以直接写成 cpn
        }
    })
</script>

说明:将vue实例看成父组件,vue 实例中声明的 components 看成子组件,父子组件中都有 data 数据,注意子组件中的data只能用方法,并返回一个对象。如果在HTML中引用子组件,而且子组件要获取父组件data中的数据,那要怎么做呢?一共分为两个步骤: 

第一步:在子组件里声明 props:['childmovies'] 用来接收父组件中要传递给子组件的 message 变量

第二步:在组件占位符上写数据绑定:<cpn v-bind:childmovies="message"></cpn>

3、父子组件通信 — 子传父(自定义事件)

<div id="app">
    <cpn @itemclick="cpnClick"></cpn>    //这里不支持驼峰标识,vue-cli中支持
</div>
<template>
    <div>
        <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template:'#cpn',
        data(){
            reutrn {
                categories:{
                    {id:'111',name:'home'},
                    {id:'222',name:'about'},
                    {id:'333',name:'cart'},
                    {id:'444',name:'profile'}
                }
            }
        },
        methods:{
            btnClick(item){
                this.$emit('itemclick',item);    //发射事件,可以将item同时传递过去
            }
        }
    }
    let vm = new Vue({
        el:'app',
        data:{
            movies:['111','222','333']
        },
        methods:{
            cpnClick(item){
                console.log('接收到了子组件传递过来的信息了');
            }
        },
        components:{
            cpn:cpn     //可以直接写成 cpn
        }
    })
</script>

说明:将 vue 实例看成父组件,vue 实例中声明的 components 看成子组件,父子组件中都有 data 数据,注意子组件中的data只能用方法,并返回一个对象。如果在 HTML 中引用子组件,当子组件需要向父组件传递数据时,就要用到自定义事件了,v-on 不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。一共分为两个步骤: 

第一步:在子组件中监听自身的点击,并通过 $emit() 方法来触发事件。

第二步:在父组件中,通过 v-on 来监听子组件事件。

4、为什么组件 data 必须是函数

组件是一个单独功能模块的封装:这个模块有属于自己的 HTML 模板,也应该有属性自己的数据 data,但组件中的 data 和 vue 实例中的 data 不一样,vue 中的 data 可以作为一个对象,但是 组件中的 date 必须是一个方法,而且在这个方法内部必须要返回一个对象,对象内部保存着数据。下面是代码:

<body>
    <div id="app">
        <component-name></component-name>
    </div>
    <template id="temp">
        <h3>这是自定义的一个全局组件---{{msg}}</h3>
    </template>
</body>
<script type="text/javascript">
    Vue.component('component-name',{
        template:'#temp',
        data:function(){    //可以将:()省略,直接写成 data(){}
            return {
                msg:'这是组件中data定义的数据'
            }
        }
    })
    var vm = new Vue({
        el:'#app',
        data:{},
        methods:{}
    });
</script>

组件中的 data 必须是 function,且必须返回一个对象,那么问题来了,在组件外面定义一个对象直接在 data 方法中 return 是否可以?答案是不可以的。因为如果页面中有多个同样的组件,那么他们的操作都会指向这一个对象,所以必须在组件中的返回值写对象,这样才会在每次操作中都返回一个新的对象。下面是一个例子:

<div id="app">
    <counter></counter><hr />
    <counter></counter><hr />
    <counter></counter><hr />
</div>
<template id="temp">
    <div>
        <input type="button" value="加一" @click="increment"/>
        <h3>{{count}}</h3>
    </div>
</template>
<script type="text/javascript">
    Vue.component('counter',{
        template:'#temp',
        data:function(){        //可以将:()省略,直接写成 data(){}
            //return dataObj	这样是不对的
            return {count:0}
        },
        methods:{
            increment(){
                this.count ++
            }
        }
    })
    var vm = new Vue({
        el:'#app',
        data:{},
        methods:{},
    });
</script>

直接在 data 方法中返回对象,则不同组件调用的时候都会返回一个新的对象,各个组件之间互不干扰。效果如下:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值