VUE 笔记
- 1.数组对象合并并去重
- 2.js 数据按时间排序
- 3.vue 解码获取url参数中包含的特殊字符
- 4.根据id来匹配后台返回来的数据后,获取该id的单条数据
- 5.list集合中有三个对象,如如何删除对象中的指定的值
- 6.将string转list集合
- 7.list 在最前面添加一项数据
- 8.list 截取数据
- 9.多个数组合并成一个,多个对象合并成一个
- 10.JS Array.reverse 将数组元素颠倒顺序
- 11.数组对象合并
- 12.vue+element-ui中的el-table-column配合v-if 数据位置错乱问题
- 13.给table 每行的操作按钮添加loding防止重复提交
- 14.给table 的json数据添加index序号
- 15.js 遍历数组取出字符串用逗号拼接
- 16.正则获取字符串中的某一段值
- 17.重新命名后台返回来的key名
- 18.循环转换返回来的后台数据类型
- 19.Element ui select同时获取value和label的值
- 20.input输入框失去焦点事件
- 21.循环将list里面的数字字符串转成list[]
- 22.设缓存信息
- 23.vue 设置cookies
- 24.json对象和字符串相互转换
- 25.共用多套验证规则时,可以在下拉选择时添加如下代码
- 26.vue element table过滤器使用
- 27.vue element table表尾合计数据
- 28.表格合计时解决精度丢失问题 Math.round( 总数据* 100) / 100
- 29.解决element组件分页点击下几页时再重新用别的接口请求数据时,页数的激活状态没跳回第一页
- 30.解决element组件获取后台数据排序
- 31.关于vue 项目页面打包后首次页面加载特别缓慢的原因及解决方案
- 32.vue element 菜单栏点击其他第一级菜单时,关闭当前已打开的第二级菜单栏
- 33.vue element table传参后端排序
- 34.v-model.trim属性实现去除input值的前后空格
- 35.element日期时间组件传参数
- 36.element type="number"的input输入框只能输入数字,限制不能输入e
- 37.JS处理数据
- 38.element tree功能
- 39.找出两个数组的不同之处
1.数组对象合并并去重
根据id去重并合并对象数组(id为唯一值)
this.tableData = this.unique(this.tableData.concat(this.multipleSelectionAll))
unique(arr) {
const res = new Map();
return arr.filter((arr) => !res.has(arr.id) && res.set(arr.id, 1))
},
2.js 数据按时间排序
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
var data = [
{
name:'1',
time:'2019-04-26 10:53:19'
},
{
name:'2',
time:'2019-04-26 10:51:19'
},{
name:'3',
time:'2019-04-26 11:04:32'
},{
name:'4',
time:'2019-04-26 11:05:32'
}
]
data.sort(function(a,b){
return a.time < b.time ? 1 : -1
});
按指定顺序排序
let list=['周一','周二','周三','周四','周五','周六','周日']
let data=['周四','周三','周二']
console.log(data.sort((a,b)=>{return list.indexOf(a)-list.indexOf(b)})) //结果['周二', '周三', '周四']
let dataName=[{name:'周四'},{name:'周三'},{name:'周二'}]
console.log(dataName.sort((a,b)=>{return list.indexOf(a.name)-list.indexOf(b.name)})) //[{name:'周二'},{name:'周三'},{name:'周四'}]
let data=[4,3,2]
console.log(data.sort((a,b)=>{return a-b})) //结果[2,3,4]
3.vue 解码获取url参数中包含的特殊字符
var uri="http://w3cschool.cc/my test.php?name=ståle&car=saab";
document.write(encodeURIComponent(uri)); //用encodeURIComponent解码
http%3A%2F%2Fw3school.cc%2Fmy%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab
http://w3schools.com/my test.asp?name=ståle&car=saab //用encodeURIComponent解码的结果
var uri="http://w3cschool.cc/my test.php?name=ståle&car=saab";
document.write(encodeURIComponent(uri)); //使用encodeURIComponent编码
以上实例输出结果:
http%3A%2F%2Fw3cschool.cc%2Fmy%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab
4.根据id来匹配后台返回来的数据后,获取该id的单条数据
//html
<el-button size="mini" type="danger" @change="selectpingtai(1)">获取后台id为1的数据</el-button>
//方法
selectpingtai: function(inspintai) {
this.$axios
.get(Url + "/PlatformAccount/findByPlatId", {
params: {
id: inspintai //接口带参数查询,根据接口需求(可不传inspintai)
}
})
.then(res => {
if (res.data.code == 200) {
var pipeilist = res.data.data;
var obj = pipeilist.find(function(obj) {
return obj.id === inspintai; //匹配id=1单条数据
});
console.log(obj) //获取到的id=1的单条数据
} else {
this.$message.info("暂无数据");
}
});
},
5.list集合中有三个对象,如如何删除对象中的指定的值
var data =[
{id:1,name:"a",age:"23"},
{id:2,name:"b",age:"25"},
{id:3,name:"c",age:"27"}
];
var zd = 1; //声明删除指定id=1的值
for (var i = 0; i <= data.length; i++) {
if (data[i].id == zd) { //循环匹配id=1的数据 (也可以匹配其他得值,如name,age)
data.splice(i, 1); //删除id=1的数据
console.log(data); // 得到剩下的list数据
}
}
6.将string转list集合
将
"[https://wx4.sinaimg.cn/large/9e5389bbly1g4tyqgszb5j212s0p6gq3.jpg, https://wx4.sinaimg.cn/large/9e5389bbly1g4tyqgsacdj20ls0qa75r.jpg, https://wx1.sinaimg.cn/large/9e5389bbly1g4tyqgs9hhj20ju0q3dhq.jpg, https://wx2.sinaimg.cn/large/9e5389bbly1g4tyqgrff0j20cb0afta1.jpg]"
转成
[{"img":"http://wx4.sinaimg.cn/orj360/9e5389bbly1g4tyqgszb5j212s0p6gq3.jpg"},{"img":"http://wx4.sinaimg.cn/orj360/9e5389bbly1g4tyqgsacdj20ls0qa75r.jpg"},{"img":"http://wx1.sinaimg.cn/orj360/9e5389bbly1g4tyqgs9hhj20ju0q3dhq.jpg"},{"img":"http://wx2.sinaimg.cn/orj360/9e5389bbly1g4tyqgrff0j20cb0afta1.jpg"}]
var a="[https://wx4.sinaimg.cn/large/9e5389bbly1g4tyqgszb5j212s0p6gq3.jpg, https://wx4.sinaimg.cn/large/9e5389bbly1g4tyqgsacdj20ls0qa75r.jpg, https://wx1.sinaimg.cn/large/9e5389bbly1g4tyqgs9hhj20ju0q3dhq.jpg, https://wx2.sinaimg.cn/large/9e5389bbly1g4tyqgrff0j20cb0afta1.jpg]";
var b=a.replace(/\[/g, ""); //去除左中括号
var c = b.replace(/\]/g, ""); //去除右中括号
var d=c.replace(/\ /g, ""); //去除空格
var e=d.split(","); //,分割
var all = [];
for (var i = 0; i < e.length; i++) {
all.push({ img: e[i] }); //循环重组list集合
}
console.log(all);
7.list 在最前面添加一项数据
//没添加前的数据
classificationlist: [
{ id: 1, name: "美妆" },
{ id: 2, name: "护肤" },
{ id: 3, name: "生活" },
{ id: 4, name: "美妆" }
],
//使用
classificationlist.unshift({ id: 0, name: "全部" }); //使用了unshift方法
//结果:
classificationlist: [
{ id: 0, name: "全部" },
{ id: 1, name: "美妆" },
{ id: 2, name: "护肤" },
{ id: 3, name: "生活" },
{ id: 4, name: "美妆" }
],
8.list 截取数据
//arrayObject.slice(start,end);
list=[{id:1,name:'LHC'},{id:2,name:'LHC'},{id:3,name:'LHC'},{id:4,name:'LHC'},{id:5,name:'LHC'},{id:6,name:'LHC'},{id:7,name:'LHC'},{id:8,name:'LHC'},{id:9,name:'LHC'}]
list.slice(2,6); //截取list的第三条开始到第七条的集合数据,即新的list=[{id:3,name:'LHC'},{id:4,name:'LHC'},{id:5,name:'LHC'},{id:6,name:'LHC'},{id:7,name:'LHC'}]
9.多个数组合并成一个,多个对象合并成一个
//arr1=[{name:'LHC',id:1},{name:'LHC087',id:2}] ,artr2={name:'LHC087087',id:3},artr3={name:'LHC0870870',id:4}
ver arrry=arr1.concat(arr2).concat(arr3).concat(arr4).concat(arr4);
//合并结果为arrry=[{name:'LHC',id:1},{name:'LHC087',id:2},{name:'LHC087087',id:3},{name:'LHC0870870',id:4}]
//两个对象合并成一个。
let para={name:'1'};
let para2={name2:'1'};
....
let a=Object.assign(para,para2,.....); //a就是{name:'1';name2:'1',...}
10.JS Array.reverse 将数组元素颠倒顺序
var arr=[255,36,677,355]
arr.reverse();
console.log(arr); //结果是[355,677,36,255]
11.数组对象合并
var platformTypeList= [
{ name: "小红书", id: 1 },
{ name: "微博", id: 2 }
],
var platformTypeListaddmore= [
{
values: "",
checked: false,
disableds: true,
ruless: [
{
required: false,
message: "小红书UID不能为空",
trigger: "blur"
},
{
pattern: /^[A-Za-z0-9]+$/,
message: "小红书UID不能含中文和标点符号",
trigger: "blur"
}
]
},
{
values: "",
checked: false,
disableds: true,
ruless: [
{ required: false, message: "微博UID不能为空", trigger: "blur" },
{
pattern: /^[A-Za-z0-9]+$/,
message: "微博UID不能含中文和标点符号",
trigger: "blur"
}
]
}
],
//ES6语法合并数组对象
var platformTypeListadd = platformTypeList.map(
(item, index) => {
return { ...item, ...platformTypeListaddmore[index] };
}
);
console.log(platformTypeListadd);
//platformTypeListadd:[
//合并之后的数据对象结构是这样的
// {
// name: "小红书",
// id: 1,
// values: "",
// checked: false,
// disableds: true,
// ruless: [
// {
// required: false,
// message: "小红书UID不能为空",
// trigger: "blur"
// },
// {
// pattern: /^[A-Za-z0-9]+$/,
// message: "小红书UID不能含中文和标点符号",
// trigger: "blur"
// }
// ]
// },
// {
// name: "微博",
// id: 2,
// values: "",
// checked: false,
// disableds: true,
// ruless: [
// { required: false, message: "微博UID不能为空", trigger: "blur" },
// {
// pattern: /^[A-Za-z0-9]+$/,
// message: "微博UID不能含中文和标点符号",
// trigger: "blur"
// }
// ]
// }
]
12.vue+element-ui中的el-table-column配合v-if 数据位置错乱问题
其实两种方法都是给所有列加了key值
第一种方法好在key值是随机数,添加列或者修改列顺序时,写上:key=Math.random()就行,但是渲染时列表会出现一瞬间的晃动
第二种不会出现晃动的瑕疵,但是修改key值麻烦
方式1:
<el-table-column label="商品id" :key="Math.random()"></el-table-column>
<el-table-column label="商品转态" v-if="activeIndex === '1'" :key="Math.random()"></el-table-column>
<el-table-column label="服务费" v-if="activeIndex === '2'" :key="Math.random()"></el-table-column>
方式2:
<el-table-column label="商品id" key="0"></el-table-column>
<el-table-column label="商品转态" v-if="activeIndex === '1'" key="1"></el-table-column>
<el-table-column label="服务费" v-if="activeIndex === '2'" key="2"></el-table-column>
13.给table 每行的操作按钮添加loding防止重复提交
//获取table数据后同时给每条数据设btnLoading字段,用this.$set()才有效
this.tableData.map(item => {
this.$set(item, 'btnLoading', false)
return item
})
//直接设置 :loading="scope.row.btnLoading"
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button v-loading="scope.row.btnLoading" size="mini" type="primary" @click="clickSendSmsBtn(scope.row)">
发送
</el-button>
</template>
<el-table-column>
//点击按钮方法时
clickSendSmsBtn(row) {
row.btnLoading= true; //当前按钮添加loding效果
sendMsgAPI({
row.msg
}).then(res => {
row.btnLoading= false //当前按钮去除loding效果
}).catch(_ => {
row.btnLoading= false //当前按钮去除loding效果
})
}
14.给table 的json数据添加index序号
for (let i = 0; i < tableData.length; i++) {
tableData[i].index = i + 1; //序号从1开始
}
//或者
elementui el-table根据分页显示表格序号
每页显示的序号都是一样的:
<el-table-column label="序号" type="index" align="center"></el-table-column>
根据分页显示序号:
当前点击的页码: currentPage
每页显示的数量: pageSize
<el-table :data="tableData" border>
<el-table-column label="序号" align="center" width="70">
<template slot-scope="scope"><span>{{scope.$index+(currentPage - 1) * pageSize + 1}} </span></template>
</el-table-column>
<el-table>
15.js 遍历数组取出字符串用逗号拼接
var arr = [{"name":"hhh"},{"name":"dddd"}]
var str = "";
for (var i = 0; i < arr.length; i++) {
str += arr[i].name+ ",";
}
//去掉最后一个逗号(如果不需要去掉,就不用写)
if (str.length > 0) {
str = str.substr(0, str.length - 1);
}
console.log(str)
16.正则获取字符串中的某一段值
var str="https://www.xiaohongshu.com/discovery/item/5d2d33d9000000002700d70c?xhsshare=CopyLink&appuid=5c3ecf5d00000000050278b7&apptime=1563243610"
var result = str.match(/item.*?xhsshare/g);
console.log(result) //结果为item/5d2d33d9000000002700d70c?xhsshare
17.重新命名后台返回来的key名
//平台搜索输入框
loadAllpingtai() {
this.$axios
.get(Url + "/Platform/getAllPlatInfo")
.then(res => {
if (res.data.code == 200) {
var data2 = [];
res.data.data.map((value, index, arry) => {
data2.push({
id: value.id,
value: value.platformName, //将后台数据的platformName变更为value
});
});
console.log(data2) //获取到的新key名的数据
} else {
this.$message.info("暂无数据");
}
});
},
18.循环转换返回来的后台数据类型
change(){
this.$axios
.get(Url + "/PlatformAccountRel/getAccountInfo")
.then(res => {
if (res.data.code == 200) {
if (res.data.data.length == 0) {
this.$message.info("数据为空!");
this.tableData = [];
this.totalCount = res.data.data.length;
} else {
this.tableData = res.data.data;
for (var i = 0; i < res.data.data.length; i++) {
res.data.data[i].newsPlatform = res.data.data[
i
].newsPlatform.toString(); //将布尔值转换成字符串型
res.data.data[i].videoPlatform = res.data.data[
i
].videoPlatform.toString(); //将布尔值转换成字符串型
}
this.totalCount = res.data.data.length;
this.$message.success("获取数据成功!");
}
} else {
this.$message.info("数据为空!");
}
this.loading = false;
});
}
19.Element ui select同时获取value和label的值
<el-form-item label="平台" prop="platformId">
<el-select
v-model="addForm.platformId"
filterable
clearable
placeholder="请选择平台"
class="ptselect"
@change="changehand(addForm.platformId)"
>
<el-option
v-for="item in pingtailist"
:key="item.id"
:label="item.platformName"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
data(){
return{
pingtailist:[{id:1,platformName:'平台一'},{id:2,platformName:'平台二'}]
}
},
methods:{
changehand(vId) {
let obj = {};
obj = this.pingtailist.find(item => {
//这里的pingtailist就是上面遍历的数据源
return item.id === vId; //筛选出匹配数据
});
console.log(obj.id); //获取到当前选择的item的id和label值
console.log(obj.platformName);
},
}
20.input输入框失去焦点事件
<el-form-item label="账号名称" prop="editaccountName">
<el-input
type="text"
v-model="editForm.accountName"
auto-complete="off"
@blur.prevent="selectfunction()" //blur.prevent 失去焦点触发事件
></el-input>
</el-form-item>
21.循环将list里面的数字字符串转成list[]
setNumber: function() {
var list="4,5,6,7,8," //多选下拉框id
var all = list.split(",");
var newarr = [];
for (var i = 0; i < all.length - 1; i++) { //all.length-1是去除最后面的 ‘,’ 逗号
var as = Number(all[i]);
newarr.push(as);
}
console.log(newarr); //将"4,5,6,7,8,"转成[4,5,6,7,8]
},
22.设缓存信息
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除。
sessionStorage 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。
//第一个页面设置
window.localStorage.setItem("name", "LHC");
//第二个页面获取
window.localStorage.getItem("name") //获取到第一个页面设置的name值
//删除指定键的数据语法:
window.localStorage.removeItem("name");
//删除所有数据:
window.localStorage.clear();
//或
//第一个页面设置
window.sessionStorage.setItem("name", "LHC");
//第二个页面获取
window.sessionStorage.getItem("name") //获取到第一个页面设置的name值
//删除指定键的数据语法:
window.sessionStorage.removeItem("name");
//删除所有数据:
window.sessionStorage.clear();
23.vue 设置cookies
在main.js写入
/* 自定义cookie相关方法 */
Vue.prototype.setCookie = function (cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
var expires = "expires=" + d.toUTCString();
console.info(cname + "=" + cvalue + "; " + expires);
document.cookie = cname + "=" + cvalue + "; " + expires;
console.info(document.cookie);
}
//获取cookie
Vue.prototype.getCookie = function (cname) {
var name = cname + "=";
var ca = document.cookie.split(";");
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == " ") c = c.substring(1);
if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
}
return "";
}
//清除cookie
Vue.prototype.clearCookie = function () {
this.setCookie("username", "", -1);
}
Vue.prototype.checkCookie = function () {
var user = this.getCookie("username");
if (user != "") {
alert("Welcome again " + user);
} else {
user = prompt("Please enter your name:", "");
if (user != "" && user != null) {
this.setCookie("username", user, 365);
}
}
}
在其他vue组件设置值
methods:{
this.setCookie("username",‘LHC’, 2); //调用上面main.js的方法设置值
console.log(this.getCookie("username")); //获取到cookie的值
}
24.json对象和字符串相互转换
1、json字符串转json对象,调用parse方法
var ob = JSON.parse(data);
2、json对象转为json字符串,调用JSON.stringify()方法
var str = JSON.stringify(data);
3.打印类型
console.log(typeof ‘LHC’);
25.共用多套验证规则时,可以在下拉选择时添加如下代码
在el-select组件的change事件添加
handleChange(val){
this.$refs.ruleForm.clearValidate(); //ruleForm为ref="ruleForm"表单名
this.$nextTick(() => this.$refs.ruleForm.clearValidate()) //ruleForm为ref="ruleForm"表单名
}
26.vue element table过滤器使用
<el-table-column label="营收(万)" prop="totalRevenue" align="center">
<template slot-scope="scope">
<p>{{scope.row.totalRevenue | totalRevenuefilters }}</p> //使用过滤器
</template>
</el-table-column>
//注册局部过滤器
filters: {
totalRevenuefilters(val) {
if (val == 0) {
return val;
} else if (val != 0) return val / 10000 + "万";
}
}
效果
27.vue element table表尾合计数据
<el-table
:data="tableData"
border
// sum-text="合计" 可直接添加默认第一列显示’合计‘字样
show-summary //显示合计行
:summary-method="getSummaries" //添加自定义合计行每一列显示数据的方法
style="width: 100%;"
height="80vh"
v-loading="loading"
>
</el-table>
getSummaries(param) { //方法
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = "合计"; //合计行第一列显示的字样 ,添加自定义方法时,上面的 sum-text="合计" 可不添加在<el-table>标签内
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] += "";
} else {
sums[index] = "--";
}
if (index === 2) { //第三列数据做处理,原来显示是11000的处理后显示的是1.1万
sums[2] = sums[2] / 10000 + "(万)";
return;
}
});
return sums;
},
效果
28.表格合计时解决精度丢失问题 Math.round( 总数据* 100) / 100
if (index === 4) {
sums[index] = Math.round(data2 * 100) / 100; //总计的数据添加这个可以解决小数点精度丢失的问题
return;
}
29.解决element组件分页点击下几页时再重新用别的接口请求数据时,页数的激活状态没跳回第一页
这里需要先删除分页组件再重新加载分页组件
<!-- 分页 -->
<div class="tabListPage" v-if="showpage"> //用v-if判断
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[15]"
:page-size="PageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalCount"
></el-pagination>
</div>
data(){
return{
showpage: true,
}
}
selectdata(){ //在重新加载数据时,先执行删除分页组件再重新加载组件
this.showpage = false;
this.$nextTick(() => {
this.showpage = true;
});
}
30.解决element组件获取后台数据排序
1、如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-change事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。
<el-table @sort-change='tableSortChange'>
<el-table-column sortable='custom' prop="createTime" label="创建时间">
</el-table-column>
</el-table>
2、定义methods监听sort-change事件
sort-change方法自带三个参数,分别代表意义是:
column:当前列
prop:当前列需要排序的数据
order:排序的规则(升序、降序和默认[默认就是没排序])
tableSortChange(column) {
if (column.order === 'descending') {
console.log('降序')‘;
this.listQuery.sortby = column.prop
this.listQuery.order = 'desc'
} else {
console.log('升序')‘;
this.listQuery.sortby = column.prop
this.listQuery.order = 'asc'
}
this.getList()
}
3、通过axios提交请求数据到后端
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
this.listLoading = false
})
}
31.关于vue 项目页面打包后首次页面加载特别缓慢的原因及解决方案
1,去掉编译文件中map文件。在编译好后,我们会看到文件夹下有特别多的.map文件,这些文件主要是帮助我们线上调试代码,查看样式。所以为了避免部署包过大,通常都不生成这些文件。
在 config/index.js 文件中将productionSourceMap 的值设置为false. 再次打包就可以看到项目文件中已经没有map文件
2,vue-router 路由懒加载
懒加载即组件的延迟加载,通常vue的页面在运行后进入都会有一个默认的页面,而其他页面只有在点击后才需要加载出来。使用懒加载可以将页面中的资源划分为多份,从而减少第一次加载的时候耗时。
懒路由写法如下:
3,使用gzip压缩
由于项目测试使用的是tomcat 服务器,因此这个我只在本地安装Nginx 服务器进行测试。在tomcat 服务器下也有压缩文件的方法,暂时没试过。
1),在安装完依赖插件后,修改config/index.js 文件下 productionGzip:true ;
安装依赖:npm install --save-dev compression-webpack-plugin@1.1.11
(如果版本太高导致报错,打包不了)
2),然后在 webback.prod.config.js 中添加如下代码。(文件大小 10.5MB–>3.5MB)
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: ‘[path].gz[query]’,
algorithm: ‘gzip’,
test: new RegExp(
‘\.(’ +
config.build.productionGzipExtensions.join(‘|’) +
‘)$’
),
threshold: 10240,
// deleteOriginalAssets:true, //删除源文件
minRatio: 0.8
})
)
3),最后在Nginx 下开启gzip 。
首先安装Nginx 服务器,然后将项目文件部署到html文件目录下,如果端口被占用,可以修改 config/nginx.conf 文件中listen:somename 来修改端口。
开启gzip:
在config/nginx.config 添加如下配置。
http:{
gzip on;
gzip_static on;
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg
image/gif image/png;
}
修改完成后,reload一下,重启服务。
4,使用CDN加载
在打包后发现vendor.js 文件占用内存特别大,这里面主要是使用的一些第三方库,例如 vuex,vue-router,axios,elementUI 等文件
我们除了在使用过程中单个组件引用,还可以使用CDN 加载。
通过在index.html 中直接引入第三方资源来缓解我们服务器的压力,其原理是将我们的压力分给了其他服务器站点。
5,其次打包后需要去掉代码中的console.log ,防止打开f12 的时候输出日志。
在webpack.prod.conf.js 文件中设置
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
})
32.vue element 菜单栏点击其他第一级菜单时,关闭当前已打开的第二级菜单栏
<el-menu
:default-active="$route.path"
class="sidebar-menu"
:collapse="!openNav"
@select="menuSelect"
:collapse-transition="false"
:default-openeds="openeds"
>
data() {
return {
openeds: [],
}
}
//方法
menuSelect(index, keyPath) {
if (keyPath.length > 1) {
this.openeds = [keyPath[0]];
} else {
this.openeds = [];
}
this.$router.push(index);
},
33.vue element table传参后端排序
<el-table
:data="tableData"
border
style="width: 100%"
v-loading="loading"
ref="sort" //设置 ref="sort" 刷新时执行 this.$refs.sort.clearSort();可清除默认排序样式
@sort-change="tableSortChange" //table设置排序监听事件
>
<el-table-column
label="发布时间"
prop="publish_date"
align="center"
width="180"
sortable="custom" //设置需要排序的lie
></el-table-column>
</el-table>
data() {
return {
tableData:[],
orderWay : 0, //默认为降序
}
}
//事件
//排序
tableSortChange: function(column) {
//console.log(column) 可以获取表内列的属性
if (column.column.label == "发布时间") { //根据该列属性设置请求参数
if (column.order === "descending") {
console.log("发布时间降序");
//降序
this.orderWay = 0; //设置请求参数(该参数是后台定义的,0为降序)
} else {
console.log("发布时间升序");
//升序
this.orderWay = 1; //设置请求参数(该参数是后台定义的,1为升序)
}
this.getUserstableData(); //上面的请求参数已修改,调用请求后台的接口获取排序后的数据再渲染到表内
},
34.v-model.trim属性实现去除input值的前后空格
<el-input
type="text"
v-model.trim="ruleForm2.phone" //用v-model.trim可以实现键盘输入时禁止在值前添加空格和提交时去除值的前后空格
auto-complete="off"
placeholder="手机号"
clearable
></el-input>
35.element日期时间组件传参数
//用于搜索条件查询表格数据时
data(){
return{
dateTime :[]
}
}
//请求参数写法:
startTime: (this.dateTime && this.dateTime [0]) || "",
endTime: (this.dateTime && this.dateTime [1]) || ""
或
startTime: this.dateTime ? this.dateTime [0] : "",
endTime: this.dateTime ? this.dateTime [1] : "",
//如果是请求后端导出时
get请求
"&startTime=" +
((this.dateTime && this.dateTime [0]) || "") +
"&endTime=" +
((this.dateTime&& this.dateTime[1]) || "") +
36.element type="number"的input输入框只能输入数字,限制不能输入e
<el-form-item label="折扣率:" prop="rebateDiscount">
<el-input
type="number"
@keydown.native="channelInputLimit" //添加方法
v-model.trim="editrebateForm.rebateDiscount" //trim修饰符去除前后空格
clearable
></el-input>
</el-form-item>
data() {
var checknumber = (rule, value, callback) => {
// var reg = /^[\d]+$/; //正则验证整数
// if (value && !reg.test(value)) {
// callback(new Error("请输入不小于0的整数"));
// }
if (value < 0 || value == 0) {
callback(new Error("请输入不小于0的数字"));
} else {
callback();
}
};
return {
editrebateRules: {
rebateDiscount: [
// { required: true, message: "折扣率不能为空", trigger: "blur" },
{
validator: checknumber, //验证规则限制为大于0的数据
trigger: "blur"
}
]
},
}
methods: {
channelInputLimit(e) {
let key = e.key;
// 不允许输入'e'
if (key === "e") {
e.returnValue = false;
return false;
}
return true;
},
37.JS处理数据
- 将 list = [
{ name: “直发”, value: “1”, voName: “amtDirect” },
{ name: “转发”, value: “2”, voName: “amtForward” }
];
转换成
{amtDirect:‘1’,amtForward:‘2’}
传给后台
var list = [
{ name: "直发", value: "1", voName: "amtDirect" },
{ name: "转发", value: "2", voName: "amtForward" }
];
let obj = {};
list.map(e => {
obj[e.voName] = e.value;
});
console.log(list);
console.log(obj);
- 根据后台返回的list数据的某字段去取这条数据
list = [
{ name: “直发”, value: “1”, voName: “amtDirect”,priceType:0 },
{ name: “转发”, value: “2”, voName: “amtForward”,priceType:1 }
];
根据 priceType字段去取这条数据
var list = [
{ name: "直发", value: "1", voName: "amtDirect" },
{ name: "转发", value: "2", voName: "amtForward" }
];
var dataPost1 = [];
var dataPost2 = [];
dataPost1 = list.filter(
item => item.priceType === 0
);
dataPost2 = list.filter(
item => item.priceType === 1
);
console.log(dataPost1); // { name: "直发", value: "1", voName: "amtDirect" },
console.log(dataPost12); // { name: "转发", value: "2", voName: "amtForward" }
- 对象根据key匹配一一赋值给对应的数组
var list = [
{ amtDirect: 1, amtForward: 2, priceType: 0 },
{ amtDirect: 3, amtForward: 4, priceType: 1 }
];
var dataGet1 = [
{ name: “直发”, voName: “amtDirect”, value: “” },
{ name: “转发”, voName: “amtForward”, value: “” }
];
结果:dataGet1 的value值取到了对应list里面对应key的value值
dataGet1 = [
{ name: “直发”, voName: “amtDirect”, value: 1 },
{ name: “转发”, voName: “amtForward”, value: 2 }
];
var list = [
{ amtDirect: 1, amtForward: 2, priceType: 0 },
{ amtDirect: 3, amtForward: 4, priceType: 1 }
];
var dataPost1 = [];
var dataPost2 = [];
var dataGet1 = [
{ name: "直发", voName: "amtDirect", value: "" },
{ name: "转发", voName: "amtForward", value: "" }
];
var dataGet2 = [
{ name: "直发", voName: "amtDirect", value: "" },
{ name: "转发", voName: "amtForward", value: "" }
];
dataPost1 = list.filter(item => item.priceType === 0);
dataPost2 = list.filter(item => item.priceType === 1);
var datass = Object.keys(dataPost1[0]);
for (var i = 0; i < datass.length; i++) {
dataGet1.map(item => {
if (item.voName == datass[i]) {
item.value = this.getNthFromObject(dataPost1[0], i);
}
});
}
var datass1 = Object.keys(dataPost2[0]);
for (var j = 0; j < datass1.length; j++) {
dataGet2.map(item => {
if (item.voName == datass1[j]) {
item.value = this.getNthFromObject(dataPost2[0], j);
}
});
}
console.log(list);
console.log(dataPost1);
console.log(datass);
console.log(dataGet1);
console.log(dataPost2);
console.log(datass1);
console.log(dataGet2);
另外getNthFromObject方法:
function getNthFromObject(data, nth) {
if (data == null) return null;
let n = 0;
for (let k in data) {
if (data.hasOwnProperty(k) && n == nth) {
return data[k];
}
n++;
}
return null;
},
38.element tree功能
//console.log(this.dep(treeData)) 过滤子节点
dep(list) {
//没有子节点时不展示出来
if (list && list.length) {
return list.filter(v => {
if (v.children) {
v.children = this.dep(v.children)
if (v.children === null || v.children.length === 0) {
return false
}
}
return true
})
}
return list
},
//递归匹配找子节点
//this.getParentId(this.treeData, '13527466666')//通过传入mobile字段匹配
//匹配获取子节点
// getParentId(list, iid) {
// for (let o of list || []) {
// if (o.mobile === iid) {
// return o
// }
// const o_ = this.getParentId(o.children, iid)
// if (o_) {
// return o_
// }
// }
// },
//数组对象获取所有的id组成新数组
this.arrData.map(item => {
return item.id
})
//递归获取树下所有相同的数据
//this.setName(this.treeData, '13527466666' )
var expandedKeysCopy=[]
setName(datas, ins) {
//遍历树 获取id数组
for (var i in datas) {
if (datas[i].mobile === ins) {
this.expandedKeysCopy.push(datas[i])
}
if (datas[i].children) {
this.setName(datas[i].children, ins)
}
}
}
//递归添加唯一ID
setId(list, ins) {
//添加唯一key(id)
return list.map((item, index) => {
item = Object.assign({}, item)
if (ins) {
//二层的id
item.id = Number(String(ins.id) + String(index))
} else {
//一层的id
item.id = index + 1
item.name = item.deptName
item.mobile = item.deptUri
}
if (!!item.children && item.children.length > 0) {
item.children = this.setId(item.children, item)
}
return item
})
},
左边相同数据勾选时左边相同数据同时勾选上右边只出现一条,右边删除时,左边相同的数据同时取消勾选的功能
//html
<!-- 添加员工 -->
<el-dialog title="添加员工" :visible.sync="dialogVisible" width="50%" :close-on-click-modal="false">
<div class="margin-10 box-s-d">
<el-row class="bg-black">
<el-col :span="12">
<div class="padding-1-r-20">
<el-input placeholder="请输入输入姓名/手机号" v-model="filterText" class="margin-t-b-10"></el-input>
</div>
</el-col>
<el-col :span="12" class="padding-1-20">
<span class="title">{{ roleName }}角色账号</span>
<span class="title2 color-danger cursor-p" @click="clearAll">清空</span>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12" class="scroll-box">
<div class="margin-t-b-5">
<el-tree
:data="treeData"
show-checkbox
default-expand-all
node-key="id"
ref="tree"
highlight-current
:props="defaultProps"
:filter-node-method="filterNode"
@check="checkTreeFun"
></el-tree>
</div>
</el-col>
<el-col :span="12" class="scroll-box">
<div v-if="addtreeData.length > 0" class="margin-t-b-5">
<div v-for="(item, index) in addtreeData" :key="index">
<el-col :span="20" class="text-left margin-t-b-5">{{ item.name }}</el-col>
<el-col :span="4" class="text-right margin-t-b-5">
<i class="el-icon-error color-danger" title="删除" @click="deleteFun(item, index)"></i>
</el-col>
</div>
</div>
<div v-else class="text-center color-font-sub content-center">暂无数据</div>
</el-col>
</el-row>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitAdd">保存</el-button>
</span>
</el-dialog>
//js
import { permissionsFilter } from '@/config/filters.js'
export default {
name: 'Permissions',
data() {
return {
domainUri: JSON.parse(sessionStorage.getItem('roleInfo')).fkdomain,
// 权限设置 - 表格数据
lists: [],
//添加员工
dialogVisible: false,
roleName: '',
roleId: '',
treeData: [],
filterText: '',
//选取的数据
addtreeData: [],
expandedKeys: [], //默认选择数据
expandedKeysCopy: [],
defaultProps: {
children: 'userAccount4ListVOList',
label: function(data, node) {
return data.name || data.deptName
}
}
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
}
},
created() {
// 获取权限设置列表
this.getList()
},
methods: {
// 获取权限设置,用信列表
getList() {
this.$http.permissions.getRoleQuery().then(res => {
console.log('查询权限列表:', res)
if (res.result) {
this.lists = permissionsFilter(res.result)
}
})
},
//添加员工
addUserFun(ins) {
this.dialogVisible = true
this.roleName = ins.name
this.roleId = ins.uri
this.addtreeData = []
this.getTreeData()
},
setId(list, ins) {
//添加唯一key(id)
return list.map((item, index) => {
item = Object.assign({}, item)
if (ins) {
item.id = Number(String(ins.id) + String(index)) // 注意子级id字符串长度不够和一级的100后的重复了,这里继续拼接字符,太长会报精度丢失的问题
} else {
item.id = index + 1
item.name = item.deptName
item.mobile = item.deptUri
}
if (!!item.userAccount4ListVOList && item.userAccount4ListVOList.length > 0) {
item.userAccount4ListVOList = this.setId(item.userAccount4ListVOList, item)
}
return item
})
},
getTreeData() {
let params = {
domainUri: this.domainUri,
roleUri: this.roleId
}
this.$http.permissions
.getUserListByGroup(params)
.then(res => {
var data = res.result.userGroupInfoVOS
this.treeData = this.setId(data)
if (res.result.userAccount4ListVOS) {
//回显数据
this.addtreeData = this.unique(res.result.userAccount4ListVOS)
this.setCheckedNodes(this.addtreeData)
}
})
.catch(err => {})
},
setName(datas, ins) {
//遍历树 获取id数组
for (var i in datas) {
if (datas[i].mobile === ins) {
this.expandedKeysCopy.push(datas[i])
}
if (datas[i].userAccount4ListVOList) {
this.setName(datas[i].userAccount4ListVOList, ins)
}
}
},
//默认选中
setCheckedNodes(ins) {
this.expandedKeys = []
this.expandedKeysCopy = []
ins.map(item => {
this.setName(this.treeData, item.mobile)
})
this.expandedKeys = this.expandedKeysCopy.map(item => {
return item.id
})
this.$refs.tree.setCheckedKeys(this.expandedKeys)
},
//过滤节点
filterNode(value, data) {
if (!value) {
return true
}
return data.name.indexOf(value) !== -1 || data.mobile.indexOf(value) !== -1
},
checkTreeFun(data) {
//匹配已选数据是否存在当前勾选数据
var obj = this.addtreeData.find(function(obj) {
return obj.mobile === data.mobile
})
if (obj === undefined) {
//不存在就是添加
var dataarr = this.$refs.tree.getCheckedNodes(true, false)
this.addtreeData = this.unique(dataarr)
} else {
//存在先删除
this.addtreeData.splice(
this.addtreeData.findIndex(item => item.mobile === data.mobile),
1
)
}
this.setCheckedNodes(this.addtreeData)
},
//删除
deleteFun(nodeObj, index) {
this.addtreeData.splice(index, 1)
this.setCheckedNodes(this.addtreeData)
this.$refs.tree.setChecked(nodeObj.id, false, true)
},
//清空
clearAll() {
this.addtreeData = []
this.$refs.tree.setCheckedKeys([])
},
//数组去重
unique(arr) {
const res = new Map()
return arr.filter(arr => !res.has(arr.mobile) && res.set(arr.mobile, 1))
},
//点击添加员工
submitAdd() {
var arry2 = []
this.addtreeData.map((item, index) => {
arry2.push(Object.assign({}, item, { roleId: this.roleId }))
})
let params = {
userCurrentRoleList: this.unique(arry2)
}
if (arry2.length === 0) {
this.info('请选择员工')
} else {
this.$http.permissions
.addUserRole(params)
.then(res => {
if (res.message === 'success') {
this.message(`权限设置成功`)
this.getList()
this.dialogVisible = false
} else {
this.error(res.message)
}
})
.catch(err => {})
}
}
}
}
//css
.credit-manage {
.content-table {
padding: 14px 0;
}
.el-table {
margin-top: 0;
}
/deep/.el-dialog__footer {
text-align: center;
}
.title {
font-size: $font-size-18;
color: $color-black;
line-height: 52px;
}
.title2 {
float: right;
line-height: 52px;
margin-right: 5px;
}
.content-center {
position: relative;
top: 50%;
transform: translateY(-50%);
}
.bg-black {
background-color: #f9f9f9;
}
.scroll-box {
height: 400px;
overflow: auto;
}
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
width: 8px; /*滚动条宽度*/
height: 8px; /*滚动条高度*/
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(8, 8, 8, 0.2);
box-shadow: inset 0 0 6px rgba(8, 8, 8, 0.2);
border-radius: 10px; /*滚动条的背景区域的圆角*/
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb {
border-radius: 10px; /*滚动条的圆角*/
box-shadow: inset 0 0 6px rgba(8, 8, 8, 0.3);
-webkit-box-shadow: inset 0 0 6px rgba(8, 8, 8, 0.3);
}
}
tree实现单选和多选
事件@check=“checkFun”
//checkData为勾选的数据,multiple是否多选,unique去重方法,setCheckedNodes勾选方法
checkFun(data) {
// 匹配已选数据是否存在当前勾选数据
var obj = this.checkData.find(obj => {
return obj.uri === data.uri
})
if (obj === undefined) {
// 不存在添加
var dataArr = this.$refs.tree.getCheckedNodes(true, false)
if (!this.multiple) {
// 单选
if (data.type && data.type === 'user') {
// 点击的是用户
if (this.checkData.length === 0) {
// 没有时
this.checkData = this.unique(dataArr)
} else {
// 如果存在直接替换
this.checkData = [data]
}
} else {
// 点击的非用户
if (data.child && data.child.length > 0) {
this.$message({
message: '请选择人员',
type: 'warning'
})
}
}
} else {
// 多选
this.checkData = this.unique(dataArr)
}
} else {
// 存在先删除
this.checkData.splice(
this.checkData.findIndex(item => item.uri === data.uri),
1
)
}
this.checkData = this.checkData.filter(item => {
return (item.type && item.type === 'user') || item.type === '102' || item.type === '104'
})
this.setCheckedNodes(this.checkData)
}
// 默认选中
setCheckedNodes(ins) {
this.expandedKeys = []
this.expandedKeysCopy = []
let res = ins.map(async item => {
await this.setName(this.treeData, item.uri)
})
if (res) {
this.expandedKeys = this.expandedKeysCopy.map(item => {
return item.uniqueKey //通过树的uniqueKey唯一值去勾选树的数据
})
this.$nextTick(() => {
this.$refs.tree.setCheckedKeys(this.expandedKeys)
})
}
}
setName(datas, ins) {
datas.map(obj => {
if (obj.uri === ins) {
this.expandedKeysCopy.push(obj)
}
if (obj.child && obj.child.length) {
this.setName(obj.child, ins)
}
})
}
tree树获取过滤函数的树节点
@Watch('filterText', { deep: true })
filterTextChange(val) {
this.$refs.tree.filter(val)
this.getFilterData() //监听输入框的时候调用
}
// 获取过滤后的树
// npm安装circular-json,filterText为过滤的条件,filterData为获取到的匹配子节点数据
import CircularJSON from 'circular-json' // 引入circular-json
async getFilterData() {
if (this.filterText) {
this.filterData = []
const rootData = this.$refs.tree.root
if (rootData.visible) {
// 有过滤数据
const childNodesStr = CircularJSON.stringify(rootData.childNodes)
const childNodes = CircularJSON.parse(childNodesStr)
var visibleData = await this.recursionNodes(childNodes) //这里只是获取到最上层的父节点
// 获取过滤后的所有type=user
await this.getFilterChileData(visibleData, this.filterText) //这里是业务需求,需要获取到父节点下的人
this.showNodata = true
} else {
// 无过滤数据
this.showNodata = false
}
} else {
this.showNodata = true
}
}
recursionNodes(childNodes) {
const nodes = childNodes
const result = []
for (const item of nodes) {
if (item.visible) { //通过树的visible为true获取所有的节点
result.push(item.data)
}
if (item.childNodes && item.childNodes.length) {
const tempResult = this.recursionNodes(item.childNodes)
item.data.children = tempResult
}
}
return result
}
getFilterChileData(datas, ins) {//用递归实现获取父节点下name和filterText匹配的所有人filterData
datas.map(obj => {
if (((obj.type && obj.type === 'user') || obj.type === '102' || obj.type === '104') && obj.name.indexOf(ins) !== -1) {
this.filterData.push(obj)
}
if (obj.child && obj.child.length) {
this.getFilterChileData(obj.child, ins)
}
})
}
39.找出两个数组的不同之处
getArrDifference(arr1, arr2) {
return arr1.concat(arr2).filter(function(v, i, arr) {
return arr.indexOf(v) === arr.lastIndexOf(v)
})
},
// 调用
getArrDifference([1,2,3],[3,4,5]) //得到[1,2,4,5]