第九节
9.1组件命名
当注册组件(或者prop)时,可以使用kabab-case(短横线分割命名)、camelCase(驼峰式命名)或PascalCase(单词首字母大写命令)
9.2组件中的data
组件中的data选项必须是一个函数,返回一个数据对象。为什么需要是一个函数,而不可以像Vue实例是一个对象呢,首先因为组件会被多次复用,而对象是引用数据类型,如果组件数据使用对象的话,那么组件所有的复用都将共享这些数据。
9.3templat的使用
直接写在选项里的模板,写在template标签里的模板、写在script标签里的模板
9.4组件之间的通讯
组件之间的通讯又叫做组件的传值,父子组件的通讯和非父子组件的通讯。
9.4.1如何进行父子组件间的通讯呢?
(一)通过props向子组件传递数据;
在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
①字符串数组,数组中的字符串就是传递时的名称;
②对象,对象可以设置传递时的类型,也可以设置默认值等。
<div id="app">
<!-- 静态传值(movies) 动态传值(des)
父组件在使用子组件的时候,可以将父组件的数据绑定到使用子组件的标签上
子组件在选项中添加一个props属性来接收数据
-->
<my-son movies="唐人街探案3,你好李焕英" :des="msg"></my-son>
</div>
<!--组件模板 分离 -->
<template id="son">
<div style="border: 1px solid red;">
<h2>这是子组件</h2>
<h3>电影名称:{{movies}}</h3>
<h4>{{des}}</h4>
</div>
</template>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script type="text/javascript">
let MySon = {
template:'#son',
//子组件定义props接收数据并使用
//数组中存放的是自定义属性的名称
props:['movies','des']//数组写法
}
new Vue({
el:'#app',
data: {
msg:'这是父组件中的msg'
},
components: {
//注册子组件
MySon
}
})
</script>
(二)通过事件向父组件发送消息
第十节
10.1propsData[使用率不高,因为有vuex]
propsData不是和属性有关,他用在全局扩展时进行传递数据
类型: {[key:string]:any}
限制: 只用于new创建的实例中
详细: 创建实例时候传递props,主要作用是方便测试,他的作用就是单页面应用中保持状态和数,就是在本局扩展里面传递参数propsData
10.2ref和$refs
ref: 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的$refs
对象是哪个。如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件;
$refs:
一个对象,持有注册过ref attribute的所有DOM元素和组件实例。
<body>
<div id="app">
<!-- 在p标签上,加上了ref特性,并赋予了id -->
<p ref="mp" id="aa">这是p标签</p>
<button type="button" @click="get">获取ref</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
methods:{
get(){
// 通过this.$refs获取到的是 绑定的元素
console.log(this.$refs.mp)
var a=document.getElementById('aa')
console.log(a)
}
}
})
</script>
</body>
第十一节
11.1插槽
11.2组件的插槽
组件的插槽也是为了让我们封装的组件更加具有扩展性。让使用者可以决定组件内部的一些内容到底展示什么。
11.3插槽的基本使用
1、<slot></slot>
2、插槽的默认值<slot><button type="button"></button></slot>
3、如果有多个值,同时放入到组件中进行替换,它会将放入的值作为元素一起替换
11.4插槽的类型
1. 默认插槽(匿名插槽) 2. 具名插槽 name 3. 作用域插槽 v-slot
11.5插槽的使用
(一)默认插槽(匿名插槽)
直接在组件中使用slot进行占位,当我们使用该组件时,在组件标签内写入需要展示的内容即可
(二)具名插槽 name
具名插槽,给slot加上name属性 <slot name="插槽名称">,
使用的时候
<span style="color: coral;" slot="uname">友谊</span>
(三)作用域插槽
<slot :abc="pLanguages">
<ul v-for="item in pLanguages">
<li>{{item}}</li>
</ul>
</slot>
用法: 将abc变量名,作为slot元素的一个属性绑定上去,传入值,在组件使用时,通过v-slot="数据别名"的方式使用
<template v-slot="bb">
<!-- {{bb.abc}}- -->
{{bb.abc.join(' - ')}}
</template>
注意:在使用作用域插槽的时候,必须使用tmeplate
插槽实战案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<!-- 引用字体图标库 -->
<link rel="stylesheet" type="text/css" href="./font/iconfont.css"/>
<style type="text/css">
.myflex{border: 1px solid #ccc;display: flex;margin-top:10px ;}
.icon-fanhui{font-size: 20px;}
ul>li{list-style: none;}
/* 设置组件三部分内容各占多少 */
.m-l{width: 15%; height: 50px;}
.m-c{width: 70%; height: 50px;}
.m-r{width: 15%; height: 50px;}
.mc{display: flex;justify-content: space-around;align-items: center; }
.myli{width: 40px;position: relative;left: -20px;text-align: center;line-height: 2;}
.active{border-bottom:3px solid rgb(253,122,122) ;color: red;font-weight: 600;}
.myinput{background-color: #eee;border: none;outline: none;width: 80%;}
.product{display: flex;align-items: center;width: 100%;height: 35px;background-color: #eee;border-radius: 20px;padding: 0 20px;}
#end{background-color: red;}
#over-three{background-color: red;border:none;font-size: 16px;text-align: center;line-height:40px;color:#fff;outline:none;}
</style>
</head>
<body>
<div id="app">
<!-- 使用组件 -->
<nav-bar></nav-bar>
<!-- 商品 -->
<nav-bar>
<ul slot="center" class="mc" style="width: 100%;">
<li
class="myli" :class="{active:current==index}"
@click="current=index"
v-for="(val,index) in arr">
{{val}}
</li>
</ul>
</nav-bar>
<!-- 带有搜索框 -->
<nav-bar :ishow="false">
<div slot="center" class="product">
<i class="iconfont icon-fangdajing"></i>
<input type="text" placeholder="蚕丝被" class="myinput" />
</div>
</nav-bar>
<!-- 不有的搜索框 -->
<nav-bar id="end">
<div slot="center" class="product">
<i class="iconfont icon-fangdajing"></i>
<input type="text" placeholder="蚕丝被" class="myinput" />
</div>
<div slot="right">
<button id="over-three">登录</button>
</div>
</nav-bar>
</div>
<!-- 组件模板 -->
<template id="mynav">
<div class="myflex">
<!-- <h1>这是navbar组件</h1> -->
<!-- 左侧 -->
<div class="m-l mc">
<slot name="left">
<i class="iconfont icon-fanhui"></i>
</slot>
</div>
<!-- 中间-->
<div class="m-c mc">
<slot name="center">
<span>购物车</span>
</slot>
</div>
<!-- 右侧 -->
<div class="m-r mc" v-if="ishow">
<slot name="right">
<i class="iconfont icon-gengduo1"></i>
</slot>
</div>
</div>
</template>
<!-- 引入vuejs库 -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script type="text/javascript">
// 注册全局组件
Vue.component("nav-bar",{//组件选项对象
template:'#mynav',
props:{
ishow:{
default:true
}
}
})
// 创建Vue实例
new Vue({
el:'#app',
data:{
arr:["商品","评价","详情","推荐"],
current:0
},
})
</script>
</body>
</html>