前言:我使用的是vue+element admin,里面用的组件都来自于element.eleme.io
备注:host:如果配置为127.0.0.1,只能本机访问,如果配置为0.0.0.0,则可以局域网访问
如果想内网穿透:报 invalid host header,只需在webpack.dev.conf.js加上
devServer: {
disableHostCheck: true,
}
以下都是我使用过程中用到的小窍门我会记录下来:
1.获取表格tableData的索引值,注意不是每列里的key,是index
使用:scope.$index
效果:比如我想要只在第一列显示增加按钮
那我可以加一个
v-if="scope.$index === 0"
效果:
2.判断对象是否为空可以用ES6语法判断它的长度
Object.keys(this.form.paramList).length === 0
3.vue在数组指定位置追加列
this.tableDataGzh.splice(-1, 0, list);//在倒数第二列追加
实现效果在追加和删除:
4.element里togglerowselection无效爬坑
官网demo: http://element-cn.eleme.io/#/duo-xuan
我想在打开编辑框时默认就选中为true的数据,可是官方demo没有详细说这个咋用,我一直以为那个row是对应的行数字
官方代码:
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
我测试官方的row就是数字,然后我在我的项目里这样写无效果。
解决代码:
this.tableDataGzh.map((tableinfo, index) => {
if (tableinfo['isApi'] === true) {
this.$nextTick(() => { // 延迟回调
console.log(this.$refs["multipleTable"])
this.$refs["multipleTable"].toggleRowSelection(this.tableDataGzh[index], true);
})
}
})
实际上要传的是对应的列,不是第几列数。说明:
multipleTable是对应table的ref
效果:
5.element的多选框实现单选:
vue:
<el-table-column label="放大关键词">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isBigWord"
@change="handleChecked(scope.$index)">
</el-checkbox>
</template>
</el-table-column>
js:
handleChecked(val) {
for (let i = 0; i < this.tableDataXcx.length; i++) {
if (i !== val) {
this.tableDataXcx[i]['isBigWord'] = false;
}
}
},
6.格式化时间
在 utils目录里的index.js里写:
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if (('' + time).length === 10) time = parseInt(time) * 1000
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
export function formatTime(time, option) {
time = +time * 1000
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
然后把这个文件在script里引入:
import {parseTime} from '@/utils'
vue文件里写:
<el-table-column :label="$t('messageManage.createTime')" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.createTime/1000 | formatTime }}</span>
</template>
</el-table-column>
效果:
vue里写:
<el-table-column :label="$t('messageManage.createTime')" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
效果:
js:
this.tableData.list.forEach(message => {
/* 格式化时间 */
if (message.createTime) {
message.createTime = parseTime(message.createTime)
}
})
vue:
<el-table-column :label="$t('messageManage.createTime')" prop="createTime" min-width="100" align="center"/>
效果和上面的一个一样
7.[Vue warn]: Error in render: "TypeError: _self.$scopedSlots.default is not a function"报错解决:
经过反复排查,没发现哪里写的有问题,最后在 https://forum.vuejs.org/t/weird-vuejs-error-with-elementui-table-self-scopedslots-default-is-not-a-function/12933/4找到答案
1.要么把v-if改成v-show
2.要么用v-if的时候加个key属性
8.Select 选择器在编辑时默认值不显示对应的名称
因为前期没那么多数据,就先把下拉写成死的,却遇到编辑页不显示对应名称的问题,但是不写死的那种都是OK的。最后看接口返回值发现返回的key不是string类型而是number,以后写死值的时候一定要注意类型
改成
效果:
9.element的select下拉选中不显示对应的项
因为上面一个下拉框选中会联动下面一个下拉框,上面一个下拉框选中后应该把下面的下拉框选中值重置,我之前是直接把的值设为null,在编辑时没事,但是新增时上面选中后,下面的下拉框选中不显示内容,于是我加了个判断,就是在下面一个下拉判断是不是之前有值,有就设为null,这样就可以避免在新增时下拉框选中不显示值的问题,还可以在上面一个下拉更改时,下面的框被重置掉
10.element如何并排显示,用<el-col></el-col>给span,整个span默认应该是分成了24块,下面的span和不超过24就行,
:gutter="50"这个值是块之间间隔
<el-row :gutter="50">
<el-col :span="10">
<el-form-item :label-width="formLabelWidth" label="主订单号:">
123
</el-form-item>
</el-col>
<el-col :span="8">
123
</el-col>
<el-col :span="6">
123
</el-col>
</el-row>
效果图:
不加gutter
加:gutter="50"
11.2019-3-15今天遇到浏览器接收接口response和preview的显示的值还不一样,发现原来接口传的那个值是long类型,js会把它给精度丢失掉,浏览器显示的值用的preview的值,显示时少了一位,建议转成string
12.js转换数组某列类型
getBizTypeByBizId(params).then(res => {
const _data = res.data
if (_data && _data.code === '200') {
let BizIdOptions = _data.data
this.BizIdOptions = BizIdOptions.map((item) => {
item.bizId = Number(item.bizId)
return{
...item,
}
});
}
}).catch(err => {
console.log(err.stack)
})
效果:
13.上传图片限制高宽
官网的demo没有说怎么限制高宽(像素) 只有大小和图片格式
官网:
修改后:
<el-form-item :label-width="formLabelWidth" label="店铺logo" prop="shopLogoUrl">
<el-upload
class="avatar-uploader"
action="/ms-api/account/uploadScenicAccountPic"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<span>图片格式:png;图片尺寸:150x150</span>
</el-form-item>
handleAvatarSuccess(res, file) {
if (res.code === '200') {
this.imageUrl = res.data[0].url
this.form.shopLogoUrl = this.imageUrl
} else {
this.$notify({
title: "失败",
message: res.msg,
type: "error",
});
}
},
beforeAvatarUpload(file) {
const isPNG = file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isPNG) {
this.$message.error('上传图片只能是 PNG 格式!');
}
if (!isLt2M) {
this.$message.error('上传图片大小不能超过2M!');
}
const isSize = new Promise(function(resolve, reject) {
let width = 150;
let height = 150;
let _URL = window.URL || window.webkitURL;
let image = new Image();
image.onload = function() {
let valid = image.width === width && image.height === height;
valid ? resolve() : reject();
};
image.src = _URL.createObjectURL(file);
}).then(
() => {
return file;
},
() => {
this.$message.error('上传图片尺只能是 150*150!');
return Promise.reject();
}
);
return isPNG && isLt2M && isSize;
},
14.js合并两个对象
普通js写法是
Object.assign(obj1,obj2)
ES6写法是:
let obj = {...obj1, ...obj2}
15.js把数组转成整形数组
this.form.newStartDate = this.form.startDate.split('-').map(Number)
效果:原:
先把字符串分割成数组,在把数组里的值转换成整形
16.Linux系统下修改文件不再热更新
在Windows上正常 但是在Linux上经常会热更新失效,最后发现是需要在config/inde.js下修改
poll: true, //这时候热更新就好了
17.开启页面缓存
设置keep-alive
在项目的layout文件夹下的components文件夹下AppMain.vue修改为
<keep-alive>
<router-view :key="key"/>
</keep-alive>
computed: {
key() {
return this.$route.fullPath
}
}
18.计算两个数组的按概率计算随机值
//按概率抽选
random(arr1, arr2) {
let sum = 0, factor = 0, random = Math.random()
for (let i = arr2.length - 1; i >= 0; i--) {
sum += arr2[i] // 统计概率总和
}
random *= sum // 生成概率随机数
for (let i = arr2.length - 1; i >= 0; i--) {
factor += arr2[i]
if (random <= factor) {
return arr1[i]
}
}
return null
}
19.js计算数组之和并保留2位小数
return eval(arr.join("+")).toFixed(2) //计算立减均值保留2位小数
20.过滤空元素
比如一个数组数据是['','1'],想要过滤成['1']
console.log(array.filter(function(e) {
return e
}))
21.js获取数组指定列
假如数组是这样,只想获取指定的字段
可以这样获取
let initiatorUserIds = self.jiangList.map(function (e) { // 获取指定列
return e.initiatorUserId;
});
得到:
22.js获取多维数组指定元素的最大值
例如:我想获取如下多维数组的level最大值
Math.max.apply(Math, data.map(function(o) {return o.level})) // 获取最大等级值
Math.min.apply(Math, data.map(function(o) {return o.level})) // 获取最小等级值
// level代表指定字段
得到结果:
23.js把两个多维数组的指定元素的相同值组合成新数组
let a=[{x:1,b:'s'},{x:1,b:'s1'},{x:2,b:'s2'},{x:3,b:'s3'},{x:3,b:'s4'},{x:4,b:'s5'}]
let res = []
while(a.length!==0){
let list = a.shift()
let arr = [list]
for (let i = 0; i < a.length; i++) {
if (a[i].level === list.level) {
arr = arr.concat(a.splice(i, 1))
i--
}
}
res.push(arr)
}
console.log(res)
24.获取data里return定义的初始值
Object.assign(this.$data, this.$options.data.call(this)); // 重置回最开始data里return定义的初始值