一、学习目标
- 掌握props选项的用法
- 掌握slot槽口的使用方法
- 掌握自定义事件的使用方法
- 能够灵活的掌握父子组件的定义与组合方法
二、props 选项的作用
2.1、props选项的作用
作用:props选项用来声明它期待获得的数据 。如图:
props本质: props为元素属性
语法:
语法:
JS中需要在组件中定义:
components:{
'myHeader': {
template: "#head",
props: ['message1','message2',....] //props的定义
}
}
template中调用:
<template id="head">
<div class="headerWarp">
<span>{{message1}}</span> //1.与data一样,props可以用在版本中
</div> //2.可以在vm实例中像 this.message 这样使用
</template>
HTML中传入实际需要的val:
<组件 message1='val'></组件>
实际例子使用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,user-scalable=0,initial-scale=1.0"/> <title>Title</title> <style> * {margin: 0;padding: 0;} .headerWarp {width: 100%;height: 48px;background: #f7f7f7; border-bottom: 1px solid #999;} </style> </head> <body> <!-- props: 定义希望接收到的值 语法:props: ['希望接收的值',.....] 使用:1)与data 一样,可以在模板中使用; 2)可以在vm实例中,像 this.msg 这样去使用 值得传入: HTML:<组件 希望接收的值='val'></组件> --> <div id="box"> <my-header txt="上海" src1="img/blue.png" src2="img/chat_blue.png"></my-header> <my-header txt="北京"></my-header> </div> <template id="head"> <div class="headerWarp"> <span>{{txt}}</span> <!--v-bind指令缩写,也可以写成v-bind='{src:scr1}'--> <img :src="src1" class="headerWarp"> <img :src="src2" class="headerWarp"> </div> </template> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components:{ 'myHeader': { template: "#head", props: ['txt','src1','src2'] //定义props,需要定义在组件内 } } }); </script> </body>
小结:
- props选项用来声明它期待获得的数据
- 使用: 与data一样可用在模板中;可在vm实例中使用。
三、slot 槽口
slot(槽口)作用:用来混合父组件的内容与子组件的模板。是在子模板去留槽口,然后再父组件的模板中去使用槽口。
3.1、匿名槽口(slot)
说明:匿名槽口(slot),顾名思义就是不需要给这个槽口起具体的名字,直接使用slot槽口,而且匿名的槽口只能定义一个。
语法:
//定义容器
<div id="box">
<parent>
<p>我是留下的不具名的槽口</p> //根据留下的不具名槽口插入内容。
</parent>
</div>
//定义模板
<template id="p">
<div>
<h1>组件模板</h1>
<slot></slot> //定义slot不具名槽口
</div>
</template>
具体使用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <parent> <p>我是留下的不具名的槽口</p> <!--留下的槽口插入内容--> </parent> </div> <!--定义模板--> <template id="p"> <div> <h1>组件模板</h1> <slot></slot> <!--定义一个不具名槽口--> </div> </template> <!-- slot: 槽口,在组件封装的过程中,向外部留出的槽口,也就是可提供插入一些内容 语法:<slot></slot> 注意:不具名槽口只能允许插入一个 --> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { //定义局部组件 "parent": { template: "#p" //根据选择器找到模板 } } }); </script> </body>
3.2、具名槽口(slot)
<slot>元素可以用一个特殊属性name来配置如何分发内容,多个slot槽口可以有不同的名字,具名slot槽口将匹配内容片断中有对应slot。
语法:
具名槽口:<slot name="slot_name"></slot>
匹配: <tag_name slot="slot_name"></tag_name>
完整语法:
//定义容器
<div id="box">
<test>
<span slot="slot1">111111</span> //调用具名槽口
</test>
</div>
//定义组件模板
<template id="t">
<div>
<h2>test</h2>
<slot name="slot1"></slot> //定义具名槽口
</div>
</template>
//创建vue对象
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el: "#box",
data: {},
components: { //定义局部组件
"test": {
template: "#t" //调用模板
}
}
});
</script>
具体使用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <test> <img slot="leftImg" src="ic_actionbar_search_icon.png"/> //调用具名槽口 <img slot="rightImg" src="ic_actionbar_button_icon"/> <span>111111</span> </test> </div> <!-- slot: 槽口,在组件的封装的过程中,向外部留出槽口,也就是可供外部插入一些内容 具名槽口:<slot name="slot_name"></slot> 匹配: <tag_name slot="slot_name"></tag_name> --> <template id="t"> <div> <h2>test</h2> <slot name="leftimg"></slot> //定义多个具名槽口 <slot name="rightimg"></slot> <slot></slot> //不具名槽口只能定义是一个 </div> </template> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { "test": { template: "#t" } } }); </script> </body>
注意:具名slot槽口可以定义多个,但是不具名slot槽口只能定义一个。
小结:
- slot作用:用来混合父组件的内容与子组件自己的模板
- 具名slot: 具名slot将匹配内容片断中有对应slot特性的元素
- 在使用指令时,是不是直接在slot槽口添加指令的,需要在slot外面包装一层使用指令:<span v-show="!bol"><slot name="nomalImg"></slot></span>
四、父子组件
4.1、父子组件定义
在一个实例中可以有多个局部组件,在局部组件中还可以定义它的子组件,在子组件还可以定义子组件,这个就是父子组件,定义如下:
components:{
'parent':{ //父组件
template: '<div></div>',
components: {
'child': { //子组件
template: '<div></div>'
}
}
}
}
4.2、父子组件的使用
说明:父子组件件作用域是相互独立的,子组件只能在父组件的模板中进行调用。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <parent></parent> </div> <!--定义父组件模板--> <template id="p"> <div class="tabbarWrap"> <!--在父组件的模板中调用--> <child></child> </div> </template> <!--定义子组件模板--> <template id="c"> <div class="itemWrap"> <img src="1.png"> <span>首页</span> </div> </template> <!-- 每一个组件相当于完整的vue实例,拥有绝大数的vm实例的配置项 子组件调用:只能在父组件的模板中进行调用 --> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { //父组件 "parent": { template: "#p", //定义子组件 components: { "child": { template: "#c" } } } } }); </script> </body>
注意事项:
- 父组件和子组件的作用域是相互独立的,是无法共享的。
- 子组件只能在父组件的模板中调用,不能直接在容器中去调用。
五、自定义事件
之前我们都是绑定一个事件,这些事件都是我们事先定义好的,但是我们也可以自定义事件,我们通过自定义事件,可以实现父子组件之间传值。这边的步骤,首先我们子组件先抛出自定义监听事件,父组件接收自定义监听事件。
5.1、抛出自定义事件监听
语法:
this.$emit('event',val) //event事件名必须传入,val值可传可不传
$emit: 代表着父组件的一个方法,实例方法,用来触发事件监听的。
参数:
- event:自定义事件名陈
- val:通过自定义事件传递的值。注:val为可选参数。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <parent></parent> </div> <!--定义父模板--> <template id="p"> <div> <h1>parent~~~~~~~~~~{{pMsg}}</h1> <child1></child1> </div> </template> <!--定义子模板--> <template id="c1"> <!--一点击就让它传值--> <div @click="fn"> <p>child1***********{{ cMsg }}</p> </div> </template> <!-- 子组件将值传递给父组件,叫做逆向传值,需要借助 自定义监听事件。 --> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { 'parent': { template: '#p', data: function(){ return { pMsg: "pppppp" } }, components: { child1: { template: "#c1", data: function(){ return { cMsg: "cccc11111" } }, methods: { fn: function(){ //console.log(11); //自定义事件 //$emit('自定义事件名称',传递的值) this.$emit('change',this.cMsg); } } } } } } }); </script> </body>
注意:
- 子组件将值传递给父组件,叫做你想传值,需要借助 自定义监听事件。
5.2、接收自定义事件监听
说明:子组件抛出自定义事件监听,父组件需要接收自定义事件监听,这样子组件的数据 才能传递给父组件。
语法:
<component @event='fn'></component>
fn: function(val){
}
val: 自定义事件传递出的值
①逆向传值
说明:以上我们说的把 子组件 的 值 通过 自定义事件 传递给 父组件,这种传递方式叫 逆向传值。子组件传值 -> 父组件接收。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <parent></parent> </div> <!--定义父模板--> <template id="p"> <div> <h1>parent~~~~~~~~~~{{pMsg}}</h1> <!--父组件接收 监听事件 --> <child1 @change="getVal"></child1> <!-- 接收事件监听出,方法名后面是不写小括号的 --> </div> </template> <!--定义子模板--> <template id="c1"> <!-- 子组件抛出监听事件 --> <div @click="fn"> <p>child1***********{{ cMsg }}</p> </div> </template> <!-- 子组件将值传递给父组件,叫做逆向传值,需要借助 自定义监听事件。 --> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { 'parent': { template: '#p', data: function(){ return { pMsg: "pppppp", message: '' } }, methods: { getVal: function(val){ //val: 代表传递过来的值 console.log("val:" + val); this.message = val; //接收自组件传递过来的值 console.log("message:" + this.message) } }, components: { child1: { template: "#c1", data: function(){ return { cMsg: "cccc11111" } }, methods: { //定义抛出自定义事件 fn: function(){ //自定义事件 //$emit('自定义事件名称',传递的值) this.$emit('change',this.cMsg); //this.cMsg传递子组件中的值 } } } } } } }); </script> </body>
步骤: 在子组件里面定义 函数 fn -> 创建抛出自定义 事件 -> 父组件 定义接收自定义组件 -> 接收 子组件传递过来的值val。
②正向传值
说明:父组件将值传递给子组件,叫做正向传值;父组件传值 -> 子组件接收。这个时候我们子组件希望从外部得到值: props: [ ]
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<body> <div id="box"> <parent></parent> </div> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: "#box", data: {}, components: { "parent": { template: '<div><h1>parent</h1><child :message="msg"></child></div>', //绑定msg值 data: function(){ return { msg: "p" } }, components: { 'child': { template: "<span>child{{ message }}</span>", //接收父组件传过来的值 props: ['message'] //使用props } } } } }); </script> </body>
注意:vue.js 中允许 正向传值,所以正向传值不需要 条件出发,是主动的。逆向传值,是不允许的,需要主动触发(主动抛出自定义事件监听)。