项目经验总结
本文内容概述
根据本文总结的通用解决方案,以后在项目初期就开始应用,随着项目的进展参与开发者会越来越感到轻松,只需对接需求,开发需求;基本常用的方法即时调用,项目维护也有迹可循,高效完成开发任务的同时,提高了生产力。
项目中频繁定义时间相关方法的问题解决方案
像类似这种项目,在web页面上展示的时间格式一般为:2023-08-12 12:20:00
或者2023-08-12 12:20
等;时间参数传给后端接口时可能是时间戳形式,也可能是其他。
在项目中几十个组件里都有定义格式化时间的函数,而且定义了很多种不同的函数,这些组件里都需要先引入moment.js
后者day.js
,很低效,维护起来很麻烦。
省心又可便捷使用的方案是,把这些方法统一定义在Vue实例的某个属性上,比如$utils
本项目中定义了如下通用时间相关方法:
import dayjs from 'dayjs'
// 格式化时间
function formatDate (t) {
return dayjs(t || new Date()).format('YYYY-MM-DD HH:mm:ss')
}
// 格式化时间
function formatShortDate (t) {
return dayjs(t || new Date()).format('YYYY-MM-DD')
}
// 最近一周
function recentWeek () {
return [dayjs().subtract(1, 'week').format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]
}
// 最近一天
function recentDay () {
return [dayjs().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]
}
// 最近一天
function recentDayDate () {
return [dayjs().subtract(1, 'day').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
}
// 获取当前年月日:2023-03-23
function getYearMonthDay () {
return dayjs(new Date()).format('YYYY-MM-DD')
}
// 获取当前周几:星期五
function getWeeks () {
const weekObj = {
0: '星期日',
1: '星期一',
2: '星期二',
3: '星期三',
4: '星期四',
5: '星期五',
6: '星期六'
}
return weekObj[dayjs().day()]
}
// 获取24h制的时分:16:24
function getHourMinute () {
return dayjs(new Date()).format('HH:mm')
}
然后挂载在Vue实例全局上
// 所有的公共方法挂载在Vue.prototype.$utils上
import * as utils from '@/utils/index.js'
Vue.prototype.$utils = utils
在组件中使用时,不用再次引入moment.js
、day.js
甚至不用引入对应的方法即可使用:
scanInBaginfo({ time: this.$utils.formatDate() }).then(res => {})
项目中频繁定义字体样式的问题解决方案
在项目进行Web开发复盘时,注意到有几百次定义类似css的地方:
font-family: PingFangSC-Semibold;
font-size: 18px;
color: rgba(0, 0, 0, 0.70);
font-weight: 600;
因为这个项目中有的页面是放在pc上,有的是大屏上,有的在PAD上,甚至有的是在明眸设备上展示,所以设计师设计的各种字体,这是需求决定的改变不了。
需求是没法改了,着手在开发上进行优化吧。
最终解决方案是使用Sass写一个全局的mixin
,这个mixin
可以传入字体、字号、颜色、字体粗细值;
// 文字样式
@mixin fontStyle ($family: MicrosoftYaHeiUI, $size: 16px, $opacity: 1, $weight: 400) {
font-family: $family;
font-size: $size;
color: rgba(0, 0, 0, $opacity);
font-weight: $weight;
}
使用时不需要任何的引入,直接@include
使用,如下
@include fontStyle(PingFangSC-Semibold, 18px, 0.7, 600);
正常使用之前需要两个配置插件style-resources-loader、vue-cli-plugin-style-resources-loader
在vue.config.js
文件中配置如下:
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
// 路径根据具体需求更改
path.resolve(__dirname, 'src/style/mixin.scss')
]
}
}
重启项目即可使用全局Sass minxin
,需要传递参数的css
片段都可才有此方式处理!
项目中其他频繁定义样式的解决方案-通用按钮、单行省略号、多行省略号、滚动条样式
项目中类似于处理字体样式的方案,还有通用按钮、单行省略号、多行省略号、滚动条样式等通用css
片段,这些和字体样式不同的地方是,不需要传入参数变量;所以不需要使用@mixin
,甚至不需要使用sass
,直接全局定义css样式,组件内直接使用即可。
本项目中如下:
/* 文字超出省略号省略号 */
.ellipsis {
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
overflow: hidden;
}
/* 文字2行超出省略号 */
.ellipsis-two {
overflow: hidden;
text-overflow: ellipsis;
display: box;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
/* 文字3行超出省略号 */
.ellipsis-three {
overflow: hidden;
text-overflow: ellipsis;
display: box;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
/* 美化滚动条样式,添加class样式.scrollbar */
.scrollbar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.scrollbar::-webkit-scrollbar-track {
background: #86a7bc;
border-radius: 2px;
}
.scrollbar::-webkit-scrollbar-thumb {
background: #177fd9;
border-radius: 6px;
}
.scrollbar::-webkit-scrollbar-thumb:hover {
background: #333;
}
.scrollbar::-webkit-scrollbar-corner {
background: #179a16;
}
/* plain版 美化滚动条样式,添加class样式.scrollbar-plain */
.scrollbar-plain::-webkit-scrollbar {
width: 2px;
height: 2px;
}
.scrollbar-plain::-webkit-scrollbar-track {
border-radius: 2px;
}
.scrollbar-plain::-webkit-scrollbar-thumb {
border-radius: 2px;
}
/* 通用绿色按钮 */
.green-button {
.el-button {
max-width: 12.2rem;
}
.el-button--primary {
border-color: #01ae97;
background-color: #01ae97;
border-radius: 4px;
}
.el-button--primary:hover {
border-color: #1bc4ae;
background-color: #1bc4ae;
}
.el-button--default {
border: 1px solid #01ae97;
border-radius: 4px;
color: #01ae97;
}
.el-button--default:hover:not(.is-disabled) {
border-color: #1bc4ae;
background: #ffffff;
color: #1bc4ae;
}
.el-button--primary:hover:not(.is-disabled) {
border-color: #1bc4ae;
background: #1bc4ae;
color: #ffffff;
}
.el-button.is-disabled.el-button--default:not(.is-icon) {
border-color: #01ae97;
background-color: #ffffff;
color: #01ae97;
opacity: 0.4;
}
}
// toast样式
.toast-tip-modify-style {
width: 50% !important;
font-size: 3.6rem !important;
line-height: 4.8rem !important;
}
项目中数字千分位展示的通用方法
项目中大屏页面,会展示很多数字,有的数字的值会很大,为了方便清晰观看,设计师建议展示为千分位计数方式,由于有多个地方使用此方法,所以全局定义此方法,也是挂载在Vue.prototype.$utils
。
定义如下:
function toThousands (n) {
let isFu = false
let isSmall = false
n = Number(n).toFixed(2)
// 考虑负数的情况
if (n < 0) {
n = Math.abs(n)
isFu = true
}
// 考虑小数情况(业务中保留两位)
let s = ''
n = n.toString()
if (n.indexOf('.') !== -1) {
isSmall = true
s = n.slice(-3)
n = n.slice(0, n.length - 3)
}
let num = n || '0'
let result = ''
while (num.length > 3) {
result = ',' + num.slice(-3) + result
num = num.slice(0, num.length - 3)
}
if (num) {
result = num + result
}
if (isFu) {
result = '-' + result
}
if (isSmall) {
result += s
}
return result
}
组件内不需要引入,使用如下:
<span class="right-text" :title="`${$utils.toThousands(item.right)}元`">
{{ $utils.toThousands(item.right) }}元
</span>
项目中使用vue-seamless-scroll
插件滚动列表,造成点击失效问题的解决方案
在此项目中用到了vue-seamless-scroll
插件,可以使列表无限滚动,给页面添加一些灵动感,并可滚动展示列表内容,用户不用使用鼠标手动滚动查看。
在使用了此插件的列表上,点击某行数据,添加点击事件时,发现失效了。
分析一下其生成的dom
结构,发现是列表每行的dom
被vue-seamless-scroll
插件遮挡了,并且这个遮挡dom
是随着列表的不断滚动动态刷新的。
在采用事件的冒泡捕获机制、事件代理以及用户自定义属性的方法解决:
在dom
上自定义属性 :data-item
<div class="t-body scrollbar-plain" @click="showVedio($event)">
<vueSeamlessScroll :data="dataList" :class-option="classOption">
<div class="item-line" v-for="(item, index) in dataList" :key="index" :data-item="JSON.stringify(item)">
<div class="order-cls ellipsis">{{ index + 1 }}</div>
...
</div>
</vueSeamlessScroll>
</div>
在点击事件的回调方法中获取自定义属性的数据:
// 展示视频详情
showVedio (e) {
// 解决vue-seamless-scroll滚动时,点击事件失效的问题;事件代理;
if (e.target.parentElement.classList.contains('item-line')) {
this.itemdata = JSON.parse(e.target.parentElement.dataset.item)
...
}
}
使用repeat(auto-fill, minmax(320px, 1fr))
方式解决页面内容自适应响应式布局问题
之前实现页面内容自适应页面尺寸变化的方案可能是如下几种:
媒体查询
/* 小屏幕(平板,大于等于 768px) */
@media (min-width: @screen-sm-min) { ... }
/* 中等屏幕(桌面显示器,大于等于 992px) */
@media (min-width: @screen-md-min) { ... }
/* 大屏幕(大桌面显示器,大于等于 1200px) */
@media (min-width: @screen-lg-min) { ... }
bootstrap
<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->
<div class="row">
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>
elementUI
<el-row :gutter="10">
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple"></div></el-col>
<el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple"></div></el-col>
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
- 此项目中使用了
Grid
布局系统中方案repeat(auto-fill, minmax(320px, 1fr))
.assemble-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 16px;
margin-top: 16px;
}
到这里本文就结束了,感谢阅读,希望能对你有所帮助!