vue + elementui工作中常见问题总结
vue页面的常用跳转history.go(-2);//后退两次history.go(2);//前进两次history.back(); //后退hsitory.forward(); //前进----------------------------------------------## 标题为什么 v-for 和 v-if 不建议⽤在⼀起?原因:v-for比v-if优先级高,每一次都需要遍历整个数组
修改input回车页面刷新
<el-form @submit.native.prevent>
<el-form-item label='部门:' style="width: 100%;">
<el-input v-model="params.officeName" style="width: 160px;" @keyup.enter.native="searchFn" clearable @clear="searchFn"></el-input>
</el-form-item>
</el-form>
vue css引入
@import '../../assets/style/flow.css';
路由变化后清除缓存再次进入页面时就是初始化的页面,两个tab切换时是不清除缓存的,因为路由么有变化
<keep-alive :include="inCludePush">
<router-view name="a" class="child-view"></router-view>
</keep-alive>
inCludePush:[]
watch: {
tabs: {
handler: function(val, oldVal) {
this.inCludePush = ['formPage','docDetail']
val.map(d => {
this.inCludePush.push(d.link.replace('/index/', ''))
})
},
// 深度观察监听
deep: true,
immediate: true
},
},
将object类型转为数组
let arr = Array.from(a.files)
tree默认选中第一个
<div slot='page-left' class='tree-wrap'>
<h5>部门</h5>
<el-input placeholder='输入关键字进行过滤' v-model='filterText'>
</el-input>
<el-scrollbar ref='scroll' class='tree-scrollbar'>
<el-tree class='filter-tree' :data='deptData' :props = '{ children : "children", label : "orgName" }' :highlight-current="true"
:filter-node-method='filterNode' @node-click='handleNodeClick' ref='tree' node-key="id">
</el-tree>
</el-scrollbar>
</div>
filterText:'',
watch: {
// 组织搜索
filterText(val) {
this.$refs.officeTree.filter(val);
}
}
// 搜索过滤
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
// 获取树
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.officeId) // 默认选中节点第一个
})
tree回显
hui() { // 回显
this.$nextTick(() => {
const _arr = [];
const _func = arr => {
arr.map(d => {
if (d.childrenList && d.childrenList.length > 0) {
_func(d);
} else {
_arr.push(d.leaderUserOffice);
}
})
}
_func(this.tableData);
this.$refs.officeTree.setCheckedKeys(_arr);
})
},
关闭右小角弹框
this.$notify.closeAll()
年月日时分秒
filters: {
formatDate: function(value) {
const date = new Date(value);
console.log(date, value)
const y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? ('0' + MM) : MM;
let d = date.getDate();
d = d < 10 ? ('0' + d) : d;
let h = date.getHours();
h = h < 10 ? ('0' + h) : h;
let m = date.getMinutes();
m = m < 10 ? ('0' + m) : m;
let s = date.getSeconds();
s = s < 10 ? ('0' + s) : s;
return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
}
},
{{time | formatDate}}//使用
渐变背景色
.todo-left {
box-sizing: border-box;
background: -webkit-linear-gradient(left, #F66157 0, #FCBE73 100%);
background: -o-linear-gradient(left, #F66157 0, #FCBE73 100%);
background: -ms-linear-gradient(left, #F66157 0, #FCBE73 100%);
background: -webkit-gradient(linear, right top, left top, color-stop(0, #F66157), to(#FCBE73));
background: -o-linear-gradient(right, #F66157 0, #FCBE73 100%);
background: linear-gradient(to left, #F66157 0, #FCBE73 100%);
color: #FFFFFF;
min-width: 230px;
height: 149px;
margin-top: 13px;
border-radius: 4px;
}
字典,list数据返回key,匹配value
{{setMsgType(scope.row.fileType)}}
setMsgType(type) {
let name;
this.fileType.forEach((d) => {
if (d.Value == type) {
name = d.Label;
}
});
return name;
},
elementui 提示语全局设置
设置:
Vue.prototype.msgSuccess = function(msg) {
this.$message({
showClose: true,
message: msg,
type: "success"
});
}
Vue.prototype.msgError = function(msg) {
this.$message({
showClose: true,
message: msg,
type: "error"
});
}
Vue.prototype.msgWarning = function(msg) {
this.$message({
showClose: true,
message: msg,
type: "warning"
});
}
调用:
this.msgSuccess('添加通知成功');
-------------------
Vue.prototype.msgSuccess = function(msg) {
Toast.success(msg);
}
Vue.prototype.msgError = function(msg) {
Toast(msg);
}
调用:this.msgSuccess('操作成功!');
Vue.prototype.msgConfirm = function(msg, callback) {
Dialog.confirm({
title: '提示',
message: msg,
beforeClose(action, done) {
if (action === 'confirm') {
if (callback) callback()
}
done();
}
});
}
调用:this.msgConfirm('确认要撤销吗?', () => {
// 逻辑内容
})
判空、不能为空
main全局设置
Vue.prototype.byteEmpty = function(obj,byteObj) {
let emptyArr = [];
Object.keys(byteObj).forEach((key) => {
if (!obj[key]) {
emptyArr.push(`${byteObj[key]}不能为空`);
}
})
return emptyArr;
}
调用:
let byteObj = { //可判断的字段 对应提示信息
title: '标题',
Age: '年龄',
Gender: '性别',
time: '时间',
address: '地址',
name: '姓名',
}
let arrRet = this.byteEmpty(this.list, byteObj)
if (arrRet && arrRet.length > 0) {
this.msgError(arrRet[0]);
return
}
jq 加载资源
$.getScript("ajax/test.js", function() {
alert("Load was performed.");
});
移动端 文本域 无法滚动,解决方案:
window.addEventListener('touchmove', function(e) {
let target = e.target;
if (target && target.tagName === 'TEXTAREA') {
e.stopPropagation();
}
}, true)
数据变化了但是视图层么有变
解决方案:
var newArray = this.tableData.slice(0); //深拷贝数据
this.tableData=[]
this.$nextTick(function () {
_this.tableData = newArray;
});
vue页面的常用跳转
history.go(-2);//后退两次
history.go(2);//前进两次
history.back(); //后退
hsitory.forward(); //前进
----------------------------------------------## 标题
为什么 v-for 和 v-if 不建议⽤在⼀起?
原因:v-for比v-if优先级高,每一次都需要遍历整个数组,造成不必要的计算,影响性能,即使100个list中只需要使用一个数据,也会循环整个数组。
<ul>
<li v-for="item in list" v-if="item.actived">{{item.name}}</li>
</ul>
解决:使用computed
<ul>
<li v-for="item in activeList">{{item.name}}</li>
</ul>
computed: {
activeList() {
return this.list.filter(val => {
return val.actived;
});
}
},
table 点击删除不调接口过滤数据 + 二次确定
this.tableData = this.tableData.filter((v) => v.taskId !== row.taskId );
this.total = this.total - 1;
thoroughDeleteFn(row) {
this.$confirm('确认要彻底该数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
接口名({
给后端传参
})
.then((res) => {
if (res.status === 0) {
this.$message.success('删除成功');
let totalPage = Math.ceil((this.total - 1) / this.pageSize)
let currentPage = this.currentPage > totalPage ? totalPage : this.currentPage
this.currentPage = currentPage < 1 ? 1 : currentPage
this.getData();
} else {
this.$message.error(res.msg);
}
})
.catch(() => {
this.$message.error('删除失败');
});
})
.catch(() => {});
},
前端完成分页
<div class="tab-bar">
<i
:style="{color:pageNoLink<1 || Math.ceil(totalLink/4) <= pageNoLink?'#999':'#333'}"
class="more el-icon-arrow-right"
@click="gotoListPage(pageNoLink + 1 ,'right')"
></i>
<i
class="more el-icon-arrow-left"
:style="{color:pageNoLink==1?'#999':'#333'}"
@click="gotoListPage(pageNoLink - 1 ,'left')"
></i>
</div>
gotoListPage(data,type) {
if(data>0 && ((type=='right' && Math.ceil(this.totalLink/4) > this.pageNoLink) || type=='left')){
this.pageNoLink = data;
//调用接口拿数据
this.listcardMoreFunc(data,'cms_link')
}
},
watch
watch: {
menuArr: {
handler(val) {
console.log('42')
},
deep: true
}
},
element-ui的el-tree 实现鼠标移入子节点,显示删除、修改等功能按钮
tree显示删除,修改博客链接,可查看详情
vue子传父、父传子
子传父、父传子博客链接,可查看详情
Vue路由获取路由参数
vue路由详细参数获取链接
// element ui中form多个表单循环校验,是否为空操作
ruleForm: {
name: "张三",
unit: "测试",
age:"23"
},
ruleList:[{
label:'name',
value:'张三'
},{
label:'unit',
value:'测试'
},{
label:'age',
value:'23'
}],
<el-form :model="ruleForm">
<el-form-item label="活动名称" :prop="ruleList[i].label" v-for="(item,i) in ruleList.length" :key='i' :rules="[{ required: true, message: ruleList[i].label+'不能为空', trigger: 'blur'}]">
<el-input v-model="ruleForm[ruleList[i].label]"></el-input>
</el-form-item>
</el-form>
getNewObject(arr,brr){
let obj={};
brr.forEach((item,index)=> {
obj[item]=arr[index];
});
this.ruleForm=obj
},
confirm() {
var jValue=[]
var jValue2=[]
this.ruleList.forEach(d=>{
if(d.type==0){
for(var item in d){
if(item=='templateField'){
jValue.push(d[item]);//key所对应的value
}
if(item=='fieldValue'){
jValue2.push(d[item]);//key所对应的value
}
}
}
})
this.getNewObject(jValue2,jValue)
this.$refs.formName.validate((valid, object) => {
if (valid) {
console.log('判断是否检验成功',valid)
} else {
return false;
}
});
},
input框第一个不能输入空格
<el-form-item label="会议室名称" :rules="[{ required: true, message: '会议室名称不能为空'},{max: 64, message: '最多输入64个字符',}]" prop="roomName">
<el-input v-model="form.roomName" placeholder="请输入会议室名称,最多输入64个字符" data-index="0" maxlength="64" show-word-limit @input="keyUps" ></el-input>
</el-form-item>
keyUps(val){
const i = parseInt(event.target.getAttribute('data-index'));
this.form.roomName = val.replace(/^\s/g,'')
},
input框输入中文;更换成英文;
<el-input v-model="halfForm.handlingDepartment" size="mini" maxlength="1000" type="textarea" autosize @input="keyUpsMent">
</el-input>
keyUpsMent(val) {
this.halfForm.handlingDepartment = val.replace(/;/g, ';');
},
开始时间、结束时间
<el-form-item label="结束时间">
<el-date-picker
v-model="pro.startDate"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
:picker-options="pickerOptionsStart"
type="datetime"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item label="-">
<el-date-picker
v-model="pro.endDate"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
:picker-options="pickerOptionsEnd"
type="datetime"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
data(){
return{
pickerOptionsStart: {
disabledDate: time => {
let endDateVal = this.pro.endDate
if (endDateVal) {
return time.getTime() > new Date(endDateVal).getTime()
}
}
},
pickerOptionsEnd: {
disabledDate: time => {
let beginDateVal = this.pro.startDate
if (beginDateVal) {
return time.getTime() < new Date(beginDateVal).getTime()
}
}
},
}
}
年份选择了2023,只能选择23年内的日期,并且结束时间和开始时间做大小校验
pickerOptionsStart: {
disabledDate: time => {
let endDayVal = this.addList.endDay
let year = this.addList.holidayYear
return (
time.getFullYear() > new Date(year).getFullYear() ||
time.getFullYear() < new Date(year).getFullYear() || time.getTime() > new Date(
endDayVal).getTime()
)
}
},
pickerOptionsEnd: {
disabledDate: time => {
let beginDateVal = this.addList.beginDay
let year = this.addList.holidayYear
return (
time.getFullYear() > new Date(year).getFullYear() ||
time.getFullYear() < new Date(year).getFullYear() || time.getTime() < new Date(
beginDateVal).getTime() - 86400000 // 可选开始时间及以后的日期
)
}
时间控件–默认当前日期
this.searchList.date=[date.getFullYear() + '-01-01',this.GetDateStr(0)]
this.searchList.beginTime=date.getFullYear() + '-01-01'
this.searchList.endTime=this.GetDateStr(0)
GetDateStr(AddDayCount) {
var dd = new Date();
dd.setDate(dd.getDate()+AddDayCount);//获取AddDayCount天后的日期
var y = dd.getFullYear();
var m = dd.getMonth()+1;//获取当前月份的日期
if (m < 10) {
m = '0' + m
}
var d = dd.getDate();
if (d < 10) {
d = '0' + d
}
return y+"-"+m+"-"+d;
}
数组遇见childs头插入一条
let arr = [{
"taskName": "姓名",
"businessTable": "record_issue",
"id": "97d8d7a1-6dc1-4838-9f65-162120f9128f",
"fromUnit": "单位1",
"fromUser": "请挺",
"childs": [{
"taskName": "姓名2",
"id": "a408583b-50b2-45cb-b53a-98fa98e624dc",
"childs": [{
"taskName": "姓名3",
"businessTable": "record_issue",
"id": "a408583b-50b2-45cb-b53a-98fa98e624dc",
}],
}],
},
{
"taskName": "姓名44",
"id": "a3c6550a-10ea-4e61-802e-4807f3521cf9",
"fromUnit": "单位11"
}
]
this.tableData = this.changeData(arr)
changeData(data) {
data && data.map(item => {
if (item.childs && item.childs.length > 0) {
item.childs.unshift({
fromUser: '办理人',
fromUnit: '办理部门',
createTime: '',
taskName: "环节",
title: "",
id: new Date().getTime() + Math.floor(Math.random() * 1000 + 1).toString()
})
item.childs.forEach(d=>{
d.son='son';
})
this.changeData(item.childs);
}
})
return data;
},
<div class="AccountLoginBox approv">
<ul>
<li v-for="(item, index) in tabList" :key="index" :class="tabIndex === index ? 'active' : ''"
@click="handerTabChange(item, index)">{{item.label}}<div class="border-bottomS" :class="tabIndex === index ? 'activeBottom' : ''"></div></li>
</ul>
</div>
tabList: [{
label: 'tab1',
value: 1
}, {
label: 'tab2',
value: 2
}],
tabIndex:0
handerTabChange(item, index) {
this.tabIndex = index;
},
.approv {
display: flex;
flex-direction: column;
align-items: flex-start;
ul {
display: flex;
margin-top: 3px;
margin:3px auto;
li {
font-size: 24px;
color: #333333;
margin-right: 50px;
padding-bottom: 2px;
cursor: pointer;
font-weight: 600;
.border-bottomS{
width:40px;height:2px;margin: 10px auto 0;
}
}
li.active {
color: #D62727;
}
div.activeBottom{
background-color: #D62727;
}
}
}
接口一起请求
import axios from 'axios';
getDictionaryList() {
axios
.all([
getDictByType({
type: 'file_secret'
}),
getDictByType({
type: 'file_time'
}),
])
.then(
axios.spread((sv, bv) => {
if (sv.status === 0) {
this.secretOption = sv.value || []
} else {
this.$message.error(sv.msg);
}
if (bv.status === 0) {
this.timeOption = bv.value || []
} else {
this.$message.error(bv.msg);
}
})
);
},
字符串设置超过多少行用点点点代替
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
.message-title {
width: 84px;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
display: block;
white-space: nowrap;
}
前端开发准备内容
1.先装node;检查(node -v)
2.检查npm(npm -v)
3.安装淘宝镜像(npm install -g cnpm --registry=https://registry.npm.taobao.org)
4.配置环境变量(在控制面板里面;高级系统设置;环境变量;在系统变量里找path)(where node找node的地址)
5.检查vue(vue -v)
6.安装vue(npm install -g @vue/cli)
7.桥接vue2.0(npm install -g @vue/cli-init)
8.检查(vue -V)
查看npm 安装的包 的历史版本
npm view animate.css versions
git上传代码时前面带着标注
feat 新功能 pref 正在进行的功能 fix:修复的bug
页面加载loading
**elementui**
const loading = this.$loading({
lock: true,
text: '加载中',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.4)'
})
loading.close();
**uniapp**
uni.showLoading({
title: '加载中'
});
uni.hideLoading();
/设置数字、字母内容超出后自动换行/
word-wrap: break-word;
word-break: break-all;
动画
animation-delay:-1s; 延迟1s
animation-iteration-count:3; 属性指定动画应运行的次数。
animation-iteration-count: infinite;使用值 “infinite” 使动画永远持续下去
点击下载正文,正文消失
function downloadBlob(response, name) {
if(window.Blob&&window.navigator.msSaveOrOpenBlob){
window.navigator.msSaveOrOpenBlob(response,encodeURI(name));
}else{
let url = window.URL.createObjectURL(response);
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.setAttribute("download", name);
document.body.appendChild(link);
link.click();
document.querySelector('body').removeChild(link)
}
}
//选择常用语 文本域非空过滤
$(this).on('input', function (e) {
$(this).val($.trim(e.target.value));
})
// 修改文件中的img的token
async changePageImgToke() {
try {
const _token = await getToken();
let uploadURL=sessionStorage.getItem('uploadURL');
this.$nextTick(() => {
const _conBox2 = document.querySelector("#tinymyClone").querySelectorAll("img");
if (_conBox2[0]) {
_conBox2.forEach((dom) => {
if(dom.getAttribute("src").indexOf(`${uploadURL}`)!=-1){
if(dom.getAttribute("src").indexOf(`?`)==-1){
const _url = dom.getAttribute("src").split("?token=")[0];
dom.setAttribute("src", `${_url}?token=${_token.value}`);
}else{
let _url = dom.getAttribute("src").replace(/&token=(\S*)&/, "&");
dom.setAttribute("src", `${_url}&token=${_token.value}`);
}
}
});
}
});
} catch (e) {
return false;
}
// try {
// const _token = await getToken();
// this.$nextTick(() => {
// const _conBox2 = document.querySelector("#tinymceId");
// if (_conBox2[0]) {
// _conBox2.forEach((dom) => {
// // const _url = dom.getAttribute("src").split("?token=")[0];
// // dom.setAttribute("src", `${_url}?token=${_token.value}`);
// if(dom.getAttribute("src").indexOf('http://chinaofd.cn:18079')!=-1){
// let _url = dom.getAttribute("src").replace(/&token=(\S*)&/, "&");
// dom.setAttribute("src", `${_url}&token=${_token.value}`);
// }
// });
// }
// });
// } catch (e) {
// return false;
// }
},
json深拷贝
this.dataRight = JSON.parse(JSON.stringify(response))
数组深拷贝
let arr=arr.concat([])
el-form必填添加星星
/deep/.el-form-item__label::before {
content: "*";
color: #f56c6c;
margin-right: 4px;
}
删除文本域边框、右下标样式
/deep/.el-textarea__inner{
border: none;
resize: none;
}
element ui tree递归
function changeData(data) {
data.map(item => {
if (item.value=="user") {
itarr.push(item.id)
}
item.children && item.children.length > 0 && changeData(item.children);
})
return itarr;
}
去重
function unique(arr) {
return Array.from(new Set(arr))
}
----------------------
const arr = [1,5,1,5,4,56,4,8,4,4,85,4,5];
const soleValue = Array.from(new Set(arr));
console.log(soleValue);
// 1, 5, 4, 56, 8, 85
过滤
const filter_arr = this.mylist.filter((d) => d.selected === true);
var login = pageEle.business.filter(function (v) {
return v.name === $(dom[q]).attr('name')
});
// 人员数组去重
function unique(arr,ev){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){
arr.splice(j,1);
j--;
}
}
}
return arr;
}
json改key
1、a:'name' b:'123'
[obj.a]:obj.b name:123
2、[name]:'123'
字符串去重
function removeRepeat(str){
var newStr = '';
var len = str.length;
for(var i=0; i<len; i++){
if(newStr.indexOf(str[i])==-1){
newStr = newStr + str[i];
}
}
return newStr;
}
删除已经提交的代码(只针对要退回的文件后面么有任何提交记录)
右击文件夹->git->repository->remotes 填写退回版本
右击文件夹->git->rollback 回滚
git push -f 删除git刚刚回滚的文件
点击删除末尾值
const fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
const citrus = fruits.slice(1, 4);//左开右关从0开始
过滤script标签
function filtercontent(text) {
if (text) {
return text.replace(/<script.*?>/ig, '').replace(/<\/script>/, '');
} else {
return '';
}
}
禁止多次点击按钮导致多次调用执行方法
var nowTime = new Date().getTime();
var clickTime = $(this).attr("ctime");
if( clickTime != 'undefined' && (nowTime - clickTime < 3000)){
mui.toast('操作过于频繁,稍后再试.');
return false;
}
$(this).attr("ctime",nowTime);
switch 符合后公共方法
switch (bus) {
case '1': case '2':
this.show();
break;
}
}
A页面点击事件触发后,B页面拿到点击事件后修改相应的操作
/**eventBus.js内容**/
import Vue from 'vue'
export default new Vue();
A页面
import eventBus from '@/lib/eventBus.js';
<el-button type="primary" size="mini" class="recover-btn" @click="btn">按钮</el-button>
handleRecover() {
this.$confirm('确认要点击?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
eventBus.$emit('btn');
})
},
B页面
import eventBus from '@/lib/eventBus.js';
created() {
eventBus.$on('btn', (message) => {
this.btn();
})
},
btn(){
console.log('是的,B页面被点击了')
}
删除table某一行
thoroughDeleteFn(row) {
this.$confirm('确认要删除该条数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
thoroughDeleteAffair({
affairQueryprocInsId: row.affairQueryprocInsId
})
.then((res) => {
if (res.status === 0) {
this.$message.success('删除数据成功');
let totalPage = Math.ceil((this.total - 1) / this.pageSize)
let currentPage = this.currentPage > totalPage ? totalPage : this.currentPage
this.currentPage = currentPage < 1 ? 1 : currentPage
this.getData();
} else {
this.$message.error(res.msg);
}
})
.catch(() => {
this.$message.error('删除数据失败');
});
})
.catch(() => {});
},
table行、列可拖动变化位置
<template>
<div style="width:800px">
<el-table :data="tableData" border row-key="id" align="left">
<el-table-column v-for="(item, index) in col" :key="`col_${index}`" :prop="dropCol[index].prop"
:label="item.label">
</el-table-column>
</el-table>
<pre style="text-align: left">
{{dropCol}}
</pre>
<hr>
<pre style="text-align: left">
{{tableData}}
</pre>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
data() {
return {
col: [{
label: '日期',
prop: 'date'
},
{
label: '姓名',
prop: 'name'
},
{
label: '地址',
prop: 'address'
}
],
dropCol: [{
label: '日期',
prop: 'date'
},
{
label: '姓名',
prop: 'name'
},
{
label: '地址',
prop: 'address'
}
],
tableData: [{
id: '1',
date: '2016-05-02',
name: '王小虎1',
address: '上海市普陀区金沙江路 100 弄'
},
{
id: '2',
date: '2016-05-04',
name: '王小虎2',
address: '上海市普陀区金沙江路 200 弄'
},
{
id: '3',
date: '2016-05-01',
name: '王小虎3',
address: '上海市普陀区金沙江路 300 弄'
},
{
id: '4',
date: '2016-05-03',
name: '王小虎4',
address: '上海市普陀区金沙江路 400 弄'
}
]
}
},
mounted() {
let tableData = JSON.parse(sessionStorage.getItem('tableData'))
let dropCol = JSON.parse(sessionStorage.getItem('dropCol'))
if(tableData){
this.tableData = tableData
}
if(dropCol){
this.dropCol=JSON.parse(sessionStorage.getItem('dropCol'))
this.col=JSON.parse(sessionStorage.getItem('dropCol'))
}
this.rowDrop()
this.columnDrop()
},
methods: {
//行拖拽
rowDrop() {
const tbody = document.querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd({
newIndex,
oldIndex
}) {
const currRow = _this.tableData.splice(oldIndex, 1)[0]
_this.tableData.splice(newIndex, 0, currRow)
console.log('行拖拽', _this.tableData)
sessionStorage.setItem('tableData', JSON.stringify(_this.tableData))
}
})
},
//列拖拽
columnDrop() {
const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
this.sortable = Sortable.create(wrapperTr, {
animation: 180,
delay: 0,
onEnd: evt => {
const oldItem = this.dropCol[evt.oldIndex]
this.dropCol.splice(evt.oldIndex, 1)
this.dropCol.splice(evt.newIndex, 0, oldItem)
console.log('列拖拽', evt.oldIndex, this.dropCol, this.tableData)
sessionStorage.setItem('dropCol', JSON.stringify(this.dropCol))
}
})
}
}
}
</script>
获取文件名后拼接.ofd
var flowFileName = resInfo.fileName.substring(0, resInfo.fileName.lastIndexOf('.')) + '.ofd'
var _isname = resInfo.fileName.substring(0,resInfo.fileName.lastIndexOf('.')).toLowerCase()
获取文件名类型
fliePath.substring(fliePath.lastIndexOf('.')+1).toLowerCase()
_houzhui = fliePath.substring(fliePath.lastIndexOf('.')).toLowerCase();
let houzui = fileUrl.substring(fileUrl.lastIndexOf('.')).toLowerCase()
let fileName = 'active' + houzui
// 被点击id 接口拿到的数据 tree旧数据
前端处理懒加载,点击父拼接子集
function getNewList(btnId, pushList, treeList) {
for (let item of treeList) {
if (item.id === btnId) {
item.children = pushList;
} else if (item.children && item.children.length > 0) {
getNewList(btnId, pushList, item.children);
}
}
}
数组根据pid组装成tree
const list = [
{ id: 1, name: '部门1', pid: 0 },
{ id: 2, name: '部门2', pid: 1 },
{ id: 3, name: '部门3', pid: 1 },
{ id: 4, name: '部门4', pid: 3 },
{ id: 5, name: '部门5', pid: 4 },
{ id: 6, name: '部门6', pid: 1 },
{ id: 7, name: '部门1-1', pid: 0 }
];
function arrayToTree(items) {
const result = []; // 存放结果集
const itemMap = {}; //
// 先转成map存储
for (const item of items) {
itemMap[item.id] = { ...item, children: [] }
}
for (const item of items) {
const pid = item.pid;
const treeItem = itemMap[item.id];
if (pid === 0) {
result.push(treeItem);
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
}
}
itemMap[pid].children.push(treeItem)
}
}
return result;
}
let a = arrayToTree(list);
console.log('a--',a);
屏幕自适应
@media screen and (max-width: 1400px) {
.loginRightBox {
right:2%;
}
}
@media screen and (min-width:1440px) and (max-width:1600px) {
/* 大于1440px 小于 1600px */
.loginRightBox {
right:3%!important;
}
}
jq ztree 懒加载
setting.callback.onExpand = function(treeId, treeNode,tree){
if(tree.isParent){
$.ajax({
url: 接口url,
cache: false,
type: 'get',
dataType: 'json',
headers: {
'Access-Token': accessToken
},
success: function (res) {
if (res.status == 0) {
treeObj.removeChildNodes(tree);
treeObj.addNodes(tree, res.value, false);
} else {
layer.msg(e.msg, {
icon: 2
})
}
}
})
}
}
去除字符串首尾空白字符
let str = ' 13 '
str.trimStart()
str.trimEnd()
json转数组
Object.values()
Object.values({a: 1, b: 2, c: 3}); // [1, 2, 3]
Object.entries()
Object.entries({a: 1, b: 2, c: 3}); // [["a", 1], ["b", 2], ["c", 3]]
flat:展开一层数组;flatMap:做了map循环和filter过滤
let arr = [1,2,[3,4]]
arr.flat(Infinity);// [1,2,3,4]
let arr1 = [1,2,3,4]
arr.flatMap(a =>{a**2}); //[1,4,9,16]
函数的节流
throttle(() => {
//处理的方法
})
/**
* 节流
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
let timer, flag;
export function throttle(func, wait = 300, immediate = true) {
if (immediate) {
if (!flag) {
flag = true;
// 如果是立即执行,则在wait毫秒内开始时执行
typeof func === 'function' && func();
timer = setTimeout(() => {
flag = false;
}, wait);
}
} else {
if (!flag) {
flag = true
// 如果是非立即执行,则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false
typeof func === 'function' && func();
}, wait);
}
}
};
开始时间不能大于结束时间
if (new Date(this.startTime).getTime() > new Date(this.endTime).getTime()) {
uni.showToast({
title: '开始时间不能大于结束时间',
icon: 'none',
duration: 2000
})
return false;
}
默认时间:当月1号到现在
this.startTimeFlag = new Date().getFullYear() + '-' + parseInt(new Date().getMonth() + 1).toString().padStart(
2, '0') + '-01'
this.endTimeFlag = new Date().getFullYear() + '-' + parseInt(new Date().getMonth() + 1).toString().padStart(2,
'0') + '-' + new Date().getDate()
年月日时分秒截取
time = time ? time .substring(0, time.lastIndexOf(':')):'' //年月日时分
time = time ? time .substring(0, time.lastIndexOf(' ')):''//年月日
多行文本自动撑高
$('textarea').each(function(){
makeExpandingArea($(this)[0])
})
function makeExpandingArea(el) {
var timer = null;
//由于ie8有溢出堆栈问题,故调整了这里
var setStyle = function (el, auto) {
if($(el).attr('orgheight')){
if (auto) el.style.height = $(el).attr('orgheight');
}else{
if (auto) el.style.height = 'auto';
}
el.style.height = el.scrollHeight + 'px';
// }
};
var delayedResize = function (el) {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
setStyle(el, 1)
}, 200);
};
delayedResize(el);
if (el.addEventListener) {
el.addEventListener('input', function () {
setStyle(el, 1);
}, false);
setStyle(el, 1)
} else if (el.attachEvent) {
el.attachEvent('onpropertychange', function () {
setStyle(el, 1)
});
setStyle(el, 1)
}
if (window.VBArray && window.addEventListener && el.attachEvent) { //IE9
el.attachEvent("onkeydown", function () {
var key = window.event.keyCode;
if (key == 8 || key == 46) delayedResize(el);
});
el.attachEvent("oncut", function () {
delayedResize(el);
}); //处理粘贴
}
}
查看打包文件的文件大小占比
"build-report": "vue-cli-service build --report"
解决elementui el-form表单input框点击回车页面刷新
<el-form @submit.native.prevent></el-form>
监听,取消监听
mounted() {
window.addEventListener('message', this.handleMessage, true);
},
destroyed() {
window.removeEventListener('message', this.handleMessage, true);
背景样式
background-image: linear-gradient(-180deg,rgba(255,255,255,0) 0%,#fff 100%);
filters使用
<el-table-column prop="name" label="分类" width="200">
<template slot-scope="scope">
{{ { _t: scope.row.name, typeList: typeList } | filterTypeText }}
</template>
</el-table-column>
<el-table-column prop="enable" label="启用" width="80" align="center">
<template slot-scope="scope">
{{ scope.row.enable | filterBooleanText }}
</template>
</el-table-column>
filters: {
filterTypeText(val) {
const _tid = val._t;
const _getType = (arr) => {
let _type = null;
for (let i = 0; i < arr.length; i++) {
if (arr[i].id === _tid) {
_type = arr[i];
break;
} else if (arr[i].children && arr[i].children.length > 0) {
const _ct = _getType(arr[i].children);
if (_ct !== null) {
_type = _ct;
break;
}
}
}
return _type;
};
const isType = _getType(val.typeList);
return isType === null ? '' : isType.name;
},
filterBooleanText(val) {
return val ? '是' : '否';
}
},
保存、修改只能出现一个的情况
<el-table-column label='操作' width='130'>
<template slot-scope='scope'>
<div class='button add' v-if="scope.row.isEdit" @click='handleEdit(scope.row,"save")'>
<span>保存</span>
</div>
<div class='button edit' v-else @click='handleEdit(scope.row,"edit")'>
<span>修改</span>
</div>
</template>
</el-table-column>
handleEdit(row, type) {
if (type == 'save') {
row.isEdit = false;
} else {
row.isEdit = true;
}
this.isShow = false;
this.$nextTick(() => {
this.isShow = true;
})
},
处理下载流,已处理的下载流
import { handleExport } from "@/lib/util";
this.$confirm('确认要导出数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let obj = { // josn
id: this.id,
currentPage: this.currentPage,
pageSize: this.pageSize
}
// const eatraData= `beginTime=${this.searchList.date ? this.searchList.date[0] : '' //string
// }&endTime=${this.searchList.date ? this.searchList.date[1] : ''
// }&userId=${this.detailInfo.userId || ''}`
// this.handleExport(obj);
handleExport(obj)
})
import Vue from 'vue'
export const EventBus = new Vue()
export function handleExport(extraData, urlStr, token) {
const xmlResquest = new XMLHttpRequest();
xmlResquest.open('POST', urlStr, true);
xmlResquest.responseType = 'blob'; // 该属性必须设置
xmlResquest.setRequestHeader('Authorization', token);
xmlResquest.setRequestHeader('Content-type','application/json'); // json -> application/json,string -> application/x-www-form-urlencoded
xmlResquest.onload = () => {
let content = xmlResquest.response;
let blob = new Blob([content]);
let reader = new FileReader(); //读取后端返回的异常信息
reader.readAsText(content, 'utf-8');
reader.onload = () => {
if (reader.result.indexOf('{"status":1') !== -1) {
EventBus.$message.error(JSON.parse(reader.result).msg);
return
}
}
if (xmlResquest.getResponseHeader(
'content-disposition')) { // 判断有没有请求头content-disposition,该请求头在后台文件流导出成功时添加
let explorer = navigator.userAgent;
let elink = document.createElement('a');
let fileName = xmlResquest.getResponseHeader('content-disposition').split(';')[1].split('=')[
1]; // 获取文件名
if (explorer.indexOf('MSIE') >= 0 || explorer.indexOf('Chrome') >= 0) { // IE和google浏览器
fileName = decodeURIComponent(fileName);
} else {
fileName = decodeURI(escape(fileName));
}
elink.download = fileName;
elink.style.display = 'none';
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
elink.href = window.URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
window.URL.revokeObjectURL('url');
}
} else {
// EventBus.$message.error('下载失败');
}
}
xmlResquest.onerror = () => {
EventBus.$message.error('下载失败');
};
xmlResquest.send(extraData);
}
// 导出
exportData(flag) {
this.$confirm('确认要导出数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
statsExport({
id: this.id,
currentPage: this.currentPage,
pageSize: this.pageSize
}).then((res) => {
this.downloadBlob(res, '统计.xlsx');
})
})
},
// blob 文件下载
downloadBlob(response, name) {
if (window.Blob && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(response, encodeURI(name));
} else {
let url = window.URL.createObjectURL(response.data);
let link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', name);
document.body.appendChild(link);
link.click();
document.querySelector('body').removeChild(link)
}
},
给script 加随机数
$($("script")).each(function(index, item){
var oldSrc =$(item).attr("src")
$(item).attr("src", oldSrc + "?testrandom="+Math.random())
})
更多推荐
所有评论(0)