Vue.js进阶系列(5)--父子组件通信(1)

  在前面的章节中小编已经为大家分享了什么是父组件和子组件,接下来小编将为大家分享父组件和子组件之间的通信

一、通信产生的原因

  在正常的开发过程中,我们从服务器获取到了大量数据。其中一部分数据并不是显示整个页面的大组件中,而是需要在下面的子组件进行展示。这个时候并不是让子组件再次发送数据请求信息给服务器,而是让大组件向服务器请求信息并将数据传递给小组件。比如看下面的例子:

组件通信原因.png

下面我们从父组件和子组件两个方面来分析为何父组件和子组件之间要有通信
  ① 父组件:如上图所示,我们想要获取小组件内容的数据,必须向服务器发送数据请求信息,而向服务器发送数据请求信息的是页面大组件(父组件)而不是小组件。如果是小组件获取数据,对于图中的5个小组件就要向服务器请求5次,如果是父组件,仅仅只需要一次,为了避免服务器不瘫痪,使用父组件向服务器发送请求信息并获取数据,将获取到的数据放在父组件的data中
  ② 子组件:由于子组件不能获取父组件或者Vue实例中的data数据,那么子组件如果想要获取在父组件data中的数据就必须通过另外一种方式,而这种方式就是父组件和子组件之间的通信

二、如何进行通信

在进行父子组件之间的通信时,有下面两种方式:
① 父传子:通过props
② 子传父:通过自定义事件

在这里小编先讲解父组件传递给子组件

1.props书写步骤

  在本次案例中,为避免组件数量过多,小编将Vue当做父组件【前面提到过,Vue实例是root组件,可以当做所有组件的父组件】,为了方便理解,小编从两个步骤说明如何实现父传子
①书写父组件和子组件的基本构造:
就像我们平常书写父子组件一样

<template id="tem">
    <div>
        <h2>我是标题</h2>
         <p>我是段落</p>
    </div>
</template>
<script>
    var vm = new Vue({
        el:'.warp',
        data:{
                message:'我是标题',
                movies:['海贼王','海王','海尔兄弟']
        },
        components:{
            cnp:{
                template:'#tem',
                },
            }
    })
</script>

代码分析如下:
  1.1 父组件:Vue实例作为父组件,其中的messag和movies存放父组件从服务器获取的数据【当然,小编这个没有连接服务器,只是为了以后真正从服务器获取数据时能知道数据存放在哪里】
  1.2 子组件:使用语法糖的格式声明了局部组件cnp,并且通过模板抽离将template的模板的内容抽离到template标签中,两者通过tem id名来建立起联系
那么下一步,小编就将父组件中的数据通过props传递到子组件中
② 通过props实现父组件和子组件之间的通信:

<div class="warp">
    <cnp v-bind:cmessage='message' v-bind:cmovies='movies'></cnp>
</div>
<template id="tem">
    <div>
        <h2>{{cmessage}}</h2>
        <p>{{cmovies}}</p>
    </div>
</template>
components:{
    cnp:{
            template:'#tem',
            props:['cmessage','cmovies']
        },
}
<!--为了便于代码的观看,其余部分已经被小编删除,后序会有完整的代码  -->

  2.1 使用props声明变量:props的写法和Vue实例中methods的写法很相似,只不过这里小编用数组来存放变量,这个变量就是后期要引用的变量名
  2.2 通过v-bind实现通信:在使用<cnp></cnp>标签引用组件时,为了将Vue实例中的数据传递到cnp组件中,使用v-bind操作cmessage属性和cmovies属性,引用上一步声明的变量名cmessage和cmovies,接着为变量赋值cmessage='message'和cmovies='movies'
  2.3 显示数据: 经过前两个步骤,数据已经从Vue传递到cnp子组件中,接下来就是在子组件的模板template中引用子组件声明的变量名即可,比如本例子引用cmessage和cmovies
注意:不能引用Vue实例中的message和movies,因为子组件是不能操作父组件的数据
下面是完成的代码和效果:

    <body>
        <div class="warp">
            <cnp v-bind:cmessage='message' v-bind:cmovies='movies'></cnp>
        </div>
        <template id="tem">
            <div>
                <h2>{{cmessage}}</h2>
                <p>{{cmovies}}</p>
            </div>
        </template>
        <script src="vue.min.js" ></script>
        <script>
            var vm = new Vue({
                el:'.warp',
                data:{
                    message:'我是标题',
                    movies:['海贼王','海王','海尔兄弟']
                },
                components:{
                    cnp:{
                        template:'#tem',
                        props:['cmessage','cmovies']
                    },
                }
            })
        </script>
    </body>

image.png

  可以看到数据已经成功的从父组件传递到了子组件中,如果你不想要以数组的形式显示数据,使用v-for指令遍历并显示即可:

<template id="tem" >
    <div>
        <h2>{{cmessage}}</h2>
        <ul v-for="item in cmovies">
            <li>{{item}}</li>
        </ul>
    </div>
</template>
image.png

2.props 类型

props支持的类型很多,主要有:String,Number, Boolean, Array, Object, Data, FunctionSymbol。下面小编主要为大家分享数组类型对象类型

① 数组类型
components:{
  cnp:{
      template:'#tem',
      props:['cmessage','cmovies']
  }
}

  这种写法虽然简洁,但是看起来有点别扭,因为cmessage是一个变量而不是字符串【因为字符串都是用引号包裹着的】,所以一般在开发的过程中,都采用对象类型。

② 对象类型

