标题
1.一键复制
本地测试是没有问题的,但更新到服务器的时候,却不生效
navigator.clipboard.writeText(val).then(() => {
this.$Message.success('复制成功')
})
经查找资料发现是浏览器禁用了非安全域的
navigator.clipboard
对象。
安全域包括本地访问与开启TLS安全认证的地址,如https
协议的地址、127.0.0.1
或localhost
。
所以要解决这个bug就是要做一个兼容写法,在安全域下使用 navigator.clipboard 提升效率,非安全域退回到 >document.execCommand('copy')
; 保证功能一直可用。
建议使用
textarea
保证了复制的文本格式
// 先给要复制的文本或者按钮加上点击事件后,并将要复制的值传过来
async copyValue(val) {
if (navigator.clipboard && window.isSecureContext) {
// navigator clipboard 向剪贴板写文本
this.$message.success('复制成功')
return navigator.clipboard.writeText(val)
} else {
// 创建text area
const textArea = document.createElement('textarea')
// 设置元素的样式属性
textArea.style.position = 'absolute';
textArea.style.top = '0';
textArea.style.right = '0';
textArea.value = val
// 使text area不在viewport,同时设置不可见
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
this.$message.success('复制成功')
return new Promise((res, rej) => {
// 执行复制命令并移除文本框
document.execCommand('copy') ? res() : rej()
textArea.remove()
})
}
},
但是很奇怪 当我复制的时候,
块1会消失
,具体原因不知道,但换了拼接到的div就好了。
块1 的样式设定如下
.eqp-title {
font-size: 1rem;
font-weight: 600;
color: #484848;
padding: 0.3rem 0.3rem 0.3rem 1.5rem;
height: 2.3rem;
line-height: 2.3rem;
top: 12px;
left: 0px;
z-index: 999;
}
解决方案如下:
右侧需要复制的最外层div 设定
class="equipment-list"
将新建的文本textArea
由拼接到body
改为拼接到equipment-list
document.body.appendChild(textArea)
—> document.getElementsByClassName('equipment-list')[0].appendChild(textArea)
注意:报错 document.getElementsByClassName(...).appendChild is not a function
,是因为当使用 getElementsByClassName() 获取元素时,其返回的是数组,而没有定位到某一具体对象,所以带下标即可
2.Ctrl+s 保存等键盘监听事件
我这里主要是实现 保存 功能
mounted() {
window.addEventListener('keydown', this.handleEvent)
},
beforeDestroy() {
window.removeEventListener('keydown', this.handleEvent) // 在页面销毁的时候记得解除
},
methods: {
async handleEvent(event) {
switch (event.keyCode) {
case 37:
console.log('ctrl + ←')
break
case 38:
console.log('ctrl + ↑')
break
case 39:
console.log('ctrl + →')
break
case 40:
console.log('ctrl + ↓')
break
case 67:
console.log('ctrl + c')
break
case 83:
console.log('ctrl + s')
event.preventDefault()
event.returnValue = false // 阻止直接保存网页
// eslint-disable-next-line no-prototype-builtins
if (event.ctrlKey && event.code === 'KeyS' && store.getters.forbidden.hasOwnProperty('ctrlS')) {
// 在这里写保存需要执行的逻辑
}
if (event.ctrlKey && event.code === 'KeyS') return false
break
case 86:
console.log('ctrl + v')
break
case 89:
console.log('ctrl + y')
if (event.ctrlKey && event.code === 'KeyY') {
this.$router.go(+1)
}
break
case 90:
if (this.$route.path === '登录成功重定向的路由,比如控制台:/dashboard') return // 防止退出项目
if (event.ctrlKey && event.code === 'KeyZ') {
this.$router.go(-1)
}
break
}
}
}
通过打印 知道自己已经有监听到
ctrl
事件 和s
事件,但ctrl
和s
同时 发生的时候,发现自己并没有监听执行内部的打印命令。当自己点 浏览器别的地方ctrl+s
的时候,就会监听执行。认为是ctrl+s
在monico editor
是不生效的,研究后发现monico editor
有自己的ctrl+s
事件监听方式:如下所示:
this.editorInstance.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
this.$emit("save", this.editorInstance.getValue());
});
父组件 就可以做相对应的 事件
<monaco-editor v-model.trim="validationRules" language="csharp" style="height: 700px" v-if="drawerFlag" @save="checkClick" />
3.每三个数字字符加一个逗号
利用过滤器,来将需要的数据每隔三个字符 加一个逗号。如下图所示:
实现方式:Vue2
<div class="card">
<div class="card-box">
<div class="title">产量</div>
<div class="num">{{ data.capacity | num }}</div>
</div>
<div class="card-box">
<div class="title">标准</div>
<div class="num">{{ data.standard | num }}</div>
</div>
<div class="card-box">
<div class="title">达成率</div>
<div class="num">{{ data.rate }}%</div>
</div>
</div>
filters: {
num: (val) => {
const value = val.toString().split("").reverse().join("");
//每个三位价格逗号
let temp = ""; // 临时变量
for (let i = 0; i < value.length; i++) {
temp += value[i];
if ((i + 1) % 3 == 0 && i != value.length - 1) {
temp += ","; // 每隔三个数字拼接一个逗号
}
}
temp = temp.split("").reverse().join("");
return temp; // 返回
},
},
注:边框背景及样式
background: rgba(14, 78, 164, 0.4);
box-shadow: inset 0px 0px 12px 0px rgba(36, 115, 239, 0.58);
4.前端集合搜索
computed: {
filterData() {
const keyWord = this.submitData.filterTable?.toUpperCase() || "";
const reg = new RegExp(keyWord);
const arr = [];
this.treeData.forEach((item) => {
if (reg.test(item)) {
arr.push(item);
}
});
return arr;
},
},
传参数的写法:
使用方式:filterData(111)
filterData() {
return function (key) {
const keyWord = this.submitData.filterTable[key]?.toUpperCase() || "";
const reg = new RegExp(keyWord);
const arr = [];
this.treeData[key].forEach((item) => {
if (reg.test(item)) {
arr.push(item);
}
});
return arr;
};
},
5.插入数据至光标处
- HTML
<Input
v-model="submitData.fieldFunction"
type="textarea"
ref="fieldFunction"
draggable
:autosize="{ minRows: 20, maxRows: 20 }"
style="margin-top: 10px"
></Input>
- JAVASCRIPT
// 调用
this.insertAtCursor(`${row}()`);
//插入数据至光标处
async insertAtCursor(myValue) {
const myField = this.$refs.fieldFunction.$el.children[0];
if (myField.selectionStart || myField.selectionStart === 0) {
let startPos = myField.selectionStart; //开始位置
let endPos = myField.selectionEnd; //结束位置
let selectionPos = endPos + myValue.length - 1; //光标选中位置(-1)
const fieldFunction = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length);
this.submitData = { ...this.submitData, fieldFunction };
await this.$nextTick(); // 这句是重点, 圈起来,不加的话后面两步有问题
myField.focus();
myField.setSelectionRange(selectionPos, selectionPos);
} else {
this.submitData = { ...this.submitData, fieldFunction: (this.submitData.fieldFunction += myValue) };
}
},
注:由于我需要调整光标位置至括号()内,所以selectionPos 有-1操作
6.指定顺序排序
const order = ["LCL", "UCL", "CL", "mean", "LSL", "USL"];
data.seriesDatas.sort((a, b) => {
return order.indexOf(a.name) - order.indexOf(b.name);
})
7.数组指定位置截取
data.slice(0, 4)
8.滚动条置顶
this.$nextTick(() => {
// 当滚动条从没有到有时,不加setTimeout滚动条将不会滚动到底部
setTimeout(() => {
let overflowY = this.$el.getElementsByClassName("timeline")[0];
if (!overflowY) {
return;
}
overflowY.scrollTop = 0;
//置底
// overflowY.scrollTop = overflowY.scrollHeight;
}, 1);
});
9.值位置整体切换-数值实现轮播类型转化
逻辑概述:点击0索引值,将0值切换到1索引,依次往后推,末尾值到首位
点击2索引值,将0值放到末尾,1值到首位,依次往前推
图片说明:
//改变线体
//index 当前点击的值索引,
changeStationData(index) {
//当点击当前的 不修改此值
if (index === 1) return;
let result = [];
//说明数据从后到前切换
if (index == 2) {
//第0个值到末尾,第一个值到第0个,第二个值到第一个
const [num1, ...num2] = this.stationData;
result = [...num2, num1];
} else {
//数据从前往后切换
//末位置到第一个,第一个值到第二个,第二个值到第三个
const [num1, ...num2] = this.stationData.reverse();
result = [num1, ...num2.reverse()];
}
this.stationData = [...result];
this.$forceUpdate();
},
10.搜索文本高亮
this.highlightSearch(["出站成功"]);
//查询字段高亮
highlightSearch(keyWords) {
let content = document.getElementsByClassName("content");
keyWords.forEach((keyWord) => {
for (let i = 0; i < content.length; i++) {
const item = content[i];
let regex = new RegExp("(" + keyWord + ")", "gi");
let highlightedContent = item.innerHTML.replace(regex, "<span class='highlight'>$1</span>");
item.innerHTML = highlightedContent;
}
});
},
#equipment-list .highlight {
background-color: #feff02;
color: #000;
}
- 参考的原始代码:
<!DOCTYPE html>
<html>
<head>
<style>
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<input type="text" id="searchInput" placeholder="搜索">
<div id="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac viverra diam. Integer ut justo nec massa aliquet fermentum.
</div>
<script>
function highlightSearch() {
var searchInput = document.getElementById("searchInput");
var content = document.getElementById("content");
var searchQuery = searchInput.value;
var regex = new RegExp("(" + searchQuery + ")", "gi");
var highlightedContent = content.innerHTML.replace(regex, "<span class='highlight'>$1</span>");
content.innerHTML = highlightedContent;
}
var searchInput = document.getElementById("searchInput");
searchInput.addEventListener("input", highlightSearch);
</script>
</body>
</html>
11. 根据数值的精度 加数值精度的0.01、0.001。。。。
//获取精度
getAccuracy(data) {
const decimal = data.toString().split(".")[1];
const decimalLength = decimal ? decimal.length : 0;
return 1 / Math.pow(10, decimalLength); //次方函数
},
12 所有key转大写
keysToUpperCase(obj) {
return Object.keys(obj).reduce((result, key) => {
result[key.toUpperCase()] = obj[key];
return result;
}, {});
},
13 对象数组List 按字母顺序排序
Object.keys(this.dataItemList).forEach((item) => {
if (this.sortDataItem) {
this.dataItemList[item].sort((a, b) => a.detailName.localeCompare(b.detailName));
} else {
this.dataItemList[item].sort((a, b) => b.detailName.localeCompare(a.detailName));
}
});
字符串和数字结合的List 按照数字排序
[{a:'Z01'},{a:'Z05'},{a:'Z03'}].sort((x,y)=>Number(x.a.replace(/\D/g, ''))-Number(y.a.replace(/\D/g, '')))