NavBar组件作为导航条,是最经常被复用的几个组件之一,下面来剖析一下它的实现过程:
NavBar通常可以分为left/center/right三块,只是这三个位置具体填充什么,需要在使用时再传入。所以我们在这三个位置分别放入一个插槽。此外,为了便于添加默认的样式,故将每个插槽用div包裹起来。
<template>
<div class="nav-bar">
<div class="left"><slot name="left"></slot></div>
<div class="center"><slot name="center"></slot></div>
<div class="right"><slot name="right"></slot></div>
</div>
</template>
样式部分,采用弹性布局;导航条高度一般都为44px;文本居中属性会被三个子div所继承;设置盒子阴影以增加美观度。box-shadow的参数分别为:阴影水平方向偏移、垂直方向偏移、模糊部分的宽度、颜色。
此外,如果只给父元素开启弹性布局,而子元素不设置相关的弹性样式,结果就是子元素全部挤在父元素的左边。(这是因为容器的justify-content属性默认值为flex-start,贴近主轴起边)
而flex: x这样的写法,相当于 flex-grow 值为x,flex-shrink 取 1,flex-basis 取 0%。
所以对于三个弹性元素,给right和left设置宽度后,剩下的空间会按照比例分配。由于left/center/right的flex-grow分别为0/1/0,所以空间全部分配给了center。
.nav-bar{ display: flex; height: 44px; line-height: 44px; text-align: center; box-shadow: 0 1px 1px rgba(100,100,100,.1); } .right, .left{ width: 60px; } .center{ flex: 1; }
当在Home主页组件中使用NavBar时,只用到了center插槽,其功能为显示“购物街”三个字,比较简单:
<nav-bar class="home-nav"><div slot="center">购物街</div></nav-bar>
当在Detail详情组件中使用NavBar时,left和center插槽被使用,left插槽中放置一个返回按钮;center插槽中代码较多,所以将使用的代码再次封装一个组件DetailNavBar:
<nav-bar>
<div slot="left" class="back" @click="backClick">
<img src="~assets/img/common/back.svg" alt="">
</div>
<div slot="center" class="title">
<div v-for="(item, index) in titles"
:key="index" @click="titleClick(index)"
class="items" :class="{active: index === currentIndex}">{{item}}</div>
</div>
</nav-bar>
<detail-nav-bar class="detail-nav" @titleClick="titleClick" ref="nav"></detail-nav-bar>
left插槽中返回按钮的功能为:点击后返回到history栈中的前一个页面。所以为其绑定单击响应方法backClick(),在backClick中只需要调用路由实例对象的back方法即可,当然也可以是this.$router.go(-1)。
this.$router.back()
center插槽中要显示四个tag,它们位于title数组中:['商品', '参数', '评论', '推荐']。所以可以通过v-for来动态显示。此外,我们希望让被选中的tag变成红色,这一功能可以通过动态绑定class来实现:给每个tag绑定单击响应方法titleClick,当某个tag被点击后,titleClick将此tag的index保存到currentIndex变量中。而一旦这样做了,当前tag就会被绑定上名为active的CSS类,在.active设置color属性即可。
titleClick(index){ this.currentIndex = index }
浙公网安备 33010602011771号