2.1 基本对象类型
就是在对象内部声明变量的类型,比如:

components:{
    cnp:{
            template:'#tem',
            props:{
                    cmessage:String,
                    cmovies:Array
                    }
            }
    }

  本例中声明cmessage是字符串类型,cmovies是数组类型。
2.2 有默认值的对象类型--default
  使用了default属性的变量,在没有被传递数据时,就会显示默认值【如果传递了数据,默认值就被数据覆盖了】。默认值的书写方式又和变量的类型有关,主要分为当变量是String类型和当变量是数组类型或者是对象类型两种情况

2.2.1 变量是String类型

components:{
    cnp:{
            template:'#tem',
            props:{
                    cmessage:{
                            type:String,
                            default:'aaaa'
                    }
            }
        }
}

  这个例子中,将cmessage的值变成了一个对象,然后在对象内部定义cmessage的类型是String,默认值是aaaa。

默认值为aaaa.png

2.2.2 变量是数组类型或者对象类型时
  当cmessage是数组类型是,如果我们是这样子书写: default:[],在Vue 2.5.17一下是不通过的,比如:

props:{
        cmessage:{
                    type:Array,
                    default:[]
                },
}

image.png

  默认值是无效的,如果默认值的类型是数组或者对象类型,默认值必须是一个函数,也就是要修改成下面的代码:

props:{
        cmessage:{
                type:Array,
                default(){
                        return []
                }
        },
}

  此外,就像刚刚开头提到的,如果在使用了default后还传递数据,新数据就会覆盖默认值。比如:

<!-- 没有默认值 -->
    <div class="warp">
        <cnp  v-bind:cmessage='message' v-bind:cmovies='movies'</cnp>
    </div>
        
<!-- 有默认值 -->
    <div class="warp">
        <cnp v-bind:cmovies='movies'></cnp>
    </div>

没有默认值.png

默认值aaaa已经被“我是标题”覆盖了
2.3 有必传值的对象类型--require
  当组件中的变量使用required属性时,意味着别人使用这个组件一定要给该变量传递数据,否则就会把报错,比如:

<div class="warp">
    <cnp></cnp>
</div>
components:{
    cnp:{
            template:'#tem',
            props:{
                    cmessage:{
                            type:String,
                            required:true
                    }
            }
        }
}
image.png

  在组件cnp的变量cmessage中使用了required属性,但是在使用组件cnp时,并没有给cmessage传递数值,这时就会报错 ,因此,如果使用了required属性时,一定要给变量传递数据,比如:

<!-- 有给cmessage传递数据 -->
    <div class="warp">
        <cnp v-bind:cmessage='message'></cnp>
    </div>
<!-- 没有给cmessage传递数据 -->
    <div class="warp">
        <cnp></cnp>
    </div>
3.props 驼峰标识

  所谓的驼峰标识其实就是指两个单词拼接在一起,第二个单词的首字母是大写。比如:myMovies就是驼峰标识。
  在Vue中,使用v-bind指令,是不支持驼峰标识的,需要将第二个单词的首字母用 “ 横线 小写"代替”。比如:

<div class="warp">
    <cnp :cMessage="message"></cnp>
</div>
<template id="tem" >
    <div>
        <p>{{cMessage}}</p>
    </div>  
</template>
<script>
    var vm = new Vue({
        el:'.warp',
        data:{
                message:'我是标题',
                movies:['海贼王','海王','海尔兄弟']
        },
        components:{
            cnp:{
                    template:'#tem',
                    props:{
                        cMessage:{
                            type:String,
                            default:'aaaa',
                        }
                    }
            }
        }
    })
</script>

效果图.png

控制台.png

  在这个例子中,我们希望就父组件Vue中的message数据传递到子组件cnp的cMessage中,但是从效果图中可以看到,并没有传递成功。这是因为在子组件使用v-bind指令操作变量时,变量使用的是驼峰标识【<cnp :cMessage="message"></cnp>】,在目前Vue的版本中是不允许的,因此需要将cMessage修改成“c-message”

<div class="warp">
    <cnp :c-message="message"></cnp>
</div>
image.png

  如果变量名是 cMyLoveMovies,同理,需要修改成“c-my-love-movies”
好了,以上就是小编今天为大家分享的干货,总结成以下几点:

1.通信目的:为了减少访问服务器是访问频率
2.props的书写方式
2.props的类型很多种,这里主要讲了数组和对象两种类型
  2.1 当props是对象类型时,可以有type,default,required属性
  2.2 default是字符串时的写法和default是数组或者对象的写法.

3.props的驼峰标识

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 本文章是我最近在公司的一场内部分享的内容。我有个习惯就是每次分享都会先将要分享的内容写成文章。所以这个文集也是用来...
    Awey阅读 9,437评论 4 67
  • 什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装...
    youins阅读 9,470评论 0 13
  • 周末两天把自己沉浸在私房课里,今天花了一天时间抽离,但发现怎么也做不到,脑海里不时浮现出周末的片段,让我突然会大笑...
    饭饭_bms阅读 309评论 0 2
  • 她住在我们家对面的筒子楼里,一个人。听说她有儿有女,却没有人去照顾这样一个女人。那个女人每天都穿着灰色的上衣和黑...
    浪瓜小姐姐阅读 485评论 0 1
  • 【心赏】画家老庄身材魁梧高大,古铜色的面庞,有时间就开着越野吉普全国各地的玩游,活脱脱就是一个桀骜不驯、狂放无羁、...
    杨宝树阅读 221评论 1 2