文章内容由sass uniapp vue 微信小程序组成

效果图展示(最好nav内容一屏展示完,超过样式会有些问题)

uniapp 微信小程序 nav自定义组件_下划线

子组件

<template>

<view class="navbar">
<view v-for="(item, _index) in navList" :key="item.state" class="nav-item" :class="{current: tabCurrentIndex === _index,active: tabCurrentIndex === _index}"
@tap="tabClick(_index)">
{{item.text}}
<view class="nav-item-icon" :class="{iconfontsize:item.iconfont&&item.iconfont.length===1}">
<text class="iconfont" v-for="(i,iIndex) in item.iconfont" :key="iIndex" :class="[i]"></text>
</view>

</view>

<view v-show="isBorder" :style="[lineStyle]" class="border-bottom"></view>


</view>

</template>

<script>
export default {
props: ['navList', 'tabCurrentIndex', 'ptabClick', 'isBorder','isWidth'], //如果需要下划线就传isBorder等于true
data() {
return {
lineStyle: {},
left:0,
width:0
}
},
created() {
let that = this;
setTimeout(function() {
const query = uni.createSelectorQuery().in(that)
query.select('.navbar').boundingClientRect();
query.exec(function(res) {
that.left=res[0].left;
that.width=res[0].width;
})
}, 300);
},
methods: {
tabClick(index) {
//当点击子组件的按钮的时候,如何拿到父组件传递过来的func方法,并调用这个方法
//英文愿意:是触发,调用、发射的意思
this.$emit("ptabClick", index);
this.changeBorder(index);
},
changeBorder(index){
let that = this;
setTimeout(function() {
const query = uni.createSelectorQuery().in(that)
query.selectAll('.nav-item').boundingClientRect();
query.exec(function(res) {

if(that.isWidth){
let left=res[0][index].left;
that.lineStyle = {
width: that.width/that.navList.length + `px`,
height:'1px',
transform: 'translateX(' +that.width/that.navList.length*index + 'px) translateX(-0%)',
transitionDuration: `0.3s`
}
}else{
let left=res[0][index].left-that.left;
that.lineStyle = {
width: res[0][index].width + `px`,
height:'3px',
transform: 'translateX(' +left + 'px) translateX(-0%)',
transitionDuration: `0.3s`
}
}
})
}, 300);
}
}
}
</script>

<style lang="scss" scoped>
@import '../../../common/css/mixins/index.scss';
@import '../../../common/css/iconfont.css';

.navbar {
display: flex;
justify-content: space-around;
line-height: $uni-line-height-xl;
padding: $uni-padding-sm $uni-padding-sm;
background: $uni-bg-color-white;
box-shadow: 0 rpx(2) rpx(10) rgba(0, 0, 0, .06);
position: relative;
z-index: 10;

.nav-item {
flex: none;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-size: $uni-font-size-base-xl;
color: $uni-color-base;

&-icon {
@include display-flex;
@include flex-direction(column);
@include justify-content(space-around);
line-height: $uni-line-height-smm;

.iconfont {
font-size: $uni-font-size-smm;
}

.grey {
color: $uni-color-black4 !important;
}
}

&-icon.iconfontsize {
.iconfont {
font-size: $uni-font-size-lg;
line-height: $uni-line-height-xl;
}
}

&.current {
color: $uni-color-main;
}

}

/* .navActive {
&.active {
@include set-border-bottom($uni-border-color-main, $uni-border-l, solid);
}
} */
}

.border-bottom {
background-color: $uni-border-color-main;
position: absolute;
top: rpx(74);
left: 0;
}

</style>

父页面

<template>
<view>
<switchNav ref="switchNav" :navList="navList" :tabCurrentIndex="tabCurrentIndex" v-on:ptabClick="tabClick"
isBorder="true"></switchNav>
</view>
</template>
<script>
import switchNav from '../../../common/components/nav/index'//nav切换引入
export default {
components: {switchNav,},
data() {
return {
tabCurrentIndex: 0,//标签当前指数
navList: [
{state: 0, text: '省',},
{state: 1, text: '市',},
{state: 3, text: '县',},
{state: 4, text: '区',},
],//导航列表
}
},
onLoad() {
let that = this;

setTimeout(function () {
that.$refs.switchNav.changeBorder(parseInt(this.tabCurrentIndex));//默认下划线在第一个 索引为0元素下面
}, 300);
},
methods: {
//选项卡单击
tabClick: function (index) {
this.tabCurrentIndex = index;
console.log(this.tabCurrentIndex);
},
}