目录
概括
技术积累
node-sass
cnpm i
不然会报错
vue 过滤器
查看代码
filters: {
ellipsis(value) {
if (!value) return ''
if (value.length > 8) {
return value.slice(0, 8) + '...'
}
return value
}
}
2
3
4
5
6
7
8
9
在 3.x 中,过滤器已移除,且不再支持。取而代之的是,我们建议用方法调用或计算属性来替换它们。
主动触发 element 表单的检查
查看代码
this.$refs.ruleForm.validateField("content");
使用 vuepress 内置组件 codegroup
yarn
npm install
在 vue 中实现 p5 有点恶心心 1.使用 toDataURL 把 canvas 转换成 base64 图片地址 2.或者用 refs 把 canvas "appendChild"到 vue 组件中 3.组件中导入 p5,其中 p5 的方法都要加'p5.',否则会报错
查看代码
mounted() { this.$nextTick(()=>{ let judgeCanvasExist =
document.getElementById("defaultCanvas0") if(judgeCanvasExist===null) { new
P5(this.main); } }) }, methods: { main(_p5) { let p5 = _p5; let bubbles = [];
const window_width = window.innerWidth; const window_height =
window.innerHeight; p5.setup = () => { p5.createCanvas(window_width / 4,
window_height / 4); for (let i = 0; i < 100; i++) { let x = p5.random(p5.width);
let y = p5.random(p5.height); let r = p5.random(20, 60); let b = new Bubble(x,
y, r); bubbles.push(b); }; let
myCanvas=document.getElementById("defaultCanvas0"); let container =
this.$refs.box; container.appendChild(myCanvas) // let dataUrl =
myCanvas.toDataURL(); //base64 // this.canvasUrl = dataUrl; //
console.log(typeof myCanvas) // console.log(myCanvas.parentNode) // debugger //
myCanvas.parentNode.removeNode(myCanvas) } p5.mouseMoved = () => { for (let i =
bubbles.length - 1; i >= 0; i--) { if (bubbles[i].contains(p5.mouseX,
p5.mouseY)) { bubbles.splice(i, 1); } } } p5.draw = () => { p5.background(0);
for (let i = 0; i < bubbles.length; i++) { if (bubbles[i].contains(p5.mouseX,
p5.mouseY)) { bubbles[i].changeColor(255); } else { bubbles[i].changeColor(0); }
bubbles[i].move(); bubbles[i].show(); } } class Bubble { constructor(x, y, r) {
this.x = x; this.y = y; this.r = r; this.brightness = 0; } changeColor(bright) {
this.brightness = bright; } contains(px, py) { let d = p5.dist(px, py, this.x,
this.y); if (d < this.r) { return true; } else { return false; } } move() {
this.x = this.x + p5.random(-2, 2); this.y = this.y + p5.random(-2, 2); } show()
{ p5.stroke(255); p5.strokeWeight(4); p5.fill(this.brightness, 125);
p5.ellipse(this.x, this.y, this.r * 2); } } } }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
快速复制网页的 cookie
查看代码
copy(document.cookie);
//粘贴并应用
"复制的内容".split(";").map((c) => (document.cookie = c));
2
3
echarts 的图标监听 window 的大小重绘
查看代码
window.addEventListener("resize", () => {
this.chartLine.resize();
});
2
3
Uncaught Error: `resize` should not be called during main process.
获取浏览器 Cookie 的值
查看代码
const cookie = (name) =>
`;${document.cookie}`.split(`${name}=`).pop().split(";").shift();
//使用
//cookie('pgv_pvid');
2
3
4
将 rgb 转换成十六进制
查看代码
const rgbToHex = (r, g, b) =>
"#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
//1<<24===1*Math.pow(2,24)
//使用
//rgbToHex(0,51,255)
//toString(16)表示转换成16进制后再转换成字符串
2
3
4
5
6
复制到剪贴板
查看代码
const copyToClipboard = async (text) => navigator.clipboard.writeText(text);
//使用
//copyToClipboard('hello world')
//Clipboard API是下一代的剪贴板操作方法,比传统的document.exeCommand()方法更强大、更合理
//如果你把上面的代码,粘贴到开发者工具里面运行,就会报错。因为代码运行的时候,开发者工具窗口是当前页,这个页面不存在 Clipboard API 依赖的 DOM 接口。一个解决方法就是,相关代码放到setTimeout()里面延迟运行,在调用函数之前快速点击浏览器的页面窗口,将其变成当前页。
//参照https://www.ruanyifeng.com/blog/2021/01/clipboard-api.html
/*
setTimeout(async () => {
copyToClipboard('hello world')
}, 2000);
*/
2
3
4
5
6
7
8
9
10
11
数组去重
查看代码
(target) => {
let arr = target;
let res = [new Set(arr)];
return res;
};
2
3
4
5
深拷贝
查看代码
function deepClone(target) {
debugger;
let result;
if (typeof target === "object") {
if (Array.isArray(target)) {
result = [];
for (let i in target) {
result.push(deepClone(target[i]));
}
} else if (target === null) {
result = null;
} else if (target.constructor === RegExp) {
result = target;
} else {
result = {};
for (let i in target) {
result[i] = deepClone(target[i]);
}
}
} else {
result = target;
}
return result;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
使用 Map 深拷贝
查看代码
function deepCloneMethod(target) {
const map = new Map();
function isObject(val) {
return val != null && typeof val === "object";
}
function clone(target) {
if (isObject(target)) {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
cloneTarget[key] = clone(target[key]);
}
return cloneTarget;
} else {
return target;
}
}
return clone(target);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
判断字符串是否全为空
str.match(/^[ ]*$/);
判断对象是否为空
查看代码
//使用Object.keys()或者Object.getOwnPropertyNames()
const obj = {};
const arr = Object.keys(obj);
console.log(arr.length > 0);
//使用JSON.stringfy()
console.log(JSON.stringify(obj) !== "{}");
2
3
4
5
6
注意
Object.keys(), 它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。 Object.getOwnPropertyNames() 返回一个数组,该数组对元素是 obj 自身拥有的枚举或不可枚举属性名称字符串。
检查日期是否有效
查看代码
const isDateValid = (...val) => !Number.isNaN(new Date(...val).valueOf());
//使用
//isDateValid(new Date())
//true
//new Date()
//Thu Nov 18 2021 21:11:16 GMT+0800 (中国标准时间)
//格林威治的子午线向东偏移8小时
2
3
4
5
6
7
查找一年中的某一天
查看代码
const dayOfYear = (date) =>
Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
//dayOfYear(new Date())
//322
2
3
4
大写字符串
查看代码
const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
//使用
//capitalize('heiheiheiyohei')
2
3
create-vueopen in new window
npm init vue@next
给所有的 div 一个 outline 样式
查看代码
[].forEach.call($("div"), (a) => {
a.style.outline =
"5px solid #" + (~~(Math.random() * (1 << 24))).toString(16);
});
2
3
4
屏幕录制
查看代码
- index.js
let btn = document.querySelector(".record-btn");
btn.addEventListener("click", async function () {
let stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
});
const mine = MediaRecorder.isTypeSupported("video/webm;codecs=vp9")
? "video/webm;codecs=vp9"
: "video/webm";
let mediaRecoder = new MediaRecorder(stream, {
mimeType: mine,
});
let chunks = [];
mediaRecoder.addEventListener("dataavailable", function (e) {
chunks.push(e.data);
});
mediaRecoder.addEventListener("stop", function () {
let blob = new Blob(chunks, {
type: chunks[0].type,
});
let url = URL.createObjectURL(blob);
let video = document.querySelector(".video");
video.src = url;
let a = document.createElement("a");
a.href = url;
a.download = "video.webm";
a.click();
});
mediaRecoder.start();
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
html
<video width="600px" class="video" controls="controls"></video>
<button class="record-btn">开始录制</button>
2
代理页面解决跨域(子页面 iframe 访问父页面)
查看详情
父页面 server1/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
server1
<iframe src="http://127.0.0.1:5500/index.html"></iframe>
<script>
window.sessionStorage.setItem('item',1);
function doSomethin (){
console.log('server1');
console.log(window.sessionStorage.getItem('item'))
}
</script>
</body>
</html>
子页面 server2/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
serer2
<button onclick="doSome()">
跨域
</button>
<script>
function doSome(){
console.log(this)
if(!document.getElementById('crossFrmane')){
var iframe = document.createElement('iframe');
iframe.setAttribute('style','position:absolute;left:-199999px;top=-1929999px');
iframe.setAttribute('src','http://127.0.0.1:5501/iframe.html')
document.body.appendChild(iframe)
}else{
document.createElement('crossFrmane').src='http://127.0.0.1:5501/iframe.html'
}
}
</script>
</body>
</html>
代理页面 server1/iframe.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
window.onload=function(){
console.log(top.sessionStorage.getItem('item'))
}
</script>
</body>
</html>
记录
在公司二次开发 ueditor 的时候遇到了跨域, 情况是当时想把 ueditor 的静态文件传到 cdn 文件目录下 ,项目访问直接在 index.html 或者 webpack 里配置引用, 富文本可以正常显示,但是涉及到弹框的 js 文件会报跨域的错误, 问题出在了 cdn 上的弹框内部 js 访问或操作当前页面中 DOM 导致的跨域, 预想的解决方法:配置 config 中的 iframeUrlMap,同是把 dialog 的文件拷贝在到线上目录下
v8
如何执行 JavaScript
将源码 (进行词法分析和语法分析)转为 AST(抽象语法树),然后解释器将其转为字节码, 如果该字节码-是热点代码,则编译器直接将其转为机器码(并把机器码保存下来,以备下次使用), 若不是热点代码,则由解释器 解释执行字节码 ----------JIT
JIT 与 AOT
JIT (Just-In-Time)--即时编译 ,边编译边运行 AOT (ahead of time)运行前进行编译
局域网分享代码方案
npm install -g keppler
keppler "My awesome project"
生成器示例
function *foo(){
var x= yield 2;
z++;
var y = yield(x*z);
console.log(x,y,z);
}
var z=1;
var it1 = foo();
var it2 = foo();
var val1 =it1.next().value;
console.log(val1)
// 2
var val2 = it2.next().value;
console.log(val2)
// 2
var val3 = it1.next(val2*10).value;
console.log(val3);
// x=20,z=2;40
var val4 = it2.next(val3*5).value;
// 600
console.log(val4);
it1.next(val4/2).value;
// 20 300 3
it2.next(val4/2).value;
// 200 300 3
vue slot 常用
查看
- 父组件
<template v-slot:zt_add></template>
- 子组件
<slot name="zt_add">
</slot>
2
事件冒泡与事件捕获
代码详情
<template>
<div class="all-box">
<div class="event_bubble_capture" contenteditable="false">
<p>点击触发</p>
<h4>
addEventListener第三个参数默认为false,表示机制为事件冒泡,自下而上触发事件
</h4>
<div class="button-a" ref="button-a">
a
<div ref="button-b" class="button-b">b</div>
</div>
<p v-if="res1">输出为{{ res1.name }}</p>
<h4>
addEventListener第三个参数为true,表示机制为事件捕获,自上而下触发事件
</h4>
<div class="button-c" ref="button-c">
c
<div ref="button-d" class="button-d">d</div>
</div>
<p v-if="res2">输出为{{ res2.name }}</p>
</div>
<dialog_drag></dialog_drag>
</div>
</template>
<script>
import { reactive } from "vue";
import dialog_drag from "../advanced/dialog_drag";
export default {
setup() {
const res1 = reactive({ name: "" });
const res2 = reactive({ name: "" });
return {
res1,
res2,
};
},
components:{
dialog_drag
},
mounted() {
this.defineBubble();
this.defineCapture();
},
methods: {
defineBubble() {
let that = this;
let txt = "";
let targetA = this.$refs["button-a"];
targetA.addEventListener("click", function (e) {
e.preventDefault();
txt += "a";
that.res1.name = txt.split("").join("=>");
txt=''
});
let targetB = this.$refs["button-b"];
targetB.addEventListener("click", function (e) {
e.preventDefault();
txt += "b";
that.res1.name = txt.split("").join("=>");
});
},
defineCapture() {
let txt = "";
let that = this;
let targetA = this.$refs["button-c"];
targetA.addEventListener(
"click",
function (e) {
e.preventDefault();
if(txt) txt=''
txt += "c";
that.res2.name = txt.split("").join("=>");
},
true
);
let targetB = this.$refs["button-d"];
targetB.addEventListener(
"click",
function (e) {
e.preventDefault();
txt += "d";
that.res2.name = txt.split("").join("=>");
txt=''
},
true
);
},
},
};
</script>
<style scoped lang="scss">
@import "~element-plus/dist/index.css";
.all-box{
border: 2px solid;
border-color:#666666 #00ff00 #888888 #0d84ff;
padding: 20px;
border-radius: 10px;
&::after{
content: ' ';
display: block;
width: 60px;
height: 20px;
background-color: #8c939d;
transform: rotate(25deg) translate(-41%,181%);
}
&::before{
content: ' ';
display: block;
width: 60px;
height: 20px;
background-color: #8c939d;
transform: rotate(-25deg) translate(-50%,-181%);
}
}
.event_bubble_capture {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.button-a,
.button-c {
width: 100px;
height: 100px;
background-color: rgb(random(235), random(235), random(235));
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
font-size: 1.2em;
font-weight: 500;
cursor: pointer;
.button-b,
.button-d {
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
background-color: rgb(random(235), random(235), random(235));
}
.button-d {
background-color: rgb(random(235), random(235), random(235));
}
}
.button-c {
background-color: rgb(random(235), random(235), random(235));
}
}
vue3自定义指令
查看详情
<template>
<div class="dialog-box">
<el-input placeholder="placeholder" style="margin-top: 10vh;width: 20em" v-focus v-model="inputString"></el-input>
<el-tag type="success" v-heightLight="'10vh'">Tag 2</el-tag>
<h4>自由移动块(自由度高,且设置了z-index)</h4>
<div class="box" v-drag>
<el-button type="primary" class="control" @click="open">move me</el-button>
</div>
</div>
</template>
<script>
import {reactive, ref, h} from 'vue'
import {ElNotification} from 'element-plus'
export default ({
setup() {
const dialogVisible = reactive({value: false});
return {
dialogVisible,
inputString: ref('')
}
},
methods: {
handelClick() {
this.dialogVisible.value = true
},
open(){
ElNotification({
title: 'wow',
message: h('i', { style: 'color: teal'}, 'you clicked me'),
})
}
},
directives: {
focus: {
mounted(el) {
el.focus()
}
},
heightLight: {
beforeMount(el, binding, vNode) {
el.style.margin = binding.value;
},
},
drag: {
mounted(el) {
const dragDom = el.querySelector('.control');
dragDom.style.cursor = 'move';
dragDom.onmousedown = (e) => {
e.stopPropagation();
const disX = e.clientX- Number(el.style.left.replace('px',''));
const disY = e.clientY-Number(el.style.top.replace('px',''));
document.onmousemove = (e) => {//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX;
let top = e.clientY;
el.style.left = left - disX + 'px';
el.style.top = top - disY + 'px';
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
}
}
}
}
}
})
</script>
<style scoped>
.dialog-box {
}
.box {
width: 50px;
height:50px;
position: relative;
z-index: 9999;
}
.box .control {
width: 100px;
height: 20px;
}
</style>
- 上述事件...和自定义指令写在下面的组件中
数组对象平铺后遍历处理属性结构的数据(自理的树状对象的垃圾处理方法)
查看详情
const data = [
{
id:1,
children:[
{
id:2,
children: [
{
id:3
}
],
},
{
id:4,
children:[
{
id:5
},{
id:6
}
]
}
]
},{
id:7
},
{
id:8,
children: [
{
id:9,
children: [{
id:10
}]
}]
}
]
let filterData = []
const getFilterData = (treeData,callback)=>{
for(let i = 0;i<treeData.length;i++){
let item = {}
Object.defineProperty(item,`${treeData[i].id}`,{
enumerable:true,
configurable:true,
set(v) {
value = treeData[i].children
},
get() {
return treeData[i].children
}
})
filterData.push(item)
if(treeData[i].children){
getFilterData(treeData[i].children)
}
}
}
getFilterData(data);
console.log(filterData)
JS type coercion
1=='1'
// true
1==='1'
// false
if(1){
console.log(5)
}
// 5
if(0){
console.log(5)
}
//
-0 === +0
// true
Object.is(-0,+0)
// false
NaN === NaN
// false
object.is(NaN,NaN)
// true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
网页全屏/退出全屏
const doc = document;
const html = doc.documentElement;
const enter =
html.requestFullscreen ||
html.webkitRequestFullScreen ||
html.mozRequestFullScreen ||
html.msRequestFullscreen;
const exit =
doc.exitFullscreen ||
doc.webkitCancelFullScreen ||
doc.mozCancelFullScreen ||
doc.msExitFullscreen;
const enterFullScreen = () => {
enter && enter.call(html);
};
const exitFullScreen = () => {
exit && exit.call(doc);
};
export { enterFullScreen, exitFullScreen };
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25