常用代码片段
- 文字一行显示,溢出省略
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
2 css两行显示,超出省略
p {
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
3.数组对象去重
//数组对象去重
function(arr, key) {
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i][key]) {
if (arr[i][key] === arr[j][key]) {
arr.splice(j, 1)
j = j - 1
}
}
}
}
return arr
}
4.验收手机号码格式
// 验证手机号码格式
export const phoneVerification = function(phone) {
let phoneCodeVerification = /^[1][3,4,5,7,8][0-9]{9}$/
return phoneCodeVerification.test(phone)
}
- 验证邮箱格式
// 验证邮箱格式
export const emailVerification = function(email) {
let emailCodeVerification = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
return emailCodeVerification.test(email)
}
6.html编码和解码
// html解码
export function ESCAPE_HTML(str, moreSign = {}) {
let arrEntities = {
lt: '<',
gt: '>',
nbsp: ' ',
amp: '&',
quot: '"',
...moreSign
}
let newEntities = {
'40': '@',
'2b': '+',
'24': '$',
'23': '#',
'2c': ',',
'7c': '|'
}
str = str.replace(/javascript:void\(0\);|javascript:void\(0\)/g, '#')
// console.log('str--', str)
// 直接过滤document script eval三个特殊单词
str = str.replace(/document|script|eval/g, '')
str = str.replace(/&(lt|gt|nbsp|amp|quot);/gi, function(all, t) {
return arrEntities[t]
})
// FIXME 待优化把两个正则合并成一个
return str.replace(/%(40|2b|24|23|2c|7c);/gi, function(all, t) {
return newEntities[t]
})
}
// 编码到后台
export function HTML_ESCAPE(str, noEscape = []) {
str = str.replace(/javascript:void\(0\);|javascript:void\(0\)/g, '#')
return str.replace(/[<>&"@+$#,|]/g, function(c) {
// 哪些字符不需要过滤
if (noEscape.includes(c)) {
return c
}
return {
'<': '<',
'>': '>',
'&': '&',
'"': '"',
'@': '%40;',
'+': '%2b;',
$: '%24;',
'#': '%23;',
',': '%2c;',
'|': '%7c;'
}[c]
})
}
7.将手机号中间4位替换为* 号
let phone = '13800138000'
let reg = /(\d{3})\d{4}(\d{3})/g
console.log(reg.test(phone));
console.log(phone.replace(reg,'$1****$2')); // 138****8000
- Excel 转base64 下载
excel下载
responseType: 'blob', //在请求api 添加上这一于
// 接口返回的数据 获取到 res.data
//将接口返回的数据rse.data 直接给下面这段方法 执行自动下载
let url = window.URL.createObjectURL(res.data)
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', '文件名.xlsx') //(设置按钮执行下载事件download ,下载的文件名)
document.body.appendChild(link)
link.click()
9 Excel文件上传( formdata)
Excel 文件上传
<input type="file" class="uploadExcel" accept=".xls, .xlsx" id="importExcel"
@change="submitCollectionFlowImport" />
data() {
return {
form: {
name: ''
},
file: undefined //
}
},
// 选择上传文件触发事件
submitCollectionFlowImport(e) {
var excelFile = document.getElementById('importExcel').files[0] //根据获取到的input dom元素 获取到上传的文件
console.log(excelFile)
let fileFormData = new window.FormData() //创建一个FormData对象 vue环境创建 要window.FormData
fileFormData.append('file', excelFile) //(上传的文件, 上传的文件名)
this.file = fileFormData
},
async submit() {
const res = await importClientExcel(this.file) //调用接口发请求 直接把file文件传参
console.log(res)
if (res.data.code === 0) {
this.$message.success('导入成功')
} else {
this.$message.error(res.data.msg)
}
this.dialogShowSwitch = false
}
- 使用 encodeURIComponent加码 decodeURIComponent 解码
// 使用 encodeURIComponent加码 decodeURIComponent 解码
// 加码
var objectToQueryString = (obj) => Object.keys(obj).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
objectToQueryString({ name: '王总', slogen: '属实', age: 26, icon: '/' }) //name=%E7%8E%8B%E6%80%BB&slogen=%E5%B1%9E%E5%AE%9E&age=26&icon=%2F
// 解码
let url = 'name=%E7%8E%8B%E6%80%BB&slogen=%E5%B1%9E%E5%AE%9E&age=26&icon=%2F'
console.log(decodeURIComponent(url)); //name=王总&slogen=属实&age=26&icon=/
h5c3部分属性代码
背景属性复合写法
//background: 颜色 url() 平铺 水平定位 纵向定位/ 缩放或长度 缩放或宽度
background: url(./logo.png) no-repeat 0 0/142px 58px;
background: green url(img/bg.jpg) no-repeat 0 0 100% 100%
background: green url(img/bg.jpg) no-repeat left bottom 100% 100%
background: green url(img/bg.jpg) no-repeat center center 100% 100%
Ajax的get请求 XMLHttpRequest.readyState的四个阶段MDN链接
return new Promise((resolve, reject) => {
//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数
ajax.open('get', 'http://127.0.0.1:5000/api/longlist');
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
// XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态 包含四个状态
// 0 UNSENT 代理被创建,但尚未调用 open() 方法。
// 1 OPENED open() 方法已经被调用。
// 2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
// 3 LOADING 下载中; responseText 属性已经包含部分数据。
// 4 DONE 下载操作已完成。
ajax.onreadystatechange = function () {
console.log(ajax);
if (ajax.readyState == 4 && ajax.status == 200) {
//步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
resolve(JSON.parse(ajax.responseText))
}
}
})
封装axios 请求
- 先在unils文件夹封装一个fetch 请求方法
// request拦截器
import axios from 'axios'
// import Message from '@/lib/ego-ui/packages/message'
import { Message } from 'element-ui'
// import router from '../router'
// 创建axios实例
const service = axios.create({
timeout: null // 请求超时时间
})
let serviceTips = '服务器超时'
// request拦截器
service.interceptors.request.use(
config => {
// 获取本地token
let token = localStorage.getItem('tokendata')
// 设置请求头
let headers = 'application/json'
// 是否携带token
let tokenFlag = true
// 防止IE浏览器获取到缓存数据
if (config.url.indexOf('?time') < 1) {
if (config.url.indexOf('?') < 1) {
config.url += '?time=' + new Date().getTime()
} else {
config.url += '&time=' + new Date().getTime()
}
}
// 是否修改请求信息
if (config.opts) {
// 获取携带token状态
tokenFlag = config.opts ? config.opts.token : true
// 获取请求头
// headers = config.opts.Header ? config.opts.Header : 'application/json'
// 拓展头部参数
let Head = config.opts.Head
if (Head) {
for (let key in Head) {
config.headers[key] = Head[key]
if (key === 'Content-Type') {
headers = Head[key]
}
}
}
}
if (token && tokenFlag) {
// 条件允许,携带token请求
// config.headers['token'] = token
config.headers['X-Auth0-Token'] = token
} else {
// headers = 'application/x-www-form-urlencoded'
}
// 设置请求格式
config.headers['Content-Type'] = headers
// config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
return config
},
err => {
return Promise.reject(err)
}
)
// http response 服务器响应拦截器
service.interceptors.response.use(
response => {
if (
response.data.code === -401 ||
response.data.code === 3001 ||
response.data.code === 40001 // ❌和后台返回code码 冲突 临时注释
) {
localStorage.removeItem('tokendata')
window.location.href = window.location.origin
// router.replace({
// path: '/login'
// })
}
return response
},
error => {
if (error.response) {
switch (error.response.status) {
case 400:
console.log(error.response)
error.response.data = '资源不存在'
break
case 401:
error.response.data = '登陆超时,重新登陆'
localStorage.removeItem('tokendata')
window.location.href = window.location.origin
// router.replace({
// path: '/login',
// query: {
// // redirect: router.currentRoute.fullPath
// } // 登录成功后跳入浏览的当前页面
// })
break
case 404:
error.response.data = '资源不存在'
break
case 406:
error.response.data = '头部无携带token'
break
case 412:
localStorage.removeItem('tokendata')
// 拦截错误 并重新跳入登页重新获取token
window.location.href = window.location.origin
// router.replace({
// path: '/login',
// query: {
// redirect: router.currentRoute.fullPath
// } // 登录成功后跳入浏览的当前页面
// })
error.response.data = '秘钥失效'
localStorage.removeItem('tokendata') // 清除token
break
case 415:
error.response.data = '请求type有误'
break
case 500:
error.response.data = '服务器异常'
break
}
serviceTips = error.response.data
}
// Message({
// message: serviceTips,
// theme: 'danger'
// })
Message.error(serviceTips)
return Promise.reject(serviceTips)
}
)
export default service
- 引入fetch方法,封装各个aip请求接口
// 引入拦截器
import Ajax from '@/utils/fetch'
// 引入公共JS
import until from '@/utils/until'
import Qs from 'qs'
// 引入接口前缀
const scrmAdminBase = until.scrmAdminBase
// 查询企微客户列表
function getQwList(data) {
return Ajax({
method: 'get',
url: scrmAdminBase + `/externalContact/list?${Qs.stringify(data, { indices: false })}`
// url: scrmAdminBase + `/externalContact/list/`,
// params: data
})
}
- 在对应的vue组件中引入直接调用发起接口请求
import { clientManageApi } from '@/api/api'
const { getQwList } = clientManageApi
created() {
this.getQwList()
},
methods: {
// 企微客户列表
async getQwList() {
this.loading = true
this.exportQueryForm = {}
const res = await getQwList({ ...this.queryForm, ...this.commonQueryForm })
this.exportQueryForm = this.commonQueryForm
console.log(this.exportQueryForm)
// console.log(res)
if (res.data.code === 0) {
console.log('获取到企微客户列表', res)
res.data.data.records.map((item) => {
item.totalSocure = []
item.followUserList.map((item1) => {
// console.log(item.totalSocure)
// console.log(item1.addWay)
if (item.totalSocure.indexOf(item1.addWay) === -1) {
item.totalSocure.push({ addWay: item1.addWay, addWayType: item1.addWayType })
console.log(item.totalSocure.length)
}
})
})
// console.log(this.tableData)
this.tableData = res.data.data.records
this.total = res.data.data.total
} else {
this.$message.error('数据加载异常')
}
this.loading = false
},
element-dialog弹窗代码片段
<template>
<div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
@closed="handleClose">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props:{
show:{
type:Boolean,
default:false
},
},
data() {
return {
dialogVisible:false
}
},
watch: {
show(newV){
this.dialogVisible = newV
},
},
methods: {
handleClose(){
this.$emit('update:show',this.dialogVisible)
},
},
}
</script>
<style>
</style>
- 时间戳转换为日期
filters:{
localTimeType(val){ //时间戳转换为日期
let now = new Date(parseInt(val + '000')) //标准长度的时间戳不用加三个零
var y = now.getFullYear()
var m = now.getMonth() + 1
var d = now.getDate();
var h = now.getHours()
var min= now.getMinutes()
return `${y}-${m}-${d} ${h}:${min}` // 输出时间格式: 2022-6-24 14:51
}
},
- vue watch监听computed计算属性,实现动态监听vuex中state属性变化
computed:{
newPageName(){
return this.$store.state.pageName //引用vuex动态属性
}
},
watch:{
newPageName:{ //监听计算属性
handler(newV){
console.log('窗口切换',newV);
this.showAddBtn = (newV === 'draft'?false:true)
},
immediate:true //深度监听
}
},
- 一键复制图片操作
// img转base64
imageToBase64(image) {
let canvas = document.createElement('canvas')
let width = image.width
let height = image.height
canvas.width = width
canvas.height = height
let context = canvas.getContext('2d')
context.drawImage(image, 0, 0, width, height)
// console.log(canvas.toDataURL('image/png'));
return canvas.toDataURL('image/png')
},
//url图片转base64
urlToBase64(url) {
let image = new Image()
image.setAttribute('crossOrigin', 'Anonymous')
image.src = url + '?v=' + Math.random()
image.onload = async ()=>{
let dataURL = await this.imageToBase64(image)
await this.base64ToBlob(dataURL)
}
},
async base64ToBlob(code) {
var parts = code.split(";base64,");
var contentType = parts[0].split(":")[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uint8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; i++) {
uint8Array[i] = raw.charCodeAt(i);
}
let blobInput = new Blob([uint8Array], {type: contentType});
try{
const clipboardItemInput = await new ClipboardItem({ 'image/png': blobInput });
console.log(blobInput)
await navigator.clipboard.write([clipboardItemInput]);
this.$message.success('图片已复制至剪切板')
}catch(e){
this.$message.error("该图片格式无法复制,请选择下载");
console.error(new Error('\n\n--------------------\n复制失败原因: \n- 该图片格式/类型无法复制至剪切板\n- 该图片链接有跨越设置,无法复制\n- 该图片体积过大\n--------------------\n\n( dddd )\n\n'))
}
},