-
1. JavaScript常用方法:
-
(1).计算百分比(保留两位小数)
/**
* 计算百分比(保留两位小数)
* @param {Number} num 分子
* @param {Number} total 分母
* @return {String} 百分比字符串
*/
getPercentileNumber(num, total) {
// 求百分比
num = parseFloat(num);
total = parseFloat(total);
if (isNaN(num) || isNaN(total)) {
return "-";
}
return total <= 0 ? "0%" : (Math.round(num / total * 10000) / 100.00) + "%";
}
-
(2).获取xx位随机数
/**
* 获取xx位随机数
* @param {Number} digit 获取随机数位数,如16位
* @param {Number/String} type 获取随机数返回值类型,可为数值型和字符串型
* @return {Number/String} 随机数返回值,可为数值型和字符串型
*/
getRandomNum(digit, type) {
let num = '';
for (let i = 0; i < digit; i++) {
num += Math.floor(Math.random() * 10);
}
switch (type) {
case String:
return num;
case Number:
return Number(num);
}
}
-
(3).获取xx位UUID
/**
* 获取UUID
* @param {Number} len 获取UUID长度,非必须
* @return {String} UUID内容
*/
getUUID(len) {
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
let uuid = [];
let radix = chars.length;
if (len) {
for (let i = 0; i < len; i++) {
uuid[i] = chars[0 | Math.random() * radix]
}
} else {
let r;
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '';
uuid[14] = '4';
for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join('');
}
-
(4).验证手机号是否合法
/**
* 验证手机号是否合法
* @param {Number} number 待验证手机号码
* @return {Boolean} 电话号码是否合法
*/
isPhoneNum(number) {
let phoneReg = /^1[3456789]\d{9}$/;
return phoneReg.test(number);
},
-
(5).验证身份证号是否合法
/**
* 验证身份证号是否合法
* @param {Number} number 待验证身份证号
* @return {Boolean} 身份证号码是否合法
*/
isCardNumber1(number) {
let cardReg = /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx])|([1−9]\d5\d2((0[1−9])|(10|11|12))(([0−2][1−9])|10|20|30|31)\d2[0−9Xx])$/;
return cardReg.test(number);
}
-
(6).切割数组返回新的数组
/**
* 接收一个数组和切割数值(即切割后子数组的元素个数),返回切割后的新数组
* @param {Array} data 待切割数组
* @param {Number} cutNum 切割后子数组的元素个数
* @return {Array} array 切割后的新数组
* */
cutArray (data, cutNum) {
if (data && cutNum > 0) {
let arrayItem = []
let array = []
let num = cutNum
data.map((item, index) => {
if (num > 0) {
arrayItem.push(item)
if (index === (data.length - 1)) {
array.push(arrayItem)
}
} else {
num = cutNum
array.push(arrayItem)
arrayItem = []
arrayItem.push(item)
if (index === (data.length - 1)) {
array.push(arrayItem)
}
}
num--
})
return array
}
}
-
(7).获取树形结构数据所有末级子节点数据
/**
* 获取树结构数据所有末级子节点数据
* 接收一个树形结构数据、需遍历字段名和返回字段名,返回所有末级子节点数据的数组
* @param {Array} data 待切割数组
* @param {traverseName} string 各节点需遍历的数据字段名
* @param {retrunName} string 返回数组的字段名
* @return {retrunName} array 所有末级子节点数据的数组
* */
export function getAllLeaf(treeData, traverseName, retrunName) {
let result = [];
function getLeaf(data) {
data.forEach(item => {
if (item[traverseName]) {
getLeaf(item[traverseName]);
} else {
result.push(item[retrunName]);
}
});
}
getLeaf(treeData);
return result;
}
-
2. css常用样式:
-
(1).滚动条:
主要属性:
::-webkit-scrollbar 滚动条整体部分,可以设置宽度
::-webkit-scrollbar-button 滚动条两端的按钮
::-webkit-scrollbar-track 外层轨道
::-webkit-scrollbar-track-piece 内层滚动槽
::-webkit-scrollbar-thumb 滚动的滑块
::-webkit-scrollbar-corner 边角
::-webkit-resizer 定义右下角拖动块的样式
常用设置:
// 设置滚动条及滚动槽宽度
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(22, 79, 129, 1);
}
&::-webkit-scrollbar-track {
border-radius: 0;
background: rgba(22, 79, 129, 0.3);
}
-
(2).背景颜色渐变:
background: linear-gradient
语法:background: linear-gradient(direction,color-stop1,color-stop2,...);
=> direction:用角度值指定渐变的方向(或角度);
=> color-stop1,color-stop2,...:用于指定渐变的起止颜色
浏览器兼容:
=> background: -webkit-linear-gradient(red,yellow,blue); /* Safari 5.1-6.0 */
=> background: -o-linear-gradient(red,yellow,blue); /* Opera 11.1-12.0 */
=> background: -moz-linear-gradient(red,yellow,blue); /* Firefox 3.6-15 */
=> background: linear-gradient(red,yellow,blue); /* 标准语法 */
参考博客:https://www.cnblogs.com/liangdecha/p/9797124.html
-
(3).非滚动列表:
HTML代码:
<div class="list-box">
<span>人员信息统计</span>
<div class="list-box-child">
<ul class="list-box-child-title">
<li class="title-item item-1">姓名</li>
<li class="title-item item-2">性别</li>
<li class="title-item item-3">年龄</li>
<li class="title-item item-4">联系电话</li>
</ul>
<ul v-for="item in 20" :key="item" class="list-box-child-content">
<li>张三</li>
<li>男</li>
<li>24</li>
<li>18888888888</li>
</ul>
</div>
</div>
CSS样式代码(环境需支持sass编译):
.list-box {
width: 100%;
height: auto;
padding: 16px;
background:rgba(251,251,251,1);
span {
font-size:18px;
font-family:PingFangSC-Semibold,PingFang SC;
font-weight:600;
color:rgba(70,81,102,1);
line-height:60px;
}
&-child {
width: 100%;
height: auto;
background: white;
&-title {
width: 100%;
height: 48px;
display: flex;
.title-item {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
border-right: 1px solid white;
flex-grow: 1;
font-size:16px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(70,81,102,1);
line-height:22px;
}
.title-item:last-child {
border-right: none;
}
.item-1 {
background:rgba(255,238,212,1);
border-right: 1px solid white;
border-top-left-radius: 5px;
}
.item-2 {
background:rgba(249,232,237,1);
border-right: 1px solid white;
}
.item-3 {
background:rgba(232,248,249,1);
border-right: 1px solid white;
}
.item-4 {
background:rgba(232,234,249,1);
border-top-right-radius: 5px;
}
}
&-content {
width: 100%;
height: 30px;
display: grid;
grid-template-columns: .72fr .71fr .73fr 1fr;
li {
display: flex;
justify-content: center;
align-items: center;
font-size:14px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(70,81,102,1);
line-height:20px;
}
}
&-content:nth-child(odd) {
background:rgba(255,255,255,1);
}
&-content:nth-child(even) {
background:rgba(246,246,246,1);
}
}
}
效果截图(数据为模拟数据):
-
(4).非滚动奇偶行奇偶列不同背景色列表
HTML代码:
<div class="list-box">
<span>各省分布情况(单位: 人)</span>
<ul v-for="(items, index) in data" :key="'data' + index">
<li v-for="(item, index) in items" :key="'itemData' + index"><label>{{ item.city }}</label><span>{{ item.value }}人</span></li>
</ul>
</div>
CSS样式代码(环境需支持sass编译):
.list-box {
width: 100%;
height: auto;
padding: 16px;
background:rgba(251,251,251,1);
span {
font-size:18px;
font-family:PingFangSC-Medium,PingFang SC;
font-weight:500;
color:rgba(70,81,102,1);
line-height:25px;
}
ul {
margin-top: 10px;
width: 100%;
height: 30px;
display: flex;
li {
width: 50%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 3px 5px;
label {
font-size:16px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(70,81,102,1);
line-height:22px;
}
span {
font-size:16px;
font-family:PingFangSC-Semibold,PingFang SC;
font-weight:600;
color:rgba(70,81,102,1);
line-height:22px;
}
}
}
ul:nth-child(even) {
li:nth-child(odd) {
background: rgba(232, 248, 249, 0.5);
}
li:nth-child(even) {
background: rgba(255, 246, 233, 0.3);
}
}
ul:nth-child(odd) {
li:nth-child(even) {
background: rgba(232, 248, 249, 0.5);
}
li:nth-child(odd) {
background: rgba(255, 246, 233, 0.3);
}
}
}
数据(数据为模拟数据):
data: [[{
city: '吉林省',
value: 29
}, {
city: '甘肃省',
value: 41
}], [{
city: '西藏自治区',
value: 13
}, {
city: '山西省',
value: 23
}], [{
city: '贵州省',
value: 31
}, {
city: '陕西省',
value: 61
}], [{
city: '山东省',
value: 44
}, {
city: '湖北省',
value: 20
}], [{
city: '湖南省',
value: 42
}, {
city: '河北省',
value: 45
}], [{
city: '河南省',
value: 25
}, {
city: '海南省',
value: 33
}], [{
city: '江西省',
value: 47
}, {
city: '浙江省',
value: 49
}], [{
city: '安徽省',
value: 35
}, {
city: '江苏省',
value: 45
}], [{
city: '辽宁省',
value: 29
}]]
效果截图:
-
(5).基于ViewUI的合并行列Table实例
HTML代码:
<div class="table-box">
<div class="table-title">
<span class="title">
基于ViewUI的合并行列Table
</span>
<span class="title">
数据为2019年数据,按人口排序
</span>
</div>
<div class="table-content">
<Table border :columns="tableTitle" :data="tableContentData" :max-height="800" :span-method="handleSpan" :disabled-hover="true"></Table>
</div>
</div>
CSS样式代码(环境需支持sass编译):
<style scoped lang="scss">
.table-box {
width: 100%;
height: 100%;
padding: 80px;
overflow-y: auto;
.table-title {
width: 100%;
height: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.title {
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(29, 29, 28, 1);
}
.title:last-child {
font-size: 18px;
}
}
.table-content {
width: 100%;
height: 800px;
}
}
</style>
<style>
.operating-box {
display: flex;
justify-content: space-between;
padding: 0 50px;
}
.modal-content {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(29, 29, 28, 1);
}
</style>
数据(数据为网络查询):
data() {
const self = this
return {
// 表格title数据
tableTitle: [
{
title: '国家',
key: 'country',
align: 'center'
}, {
title: '省',
key: 'province',
align: 'center'
}, {
title: '市',
key: 'city',
align: 'center'
}, {
title: '人口(单位:万)',
key: 'population',
align: 'center'
}, {
title: '面积(单位:平方公里)',
key: 'area',
align: 'center'
}, {
title: '操作',
key: 'operating',
align: 'center',
render: function (h, params) {
return h('div', {
class: 'operating-box'
}, [
h('Button', {
props: {
type: 'primary',
// render函数中调用方法传递额外参数
// 'on-remove': (file, fileList) => self.onRemove(file, fileList, params.row.indexId),
// 'on-success': (response, file, fileList) => self.uploadSuccess(response, file, fileList, params.row.indexId),
},
nativeOn: {
click() {
self.viewInf(params.row)
}
},
// on: {
// 'on-change'() {
// }
// },
class: {},
style: {}
}, '查看'),
h('Button', {
props: {
type: 'error'
},
nativeOn: {
click() {
self.deleteItem(params.row._index)
}
},
class: {},
style: {}
}, '删除')
])
}
}
],
// 表格数据
tableContentData: [
{
country: '中国',
province: '贵州省',
city: '毕节',
population: '660.61',
area: '26852',
operating: '-'
}, {
country: '-',
province: '-',
city: '遵义',
population: '619.21',
area: '30763',
operating: '-'
}, {
country: '-',
province: '-',
city: '贵阳',
population: '462.18',
area: '8034',
operating: '-'
}, {
country: '-',
province: '-',
city: '黔东南',
population: '348.54',
area: '30339',
operating: '-'
}, {
country: '-',
province: '-',
city: '黔南',
population: '324.22',
area: '26195',
operating: '-'
}, {
country: '-',
province: '-',
city: '铜仁',
population: '312.24',
area: '18003',
operating: '-'
}, {
country: '-',
province: '-',
city: '六盘水',
population: '288.99',
area: '9914',
operating: '-'
}, {
country: '-',
province: '-',
city: '黔西南',
population: '281.12',
area: '16805',
operating: '-'
}, {
country: '-',
province: '-',
city: '安顺',
population: '231.35',
area: '9267',
operating: '-'
}, {
country: '-',
province: '甘肃省',
city: '兰州',
population: '361.62',
area: '13085.6',
operating: '-'
}, {
country: '-',
province: '-',
city: '天水',
population: '326.25',
area: '14392',
operating: '-'
}, {
country: '-',
province: '-',
city: '定西',
population: '269.86',
area: '19609',
operating: '-'
}, {
country: '-',
province: '-',
city: '陇南',
population: '256.77',
area: '27923',
operating: '-'
}, {
country: '-',
province: '-',
city: '庆阳',
population: '221.12',
area: '27119',
operating: '-'
}, {
country: '-',
province: '-',
city: '平凉',
population: '206.80',
area: '11325',
operating: '-'
}, {
country: '-',
province: '-',
city: '临夏回族自治州',
population: '194.67',
area: '8169',
operating: '-'
}, {
country: '-',
province: '-',
city: '武威',
population: '181.51',
area: '33249',
operating: '-'
}, {
country: '-',
province: '-',
city: '白银',
population: '170.88',
area: '21209',
operating: '-'
}, {
country: '-',
province: '-',
city: '张掖',
population: '119.95',
area: '40874',
operating: '-'
}, {
country: '-',
province: '-',
city: '酒泉',
population: '109.59',
area: '192000',
operating: '-'
}, {
country: '-',
province: '-',
city: '甘南藏族自治州',
population: '68.01',
area: '40201',
operating: '-'
}, {
country: '-',
province: '-',
city: '金昌',
population: '46.41',
area: '8896',
operating: '-'
}, {
country: '-',
province: '-',
city: '嘉峪关',
population: '23.19',
area: '2935',
operating: '-'
}
]
}
}
JS方法代码:
// 合并行列
handleSpan({row, column, rowIndex, columnIndex}) {
// handleSpan: function ({rowIndex, columnIndex}) {
const self = this
// 第一列
let length = self.tableContentData.length
if (rowIndex === 0 && columnIndex === 0) {
return [length, 1];
} else if (rowIndex >= 1 && rowIndex < length && columnIndex === 0) {
return [0, 0];
}
// 第二列
if (rowIndex === 0 && columnIndex === 1) {
return [9, 1];
} else if (rowIndex >= 1 && rowIndex <= 8 && columnIndex === 1) {
return [0, 0];
}
if (rowIndex === 9 && columnIndex === 1) {
return [14, 1];
} else if (rowIndex >= 10 && rowIndex <= length - 1 && columnIndex === 1) {
return [0, 0];
}
},
// 查看信息
viewInf(data) {
const self = this
self.$Modal.info({
title: '详细信息',
content: '<div class="modal-content">国家:' + data.country + '</br>' + '省份:' + data.province + '</br>' + '市州:' + data.city + '</br>' + '人口:' + data.population + ' 万人</br>' + '面积:' + data.area + ' 平方公里</div>'
});
},
// 删除数据
deleteItem(index) {
const self = this
self.$Modal.confirm({
title: '您确认要删除该条数据吗?',
content: '确认后仅删除人口及面积数据',
onOk: () => {
self.tableContentData[index].population = '-'
self.tableContentData[index].area = '-'
},
onCancel: () => {
// 取消
}
});
}
效果截图:
1.初始效果:
2.点击查看详细信息效果:
3.点击删除效果(将某市州人口及面积数据修改为“-”):
-
3.常用解决方案:
(1).Android和IOS系统页面底部输入框获取焦点后向上滑至可视区域:
HTML代码:
<div class="wrapper">
<div class="form">
<div v-for="item in 20" :key="item" class="form-group">
<label>手机号</label>
<input type="number" placeholder="填写手机号" @focus="onFocus" @blur="onBlur">
</div>
</div>
</div>
JS方法代码:
// 获取焦点
onFocus () {
window.addEventListener('resize', () => {
if (document.activeElement.tagName === 'INPUT') {
window.setTimeout(() => {
document.activeElement.scrollIntoViewIfNeeded();
}, 0);
}
})
},
// 失去焦点
onBlur () {
// 软键盘收起的事件处理
let ua = window.navigator.userAgent;
if (!!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
// $alert('ios端');
var currentPosition, timer;
var speed = 1;
timer = setInterval(function() {
currentPosition = document.documentElement.scrollTop || document.body.scrollTop;
currentPosition -= speed;
window.scrollTo(0, currentPosition); // 页面向上滚动
currentPosition += speed;
window.scrollTo(0, currentPosition); // 页面向下滚动
clearInterval(timer);
}, 100);
}
}
CSS样式代码(环境需支持sass编译):
.wrapper {
padding: 3px 16px;
}
.form-group {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 0;
border-bottom: 1px solid #eee;
label, input {
font-size: 14px;
}
input {
text-align: right;
}
}
效果动图:
(2).固定头部部分,内容部分滚动(吸顶):
提示:此处大家或许会有疑问,既然用了Vant的组件了,为什么不用Vant的吸顶完成呢?你以为我不想节省时间用Vant的吸顶吗?我用了,但是手机系统存在兼容性问题,用Vant的还是存在风险的。而且我发现用Vant的吸顶功能屏幕滚动时存在页面跳动,体验很不友善。
再次提示:有时候直接复制这些代码可能不会成功滚动,首先应该排除一下样式类为main-content的节点及其所有父节点(直到body节点)是否都设置了height: 100%;的样式属性。没有设置的话加上去试试。
HTML代码(搜索等部分基于Vant开发):
<div class="wrapper">
<div class="main-content">
<!--固定头部部分-->
<div class="header">
<!-- 搜索部分 -->
<div class="header-search">
<form action="/">
<van-search
v-model="searchValue"
background="#FBFBFB"
placeholder="请输入关键词搜索"
:clearable="false"
show-action
shape="round"
@input="searchValueChange"
@search="onSearch"
class="header-search-item"
>
<div v-if="searchValue" slot="right-icon" class="van-icon van-icon-clear van-icon-clear-self"
@click="claerSearch"></div>
<div slot="action" class="header-search-item-text" @click="onSearch">搜索</div>
</van-search>
</form>
</div>
<!-- 分类title部分 -->
<div class="header-title">
<ul>
<li v-for="(item, index) in contentTitleList" :key="'contentTitle' + index" tabindex="1" :class="{ 'type-content-selected': selectIndex === index }" @click="typeChange(item.code, index)">{{ item.value }}</li>
</ul>
</div>
</div>
<!--可滚动内容-->
<div class="content">
<ul v-for="item in 30" :key="item">
<li>张三</li>
<li>男</li>
<li>24</li>
<li>18888888888</li>
</ul>
</div>
</div>
</div>
数据:
// 未进行分类选择
selectIndex: 0,
// 分类标题列表
contentTitleList: [{
code: 0,
value: '贵州省'
}, {
code: 1,
value: '甘肃省'
}, {
code: 2,
value: '青海省'
}, {
code: 3,
value: '海南省'
}, {
code: 4,
value: '陕西省'
}, {
code: 5,
value: '山西省'
}, {
code: 6,
value: '湖南省'
}, {
code: 7,
value: '河南省'
}, {
code: 8,
value: '江西省'
}]
JS方法代码:
// 切换分类
typeChange (data, index) {
const self = this
self.selectIndex = index
}
CSS样式代码(环境需支持sass编译):
.wrapper {
padding: 0;
height: 100%;
}
.main-content {
display: flex;
flex-direction: column;
height: 100%;
background: rgba(251, 251, 251, 1);
.header {
width: 100%;
height: auto;
flex-shrink: 0;
margin-bottom: auto;
padding: 12px 16px 0 16px;
&-search {
width: 100%;
height: 36px;
padding: 1px 0 1px 0;
.van-search__action:active {
background: rgba(251, 251, 251, 1);
}
&-item {
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(165, 170, 179, 1);
line-height: 22px;
padding: 0;
.van-cell {
display: flex;
align-items: center;
}
&-text {
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(70, 126, 234, 1);
line-height: 22px;
margin-left: 8px;
}
}
.van-icon-clear-self {
color: #CCD2D6;
}
}
&-title {
width: 100%;
height: 26px;
margin-top: 22px;
padding: 1px 0 1px 0;
overflow-y: hidden;
overflow-x: auto;
/*border: 1px solid red;*/
&::-webkit-scrollbar {
display: none;
}
.type-content-selected {
border-radius: 1px;
border-bottom: 2px solid #4A81EE;
color: rgba(74, 129, 238, 1) !important;
}
ul {
white-space: nowrap;
li {
display: inline-table;
vertical-align: auto;
font-size: 14px;
margin-right: 20px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(70, 81, 102, 1);
line-height: 20px;
}
}
}
}
.content {
width: 100%;
height: auto;
overflow: auto;
padding: 0 16px 16px 16px;
margin-top: 6px;
background: rgba(251, 251, 251, 1);
ul {
width: 100%;
height: 30px;
display: grid;
grid-template-columns: .72fr .71fr .73fr 1fr;
li {
display: flex;
justify-content: center;
align-items: center;
font-size:14px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(70,81,102,1);
line-height:20px;
}
}
ul:nth-child(odd) {
background:rgba(255, 238, 212, 0.6);
}
ul:nth-child(even) {
background:rgba(232, 248, 249, 0.6);
}
}
}
效果动图:
(3).input输入框在IOS系统下默认内容在垂直方向上没有居中:
需要添加::-webkit-input-placeholder样式并设置其padding-top属性,具体设置多少在实际情况下修改哦
例如:
/* 使用webkit内核的浏览器 */
::-webkit-input-placeholder {
padding-top: 0.12rem;
}
(4).input输入框在IOS10系统下无法选中获取焦点(不能弹出输入法):
需要在input输入框加-webkit-user-select: text的属性;若无法保证其被优先加载,最好提高其加载优先级。
例如:
.main-content .header-search-item input {
-webkit-user-select: text !important;
}
(5).Vue.js移动端项目引入第三方组件库(Vant),引入Vant组件的页面在本地环境样式正常,打包部署后样式加载和本地一致,但样式布局错乱:
造成此问题的原因:有可能是在main.js导入路由顺序在导入Vant组件库之后造成的,具体原因待查。如果遇到如标题的问题,可以先这样尝试解决。
例如: