有以下功能逻辑,实现了一个时间轴组件,点击+、-号后像地图那样放大组件以显示不同的UI。
默认显示年月:
当点击一下加号时切换为年:
当点击减号时切换为日:
即加号、减号点击就是在年月日显示进行切换。给Scrollview添加了鼠标滚动事件:当切换日期显示时滚轮滚动时,scrollview的滚动条没有反应,就很奇葩。。。
<el-scrollbar ref="scrollContainer" class="right-view" horizontal @wheel.native.prevent="handleScroll">
页面代码为:
<template> <div class="flex-row container-view"> <div class="left-view"> <div class="placeholder-view"></div> <div class="switch-view flex-column jc-between"> <div class="h-view flex-row jc-around"> <i class="btns-view flex-row el-icon-timer" style="justify-content: center;" @click="toCurrentAction"></i> <i class="btns-view flex-row el-icon-circle-plus-outline" style="justify-content: center;" @click="toDayAction"></i> <i class="btns-view flex-row el-icon-remove-outline" style="justify-content: center;" @click="toYearAction"></i> </div> <div class="flex-row w-100" style="height: 30px;"> <div class="flex-column" style="width: 12px;"> <div class="flex-column" style="height: 15px;justify-content:flex-end"> <i style="width: 8px;height:8px;background-color:#a0a0a0;border-radius:4px"></i> <i style="width: 1px;height:4px;background-color:#a0a0a0;"></i> </div> <div class="flex-column" style="height: 15px;justify-content:flex-start"> <i style="width: 1px;height:4px;background-color:#a0a0a0;"></i> <i style="width: 8px;height:8px;background-color:#a0a0a0;border-radius:4px"></i> </div> </div> <div class="flex-column"> <span class="flex-column" style="font-size:10px;color:#a0a0a0;height:15px;line-height:15px">自2021.01.01</span> <span class="flex-column" style="font-size:10px;color:#a0a0a0;height:15px;line-height:15px">至2024.10.31</span> </div> </div> </div> </div> <el-scrollbar ref="scrollContainer" class="right-view" horizontal @wheel.native.prevent="handleScroll"> <template v-if="viewMode == 1"> <div class="date-view flex-column" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row w-100" style="height: 20px;"> <p v-for="(item, index) in yearList" :key="index" style="color:#a0a0a0;font-size:13px;" :style="{ width: (monthList.length / yearList.length * gutterGap) + 'px' }">{{ item.date }} </p> </div> <div class="flex-row" style="height: 20px;"> <p v-for="item in monthList" :style="{ width: `${gutterGap}px` }" style="color:#505050;font-size:13px;">{{ item.month + '月' }}</p> </div> </div> <div class="switch-view bd-blue" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row h-100" style="position: relative;"> <p class="sep-h-line" v-for="(item, kdex) in monthList" :style="{ left: (kdex * gutterGap + 10) + 'px' }"></p> </div> </div> </template> <template v-else-if="viewMode == 2"> <div class="date-view flex-column" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row w-100" style="height: 20px;"> <p v-for="(item, index) in yearList" :key="index" style="color:#a0a0a0;font-size:13px;" :style="{ width: (monthList.length / yearList.length * gutterGap) + 'px' }">{{ item.date }} </p> </div> <div class="flex-row" style="height: 30px;"> <div v-for="(item, mdex) in monthList" class="flex-column" :key="mdex"> <span :style="{ width: `${gutterGap}px` }" style="color:#505050;font-size:13px;">{{ item.month + '月' }} </span> <div class="flex-row"> <span style="font-size: 12px;color:#505050;text-align:center;" v-for="(dtem, ddex) in daysList(item)" :key=ddex :style="{ width: `${gutterGap / monthDays(item)}px` }"> {{ dtem.label }} </span> </div> </div> </div> </div> <div class="switch-view bd-blue" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row h-100" style="position: relative;"> <p class="sep-h-line" v-for="(item, kdex) in monthList" :style="{ left: (kdex * gutterGap + 10) + 'px' }"></p> </div> </div> </template> <template v-else> <div class="date-view flex-column" style="justify-content:flex-end" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row w-100" style="height: 20px;"> <p v-for="(item, index) in yearList" :key="index" style="color:#a0a0a0;font-size:13px;" :style="{ width: (monthList.length / yearList.length * gutterGap) + 'px' }">{{ item.date }} </p> </div> </div> <div class="switch-view bd-blue" :style="{ width: (yearList.length / yearList.length * monthList.length * gutterGap) + 'px' }"> <div class="flex-row h-100" style="position: relative;"> <p class="sep-h-line" v-for="(item, kdex) in monthList" :style="{ left: (kdex * gutterGap + 10) + 'px' }"></p> </div> </div> </template> </el-scrollbar> </div> </template> <script> import { getDaysInMonth } from '@/utils/index.js' export default { data() { return { gutterGap: 120, scrollWith: 0, //0年 1月 2日 viewMode: 1, yearList: [{ date: '2021' }, { date: '2022' }, { date: '2023' }, { date: '2024' }], monthList: [], dayList: [{ "day": '1' }, { "day": '2' }, { "day": '3' }, { "day": '4' }] } }, created() { this.autoMonths() this.$nextTick(() => { let atarget = document.querySelector(".right-view") this.scrollWith = atarget.offsetWidth }) }, computed: { scrollWrapper() { return this.$refs.scrollContainer.$refs.wrap } }, mounted() { this.$nextTick(() => { this.$refs.scrollContainer.update() }) }, methods: { autoMonths() { this.monthList.removeAllObject() this.yearList.forEach((e, index) => { for (let a = 0; a < 12; a++) { let d = e.date + '-' + (a < 10 ? '0' : '') + (a + 1) let k = { month: a + 1, date: d } this.monthList.push(k) } }) }, handleScroll(e) { const eventDelta = e.wheelDelta || -e.deltaY * 40 const $scrollWrapper = this.scrollWrapper let scrolled = $scrollWrapper.scrollLeft + eventDelta / 4 $scrollWrapper.scrollLeft = scrolled this.$emit("scrolled", scrolled) }, toCurrentAction() { }, toDayAction() { this.viewMode = Math.max(0, this.viewMode - 1) if (this.viewMode == 1) { //显示月 this.gutterGap = 120 } else { //显示年 this.gutterGap = 30 } let vl = Math.max(this.scrollWith / (this.yearList.length * 12), this.gutterGap) vl = Math.ceil(vl) this.gutterGap = vl this.$nextTick(() => { this.$refs.scrollContainer.update(); }); }, toYearAction() { //单位年 this.viewMode = Math.min(2, this.viewMode + 1) if (this.viewMode == 1) { //显示月 this.gutterGap = 120 } else { //显示日 this.gutterGap = 720 } this.$nextTick(() => { this.$refs.scrollContainer.update(); }); }, monthDays(m) { let c = getDaysInMonth(m.date) return c }, daysList(m) { let c = getDaysInMonth(m.date) let list = [] for (let i = 0; i < c; i++) { let e = { label: (i + 1) + '', value: m.date + (i < 10 ? '0' : '') + (i + 1) } list.push(e) } return list } } } </script> <style lang="scss" scoped> .flex-row { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; } .flex-column { display: flex; flex-direction: column; justify-content: flex-start; align-items: center; } .container-view { min-height: 150px; height: 150px; max-height: 150px; } .left-view { width: 100px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; } .jc-around { justify-content: space-around; } .jc-between { justify-content: space-between; } .right-view { width: calc(100% - 100px); background-color: transparent; } .date-view { width: 100%; height: 50px; } .placeholder-view { height: 50px; background-color: transparent; } .switch-view { background-color: #f3f5f9; height: 100px; } .h-view { background-color: white; margin: 5px; } .btns-view { width: 24px; height: 24px; background-color: transparent; } .bd-blue { border-top: 20px solid #0286ef; } .sep-h-line { position: absolute; width: 1px; height: 100%; background-color: #e2e7fb; } ::v-deep { .is-horizontal { height: 10px !important; left: 0px; display: inline !important; margin-top: 6px; } } </style>
因scrollview内的内容不断的进行变化,他的contentsize也是动态变化,但此时当切换后鼠标滚轮无法触发Scrollview的滚动条一块儿跟着滑动。
修正方案为:强行更新scrollview,出现的问题随之修复。
this.$nextTick(() => { this.$refs.scrollContainer.update(); });