文章目录
-
- 概要
- 技术名词解释
- 技术细节
- 小结
概要
首先看效果
技术名词解释
- uniapp
- uni组件
技术细节
首先看需求是步骤条,然后看组件中没有自己想要的步骤条,那么就的自己去写
一、HTML部分
<template>
<view class="mainStepOut">
<view class="stepOut">
<ul class="stepul">
<li class="stepItem">
<!-- 大圈部分 -->
<view v-for="(item,index) in list" :key="index">
<!-- 小圈部分 -->
<view class="step1" v-if="item.step.length>0" v-for="(item1,index1) in item.step" :key="index1">
<!-- 此处为小圆圈 -->
<view :class="index1 === 0 ?(index===0?'iconSmall active':'iconSmall'):'iconSmall'"></view>
<!-- 模拟步骤条连接线(判断列表到最后一项后把线隐藏) -->
<view class="line" :style="'height:'+stepnewheight[index1]+'px'"
v-if="index !== list.length - 1 && item.title1!==''">
</view>
<!-- 主题内容 -->
<view class="stepStatus1" :id="'stepStatus1'+index1">
<view :class="index1 === 0 ?(index===0?'titlecolor':'title'):'title'">
<text>{{item1.title}}</text>
<text>{{item1.date}}</text>
</view>
<view class="annotation">
<view class="item_person" v-html="item1.content">
<!-- {{item1.content}} -->
</view>
</view>
</view>
</view>
<view class="step1" v-if="item.title1!==''">
<!-- 此处为圆圈 -->
<view :class="item.step.length!==0?'icon':(index == 0 ?'icon1':'icon')"></view>
<!-- 模拟步骤条连接线(判断列表到最后一项后把线隐藏) -->
<view class="line" :style="'height:'+newheight[index]+'px'"
v-if="index !== list.length - 1">
</view>
<!-- 主题内容 -->
<view class="stepStatus" :id="'stepStatus'+index">
<view :class="item.step.length!==0 ? 'title':(index == 0 ?'titlecolor':'title')">
<view>{{item.title1}}</view>
<text v-if="item.title2">{{item.title2}}</text>
<text>{{item.date}}</text>
</view>
<view class="annotation">
<view class="item_person" v-html="item.content">
</view>
</view>
</view>
</view>
</view>
</li>
</ul>
</view>
</view>
</template>
二、CSS部分
<style lang="scss" scoped>
.mainStepOut{
height: 100%;
overflow-y: auto;
}
.stepOut {
height: 100%;
padding-top: 40rpx;
width: 100%;
display: flex;
justify-content: space-between;
.stepul {
list-style: none;
width: 100%;
margin-left: -20rpx;
.stepItem {
width: 100%;
font-size: 32rpx;
position: relative;
border-left: #d7d7d7;
// display: flex;
.step1 {
display: flex;
width: 100%;
// height: 200rpx;
font-size: 32rpx;
position: relative;
border-left: #d7d7d7;
}
.icon {
width: 32rpx;
height: 32rpx;
flex: 0 0 32rpx;
border-radius: 50%;
background: #fff;
border: 4rpx solid #d7d7d7;
position: relative;
z-index: 888;
}
.icon1 {
width: 38rpx;
height: 38rpx;
border-radius: 50%;
flex: 0 0 38rpx;
right: 1.5px;
border: 4rpx solid #2E88FF;
position: relative;
z-index: 888;
background-color: #fff;
}
.icon1:before {
content: "";
position: absolute;
top: 5rpx;
left: 5rpx;
width: calc(100% - 8rpx);
height: calc(100% - 8rpx);
background-color: #2E88FF;
border-radius: 50%;
flex: 0 0 calc(100% - 8rpx);
}
.iconSmall {
width: 21rpx;
height: 21rpx;
border-radius: 50%;
flex: 0 0 21rpx;
background: #fff;
// border: 4rpx solid #d7d7d7;
position: relative;
left: 2.8px;
background: #808080;
z-index: 888;
margin-right: 10rpx;
}
.active {
background-color: #2E88FF;
border: 0;
}
.line {
position: absolute;
top: 12rpx;
// left: 13rpx;
left: 14rpx;
width: 4rpx;
// height: 200rpx;
background-color: #e2e2e2;
z-index: 111;
}
.stepStatus {
width: 100%;
padding: 0 25rpx;
background: #FAFAFA;
margin-bottom: 26rpx;
margin-left: 15rpx;
margin-right: 15rpx;
padding-top: 10rpx;
margin-top: -16rpx;
padding-bottom: 10rpx;
border-radius: 18rpx;
.annotation {
font-size: 25rpx;
color: #b0b0b0;
}
}
.stepStatus1 {
width: 100%;
padding: 0 25rpx;
background: #FAFAFA;
margin-bottom: 26rpx;
margin-left: 15rpx;
margin-right: 15rpx;
padding-top: 10rpx;
margin-top: -16rpx;
padding-bottom: 10rpx;
border-radius: 18rpx;
.annotation {
font-size: 25rpx;
color: #b0b0b0;
}
}
// 未进行
.title {
display: flex;
color: #808080;
margin-bottom: 10rpx;
view {
font-size: 30rpx;
// font-weight: 700;
margin-right: 18rpx;
}
text {
font-size: 25rpx;
display: flex;
flex-direction: column-reverse;
justify-self: end;
margin-right: 20rpx;
}
}
// 已进行
.titlecolor {
display: flex;
color: #2E88FF;
margin-bottom: 10rpx;
view {
color: #2E88FF;
font-size: 30rpx;
// font-weight: 700;
margin-right: 18rpx;
}
text {
font-size: 25rpx;
display: flex;
flex-direction: column-reverse;
justify-self: end;
margin-right: 20rpx;
}
}
}
}
}
</style>
因为有小圈还有大圈所有上面的主体部分的进行判断,很好理解的上面都有注释,当你的数组长度最大时就不显示线条,反之显示
现在几乎实现了整体部分,但是bug出现了,就是你的部分如果高的话就会把下面部分挤出去,线条就不能正常链接了,这个问题怎么解决呢!!!别着急看下面
三、bug问题解决
咱们可以通过uniapp中的Api进行判断它的高度进行给线段设置高度(uni.createSelectorQuery)
uni.createSelectorQuery()
返回一个 SelectorQuery
对象实例。可以在这个实例上使用 select
等方法选择节点,并使用 boundingClientRect
等方法选择需要查询的信息。
Tips:
- 使用
uni.createSelectorQuery()
需要在生命周期mounted
后进行调用。 - 默认需要使用到
selectorQuery.in
方法。
measureViewHeight() {
for (let i = 0; i < this.list.length; i++) {
uni.createSelectorQuery()
.in(this)
.select(`#stepStatus${i}`)
.boundingClientRect(rect => {
// console.log(`Div1的高度为:${rect.height}px`);
let sum = rect.height + 9
this.newheight.push(sum)
})
.selectViewport()
.scrollOffset()
.exec();
}
for (let i = 0; i < this.list.length; i++) {
for (let j = 0; j < this.list[i].step.length; j++) {
uni.createSelectorQuery()
.in(this)
.select(`#stepStatus1${j}`)
.boundingClientRect(rect => {
// console.log(`Div的高度为:${rect.height}px`);
let sum = rect.height + 9
this.stepnewheight.push(sum)
})
.selectViewport()
.scrollOffset()
.exec();
}
}
},
重新命名两个数组进行存储主体的高度,进行在html部分进行循环输出,我为什么在后面加了一个9呢,因为我进行测试输出的高度总比我想要的高度小,所有我给他们固定加了9px。可以根据自己的需求进行加减
<!-- 模拟步骤条连接线(判断列表到最后一项后把线隐藏) -->
<view class="line" :style="'height:'+stepnewheight[index1]+'px'"
v-if="index !== list.length - 1 && item.title1!==''">
</view>
四、完整代码
<template>
<view class="mainStepOut">
<view class="stepOut">
<ul class="stepul">
<li class="stepItem">
<!-- 大圈部分 -->
<view v-for="(item,index) in list" :key="index">
<!-- 小圈部分 -->
<view class="step1" v-if="item.step.length>0" v-for="(item1,index1) in item.step" :key="index1">
<!-- 此处为小圆圈 -->
<view :class="index1 === 0 ?(index===0?'iconSmall active':'iconSmall'):'iconSmall'"></view>
<!-- 模拟步骤条连接线(判断列表到最后一项后把线隐藏) -->
<view class="line" :style="'height:'+stepnewheight[index1]+'px'"
v-if="index !== list.length - 1 && item.title1!==''">
</view>
<!-- 主题内容 -->
<view class="stepStatus1" :id="'stepStatus1'+index1">
<view :class="index1 === 0 ?(index===0?'titlecolor':'title'):'title'">
<text>{{item1.title}}</text>
<text>{{item1.date}}</text>
</view>
<view class="annotation">
<view class="item_person" v-html="item1.content">
<!-- {{item1.content}} -->
</view>
</view>
</view>
</view>
<view class="step1" v-if="item.title1!==''">
<!-- 此处为圆圈 -->
<view :class="item.step.length!==0?'icon':(index == 0 ?'icon1':'icon')"></view>
<!-- 模拟步骤条连接线(判断列表到最后一项后把线隐藏) -->
<view class="line" :style="'height:'+newheight[index]+'px'"
v-if="index !== list.length - 1">
</view>
<!-- 主题内容 -->
<view class="stepStatus" :id="'stepStatus'+index">
<view :class="item.step.length!==0 ? 'title':(index == 0 ?'titlecolor':'title')">
<view>{{item.title1}}</view>
<text v-if="item.title2">{{item.title2}}</text>
<text>{{item.date}}</text>
</view>
<view class="annotation">
<view class="item_person" v-html="item.content">
</view>
</view>
</view>
</view>
</view>
</li>
</ul>
</view>
</view>
</template>
<script>
import Api from '@/untils/api.js'
export default {
data() {
return {
list: [], //模拟数据
newheight: [],
stepnewheight: []
};
},
created() {
},
mounted() {
this.getProgressByAccountNo()
this.$nextTick(() => {
setTimeout(() => {
this.measureViewHeight()
}, 320)
})
},
methods: {
measureViewHeight() {
for (let i = 0; i < this.list.length; i++) {
uni.createSelectorQuery()
.in(this)
.select(`#stepStatus${i}`)
.boundingClientRect(rect => {
// console.log(`Div1的高度为:${rect.height}px`);
let sum = rect.height + 9
this.newheight.push(sum)
})
.selectViewport()
.scrollOffset()
.exec();
}
for (let i = 0; i < this.list.length; i++) {
for (let j = 0; j < this.list[i].step.length; j++) {
uni.createSelectorQuery()
.in(this)
.select(`#stepStatus1${j}`)
.boundingClientRect(rect => {
// console.log(`Div的高度为:${rect.height}px`);
let sum = rect.height + 9
this.stepnewheight.push(sum)
})
.selectViewport()
.scrollOffset()
.exec();
}
}
},
// 进度接口
getProgressByAccountNo() {
//接口
}
}
};
</script>
<style lang="scss" scoped>
.mainStepOut{
height: 100%;
overflow-y: auto;
}
.stepOut {
height: 100%;
padding-top: 40rpx;
width: 100%;
display: flex;
justify-content: space-between;
.stepul {
list-style: none;
width: 100%;
margin-left: -20rpx;
.stepItem {
width: 100%;
font-size: 32rpx;
position: relative;
border-left: #d7d7d7;
// display: flex;
.step1 {
display: flex;
width: 100%;
// height: 200rpx;
font-size: 32rpx;
position: relative;
border-left: #d7d7d7;
}
.icon {
width: 32rpx;
height: 32rpx;
flex: 0 0 32rpx;
border-radius: 50%;
background: #fff;
border: 4rpx solid #d7d7d7;
position: relative;
z-index: 888;
}
.icon1 {
width: 38rpx;
height: 38rpx;
border-radius: 50%;
flex: 0 0 38rpx;
right: 1.5px;
border: 4rpx solid #2E88FF;
position: relative;
z-index: 888;
background-color: #fff;
}
.icon1:before {
content: "";
position: absolute;
top: 5rpx;
left: 5rpx;
width: calc(100% - 8rpx);
height: calc(100% - 8rpx);
background-color: #2E88FF;
border-radius: 50%;
flex: 0 0 calc(100% - 8rpx);
}
.iconSmall {
width: 21rpx;
height: 21rpx;
border-radius: 50%;
flex: 0 0 21rpx;
background: #fff;
// border: 4rpx solid #d7d7d7;
position: relative;
left: 2.8px;
background: #808080;
z-index: 888;
margin-right: 10rpx;
}
.active {
background-color: #2E88FF;
border: 0;
}
.line {
position: absolute;
top: 12rpx;
// left: 13rpx;
left: 14rpx;
width: 4rpx;
// height: 200rpx;
background-color: #e2e2e2;
z-index: 111;
}
.stepStatus {
width: 100%;
padding: 0 25rpx;
background: #FAFAFA;
margin-bottom: 26rpx;
margin-left: 15rpx;
margin-right: 15rpx;
padding-top: 10rpx;
margin-top: -16rpx;
padding-bottom: 10rpx;
border-radius: 18rpx;
.annotation {
font-size: 25rpx;
color: #b0b0b0;
}
}
.stepStatus1 {
width: 100%;
padding: 0 25rpx;
background: #FAFAFA;
margin-bottom: 26rpx;
margin-left: 15rpx;
margin-right: 15rpx;
padding-top: 10rpx;
margin-top: -16rpx;
padding-bottom: 10rpx;
border-radius: 18rpx;
.annotation {
font-size: 25rpx;
color: #b0b0b0;
}
}
// 未进行
.title {
display: flex;
color: #808080;
margin-bottom: 10rpx;
view {
font-size: 30rpx;
// font-weight: 700;
margin-right: 18rpx;
}
text {
font-size: 25rpx;
display: flex;
flex-direction: column-reverse;
justify-self: end;
margin-right: 20rpx;
}
}
// 已进行
.titlecolor {
display: flex;
color: #2E88FF;
margin-bottom: 10rpx;
view {
color: #2E88FF;
font-size: 30rpx;
// font-weight: 700;
margin-right: 18rpx;
}
text {
font-size: 25rpx;
display: flex;
flex-direction: column-reverse;
justify-self: end;
margin-right: 20rpx;
}
}
}
}
}
</style>
接口数据结构
小结
如果感觉还不错的话可以关注博主哦,会持续更新的,谢谢~谢谢