杂记
不知不觉发现以前一个记录常用资源的 md 文件已经一万行了, 可能记了也是只有需要用的时候才会去翻阅, 今天把里面的内容进行分类, 改删一部分.
前端实现自动部署
代码部分
<!-- upload/index.js -->
const config = require("./config.js");
const shell = require("shelljs");
const path = require("path");
let Client = require("ssh2-sftp-client");
// 打包 npm run build
const compileDist = async () => {
if (shell.exec("npm run build").code == 0) {
console.log("打包成功");
}
};
/**
* 链接
*/
async function connectSSh() {
let sftp = new Client();
sftp
.connect({
host: config.ip, // 服务器 IP
port: config.port,
username: config.username,
password: config.password,
})
.then(() => {
console.log("先执行删除服务器文件");
return sftp.rmdir(config.rmpath, true);
})
.then(() => {
// 上传文件
console.log("开始上传");
return sftp.uploadDir(path.resolve(__dirname, "../.vitepress/dist"), config.path);
})
.then((data) => {
console.log("上传完成");
sftp.end();
})
.catch((err) => {
console.log(err, "失败");
sftp.end();
});
}
/**
* 运行脚本
*/
async function runTask() {
await compileDist(); // 打包完成
await connectSSh(); // 提交上传
}
runTask();
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!-- /upload/config.js -->
module.exports = {
ip: "12.93.17.23", // ssh地址
username: "root", // ssh 用户名
port: "22", // 端口
password: "878484", // ssh 密码
path: "/www/wwwroot/pre.demo.com", // 操作开始文件夹 可以直接指向配置好的地址
rmpath: "/www/wwwroot/pre.demo.com/", // 需要删除的文件夹
};
<!-- 静默执行, 创建 shangchuan.vbs -->
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c shangchuan.bat",vbhide
// 注意添加到定时任务的时候, 不要搞一些什么关键字当名称, 否则win10不执行
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
其余部分
- 在 package.json 中配置
"upload": "node upload/index.js"
- windows 下面添加定时任务, 自动执行脚本
需注意一定要写起始于, 选择脚本执行的位置
手机投屏软件 scrcpy
- 链接手机
- 打开开发者模式
- 允许 usb 调试
scrcpy -S 息屏投屏 scrcpy -m1080 设置大小 最终命令: scrcpy -m 800 --window-borderless --always-on-top --turn-screen-off --window-x 1550 --window-y 300
常用的快捷键
alt+h 首页 alt+o 息屏
看视频地址
网盘下载地址 https://www.rrdynb.com/
https://www.naifei6.com/play-141578-1-40.html
- 飞兔影视 https://www.feitu.tv/
- 一帆视频 https://www.iyf1.tv/
- 555 电影 https://www.o8tv.com/
- 星火直播 https://www.xhzb.tw/
- 胖子视频 https://www.pangzitv.com/
- 捷华影视 https://www.jiehua.tv/
- 优视频 https://www.uvod.tv/
- 独播库 https://www.duboku.tv/
- 唐人街影院 https://www.tangrenjie.tv/https://www.4khdr.cn/https://www.dyzj.cc/
电影先生: http://dyxs.mehttp://dyxs.de
好用的 gif 压缩工具
https://docsmall.com/gif-compress
png 压缩工具
工具网站
邮编 行政区划查询
接外包
https://zhuanlan.zhihu.com/p/499616877
前端实现在线 ppt
https://github.com/pipipi-pikachu/PPTist
不让刷新浏览器
window.onbeforeunload = (e) => {
if (this.modifyArr.length > 0) {
e.returnValue = "关闭提示";
return "关闭提示";
} else {
window.onbeforeunload = null;
}
};
2
3
4
5
6
7
8
css 选择不以什么开头
.gray > path:not([fill^='url('])
document.all
ie 最早支持, 后来其他浏览器都支持, 返回的是所有的 html 的数组, 但是使用 typeof 检测时, 返回 undefined
js 手动触发事件
- ie 模式
document.getElementById("clickMe").click();
- 其他浏览器
// 方法1
var e = document.createEvent("MouseEvents");
e.initEvent("click", true, true);
document.getElementById("clickMe").dispatchEvent(e);
// 方法2
let ev = new Event("mouseenter");
btn.dispatchEvent(ev);
2
3
4
5
6
7
8
fixed 元素的父元素加了 transform 就会以父元素为参考对象
去除 input 框 number 的默认样式和事件
<style>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: textfield;
}
input[type="number"] {
-moz-appearance: textfield;
}
</style>
<el-input type="number" @mousewheel.native.prevent />
2
3
4
5
6
7
8
9
10
11
12
无限轮播
实现思路: 通过切换类名, 给中间那个元素放大, 并且层级提升, 其余保持不变, 在第一个位置的时候移动到最后一个位置, 最后一个位置移动到中间 实现效果:
<div class="swiper_item front fl">
<div class="pic">
<img
@click="handleBigpicShow(pic && pic.leftPic)"
v-lazy="pic && pic.leftPic"
alt=""
/>
<div class="text">
<span class="pic_icon"></span>
{{ insetDiscrenData.pic && insetDiscrenData.pic.createDate }}
</div>
</div>
</div>
<div class="swiper_item active fl">
<div class="pic">
<img
@click="handleBigpicShow(pic && pic.wormImage)"
v-lazy="pic && pic.wormImage"
alt=""
/>
<div class="text">
<span class="pic_icon"></span>
{{ insetDiscrenData.pic && insetDiscrenData.pic.createDate }}
</div>
</div>
</div>
<div class="swiper_item back fr">
<div class="pic">
<img
@click="handleBigpicShow(pic && pic.rightPic)"
v-lazy="pic && pic.rightPic"
alt=""
/>
<div class="text">
<span class="pic_icon"></span>
{{ insetDiscrenData.pic && insetDiscrenData.pic.createDate }}
</div>
</div>
</div>
<script>
// 点击的时候切换类名实现
let front = document.querySelector('.front') // 第一个
let back = document.querySelector('.back') // 最后一个
let active = document.querySelector('.swiper_item.active') // 中间展示
if (val === 'pre') {
// 上一页
front.className = 'swiper_item back'
back.className = 'swiper_item active'
active.className = 'swiper_item front'
} else {
// 下一页
front.className = 'swiper_item active'
back.className = 'swiper_item front'
active.className = 'swiper_item back'
}
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
上下轮播
实现思路: 将该元素复制为两份, 放在一块, 然后移动外面那个盒子的 scrollTop 来实现滚动轮播, 当第一个滚动完, 再把整个盒子的 scrollTop 设置为 0
<div
v-if="
equipmentListData.wormEquiList &&
equipmentListData.wormEquiList.length > 0
"
id="table_main"
class="table_main"
>
<div
@mouseenter="controlScroll(0)"
@mouseleave="controlScroll(1)"
id="table_con"
class="con"
>
<div
@click="handleSelectRow(index, item)"
:class="{ active: currentIndex === index }"
v-for="(item, index) in equipmentListData.wormEquiList"
:key="index"
class="item"
>
<span
:title="item[tableItemKey[ind]]"
class="text-overflow-line"
v-for="(it, ind) in tableItemKey"
:key="ind"
>
{{ item[tableItemKey[ind]] }}
</span>
</div>
</div>
<div
id="table_con1"
@mouseenter="controlScroll(0)"
@mouseleave="controlScroll(1)"
class="con"
v-if="
equipmentListData.wormEquiList &&
equipmentListData.wormEquiList.length > 3
"
>
<div
@click="handleSelectRow(index, item)"
:class="{ active: currentIndex === index }"
v-for="(item, index) in equipmentListData.wormEquiList"
:key="index"
class="item"
>
<span
:title="item[tableItemKey[ind]]"
class="text-overflow-line"
v-for="(it, ind) in tableItemKey"
:key="ind"
>
{{ item[tableItemKey[ind]] }}
</span>
</div>
</div>
</div>
<script>
// 触发
this.timer = setInterval(() => {
this.scrollInfinite(father, con, con1);
}, 50)
scrollInfinite(father, con, con1) {
if (!father) {
return;
}
father.scrollTop += 1;
if (father.scrollTop > con.offsetHeight) {
/**第二次到达顶部的时候将scrolltop设置为0 */
father.scrollTop = 0;
}
}
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
git 提交代码规范
feat: 新功能
fix: 修复bug
docs: 文档改变
style: 代码格式改变
refactor: 某个功能重构
perf: 性能优化
test: 增加测试
build: 构建工具改变
revert: 撤销上次commit
chore: 开发环境配置改变
2
3
4
5
6
7
8
9
10
解决 vuerouter 跳转重复页面报错
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err)
}
2
3
4
地图资源整理
- 地图取点返回 json
- 获取中国地图的坐标经纬度
http://datav.aliyun.com/tools/atlas/#&lat=33.8339199536547&lng=98.6572265625&zoom=4
- echarts 平面地图资源整理
vue 动态引入外部 js script
<template>
<div id="baseReport">
<remote-css
href="https://cdn.bootcss.com/twitter-bootstrap/4.2.1/css/bootstrap-grid.min.css"
>
</remote-css>
<remote-css
href="https://cdn.bootcss.com/twitter-bootstrap/4.2.1/css/bootstrap-reboot.css"
></remote-css>
<remote-css
href="https://cdn.bootcss.com/twitter-bootstrap/4.2.1/css/bootstrap.css"
></remote-css>
<remote-js
src="https://cdn.bootcss.com/twitter-bootstrap/4.2.1/js/bootstrap.bundle.js"
></remote-js>
<remote-js
src="https://cdn.bootcss.com/twitter-bootstrap/4.2.1/js/bootstrap.js"
></remote-js>
<div class="card-group">
<div class="card">这里是内容</div>
<div class="card">这里是内容</div>
<div class="card">这里是内容</div>
</div>
</div>
</template>
<script>
export default {
components: {
"remote-css": {
render(createElement) {
return createElement("link", {
attrs: {
rel: "stylesheet",
href: this.href,
},
});
},
props: {
href: {
type: String,
required: true,
},
},
},
"remote-js": {
render(createElement) {
return createElement("script", {
attrs: {
type: "text/javascript",
src: this.src,
},
});
},
props: {
src: {
type: String,
required: true,
},
},
},
},
//jsx语法示例
// components: {
// 'remote-js': {
// render(h) {
// return (
// <script type= 'text/javascript' src={this.cdn}></script>
// )
// },
// props: {
// cdn: {
// type: String,
// required: true
// }
// }
// },
// 'remote-css': {
// render(h) {
// return (
// <link rel='stylesheet' type='text/css' href={this.cdn} />
// )
// },
// props: {
// cdn: {
// type: String,
// required: true
// }
// }
// }
// }
};
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
文字渐变
.gradient-text-one {
background-image: -webkit-linear-gradient(bottom, red, #fd8403, yellow);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
// 具有兼容性问题 ie下面直接不行
/* 来源地址:https://www.php.cn/css-tutorial-408797.html */
2
3
4
5
6
7
8
js 根据父元素, 删除元素
first.parentNode.removeChild(first);
代码高亮以及在 html 中展示代码
<div class="code">
<pre>
<code class="html">
<!-- Unstyled gauge (All defaults) -->
<div id="gauge0" class="gauge-container"></div>
</code>
<code class="javascript">
var gauge0 = Gauge(document.getElementById("gauge0"));
</code>
</pre>
</div>
2
3
4
5
6
7
8
9
10
11
引入 /工具/代码高亮中的 js
vue 封装自增数字指令
directives: {
countRunning(el, binding, vnode, oldVnode) {
var options = {
time: 2000,
initNum: parseInt(0),
num: el.getAttribute("data-target"),
regulator: 50
};
if (options.initNum == options.num) return;
var time = options.time, //总时间--毫秒为单位
finalNum = options.num, //要显示的真实数值
regulator = options.regulator || 100, //调速器,改变regulator的数值可以调节数字改变的速度
step = (finalNum - options.initNum) / (time / regulator),
/*每30ms增加的数值--*/
count = options.initNum, //计数器
initial = options.initNum;
var timer = setInterval(() => {
count = count + step;
if (count >= finalNum && options.initNum < finalNum) {
clearInterval(timer);
count = finalNum;
}
if (count <= finalNum && options.initNum > finalNum) {
clearInterval(timer);
count = finalNum;
}
//t未发生改变的话就直接返回
var t = Math.floor(count);
if (t == initial) return;
initial = t;
el.innerHTML = initial;
}, 30);
}
},
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
30
31
32
33
34
highcharts 更新数据
this.$refs.hcharts.charts.series[0].update({
data
})
2
3
隐藏滚动条
::-webkit-scrollbar {
/*滚动条整体样式*/
width: 0.02rem;
/*高宽分别对应横竖滚动条的尺寸*/
height: 0.06rem;
background-color: rgba(0, 0, 0, 0);
}
scrollbar {
/*滚动条整体样式*/
width: 0.02rem;
/*高宽分别对应横竖滚动条的尺寸*/
height: 0.06rem;
background-color: rgba(0, 0, 0, 0);
}
::-ms-scrollbar {
/*滚动条整体样式*/
width: 0.02rem;
/*高宽分别对应横竖滚动条的尺寸*/
height: 0.06rem;
background-color: rgba(0, 0, 0, 0);
}
::-webkit-scrollbar-thumb {
/*滚动条里面小方块*/
border-radius: 0.04rem;
-webkit-box-shadow: inset 0 0.05rem rgba(0, 0, 0, 0.2);
background: rgba(0, 0, 0, 0);
}
::-webkit-scrollbar-track {
/*滚动条里面轨道*/
background: rgba(0, 0, 0, 0);
border-radius: 0.04rem;
}
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
30
31
32
33
34
35
36
适配 echarts 中的字体大小
// 计算文字大小 rem 转px
function changeFontSize(fontsize) {
return (fontsize * window.innerWidth) / 1920
}
2
3
4
图片适配, 在所有屏幕下面不变形的处理方案
img {
max-height: 0.2rem;
max-width: 0.2rem;
height: auto;
width: auto;
}
2
3
4
5
6
判断手机
const mobile =
navigator.userAgent.match(/Android/i) ||
navigator.userAgent.match(/webOS/i) ||
navigator.userAgent.match(/iPhone/i) ||
navigator.userAgent.match(/BlackBerry/i) ||
navigator.userAgent.match(/Windows Phone/i)
2
3
4
5
6
普通 html 中模块化导入导出
<body>
<script type="module">
import { ceshi } from './index.js'
ceshi()
</script>
</body>
2
3
4
5
6
iview 弹出窗, 点击其余部分隐藏, 点击外部隐藏, clickout
更简单的使用:
Day.js 使用
使用方法
- 安装:
npm install dayjs
- 引入:
var dayjs = require('dayjs')
//import dayjs from 'dayjs' // ES 2015
dayjs().format()
2
3
- 获取当前时间
var now = dayjs()
- 解析 ISO 8601
dayjs('2018-04-04T16:00:00.000Z')
可以只传递 ISO 时间 - 解析
dayjs("12-25-1995", "MM-DD-YYYY")
- 常用的占位符对照表
YY | 18 | 两位数的年份 |
---|---|---|
YYYY | 2018 | 四位数的年份 |
M | 1-12 | 月份,从 1 开始 |
MM | 01-12 | 月份,两位数 |
MMM | Jan-Dec | 缩写的月份名称 |
MMMM | January-December | 完整的月份名称 |
D | 1-31 | 月份里的一天 |
DD | 01-31 | 月份里的一天,两位数 |
H | 0-23 | 小时 |
HH | 00-23 | 小时,两位数 |
h | 1-12 | 小时, 12 小时制 |
hh | 01-12 | 小时, 12 小时制, 两位数 |
m | 0-59 | 分钟 |
mm | 00-59 | 分钟,两位数 |
s | 0-59 | 秒 |
ss | 00-59 | 秒 两位数 |
S | 0-9 | 毫秒,一位数 |
SS | 00-99 | 毫秒,两位数 |
SSS | 000-999 | 毫秒,三位数 |
Z | -05:00 | UTC 的偏移量 |
ZZ | -0500 | UTC 的偏移量,两位数 |
A | AM PM | 上午 下午 大写 |
a | am pm | 上午 下午 小写 |
Do | 1st... 31st | 带序数词的月份里的一天 |
- 传递时间戳
dayjs(1318781876406)
- 传递日期对象
var d = new Date(2018, 8, 18)
var day = dayjs(d)
2
- 检验日期对象是否是有效的时间
dayjs().isValid()
- 获取和设置时间
dayjs().hour() // 不传递值表示获取
dayjs().hour(12) // 传递表示设置
2
常用学习网站
常用的学习网站 1、@IT 楠老师
网站:www.itnanls.cn 2、@峰华前端工程师
网站:https://zxuqian.cn 3、@CodeSheep
网站:https://www.codesheep.cn 4、@朱安邦-Web 前端程序员
网站:www.axihe.com
01. 大学资源网 http://www.dxzy163.com/
02. 中国大学 MOOC https://www.icourse163.org/
03. 一课堂 http://www.1ketang.com/
04. b站
05. 网易公开课(学公开课就可以了)
06. 1纳米学习 http://www.1nami.com/
国外学习课堂
01. Edx https://www.edx.org/
02. 可汗学院 https://www.khanacademy.org/
03. Coursera https://www.coursera.org/
04. 译学馆 https://www.yxgapp.com/
05. 慕课网
06. 田间小站 https://www.tianfateng.cn/
07. 每日听力
08. 泸江英语 https://www.hjenglish.com/
09. 站酷高高手 (摄影)
10. Oeasy 会玩才会学 (计算机 )
11 考试酷 https://www.examcoo.com/
12. 回答库 https://www.asklib.com
13. 万千集合站
14. iData 期刊文件专业学术资料
15. 鸠摩搜书 读书类
16. 音乐而聚
17手工客 (手工)
18. wikiHow 生活技巧类
19. MUSCLEWIKI 健身
20. 医药微视
效果网 特效网
https://www.jq22.com/http://www.htmleaf.com/ jquery 之家 https://www.dowebok.com/ 常用的 js 库 https://www.miaoroom.com/resource/code/ued/ued-plugin.html 很实用 https://techbrood.com/ 能编辑代码的
vue 中 input 自动获取焦点指令封装
directives: {
focus: {
// 指令的定义
inserted: function(el) {
el.focus();
}
}
},
// 使用
v-focus
2
3
4
5
6
7
8
9
10
11
最全前端资料
https://www.miaoroom.com/resource/code/code-notes/ued-learningpath.html
跨域处理
https://www.miaoroom.com/resource/code/ued/cross-domain.html
全屏滚动
https://www.jq22.com/yanshi1124
markdown 文件编辑器
https://pandao.github.io/editor.md/
移动端开发总结
https://www.miaoroom.com/resource/code/ued/vue-mobile-dev.html
瀑布流插件
http://www.htmleaf.com/jQuery/pubuliuchajian/201506021952.html
滚动条美化
http://www.htmleaf.com/jQuery/Layout-Interface/201606143599.html
两个变量互换
[nums[p], nums[i]] = [nums[i], nums[p]
通过 css 来监测浏览器是否在全屏
@media (device-width: 100vw) and (device-height: 100vh) {
/* 全屏下 */
html {
background-color: #f00;
}
}
2
3
4
5
6
通过 js 来监测浏览器是否在全屏
body.is-fullscreen.content {
padding...
例如:
}
// 监测全屏改变, 然后切换类名, 通过该类名去写相应的css样式
document.addEventListener('fullscreenchange', function() {
document.body.classList.toggle('is-fullscreen', document.fullscreenEnabled);
});
2
3
4
5
6
7
8
抠图
字体下载 免费字体
https://www.zitijia.com/t/免费商用
PDF 工具
每日热榜
蜘蛛压缩字体 字体优化
使用方法:
- npm install font-spider -g
@font-face {
font-family: 'pinghei';
src: url('./font/苹方特粗体.ttf');
font-weight: normal;
font-style: normal;
}
div {
font-family: 'pinghei';
}
2
3
4
5
6
7
8
9
10
font-spider ./test.html
将常用的 3500 个中文字存储起来, 然后通过蜘蛛来进行提取
图片上传压缩
tinypng.comhttps://shrinkme.app/ 图片压缩网站
https://github.com/think2011/localResizeIMG
第一种方法不行, 跨域, 没找到合理的解决方案, 试过了网上的解决方案都不行
<script src="./dist/lrz.bundle.js"></script>
// <input id="file" type="file" accept="image/*" />
lrz('https://gitee.com/zhangdailin/img/raw/master/img/20201111114111.png')
.then(function (rst) {
console.log('rst', rst)
// 处理成功会执行
})
.catch(function (err) {
console.log('err', err)
// 处理失败会执行
})
.always(function () {
// 不管是成功失败,都会执行
})
document.querySelector('#file').addEventListener('change', function () {
lrz(this.files[0])
.then(function (rst) {
// 处理成功会执行
console.log(rst)
let img = new Image()
img.src = rst.base64
img.onload = function () {
window.document.body.appendChild(img)
}
})
.catch(function (err) {
// 处理失败会执行
})
.always(function () {
// 不管是成功失败,都会执行
})
})
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
30
31
32
滚动到可视区域
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView 在 ie8, 以上有效, 可以让元素滚动到可视区域, ie 不支持传递参数 div.scrollIntoView({block: "end", behavior: "smooth"})
// 平滑滚动到指定位置
JS 控制文本框禁止输入特殊字符大全
https://www.jianshu.com/p/2940e0f7e9ae 实现思路, 监听输入或者粘贴事件, 然后进行正则匹配, 替换掉不合理的符号
图片下载
// 下载图片
downPhoto(path) {
this.downloadFiles(path)
},
// 下载
downloadFiles(content) {
console.log(content)
const downloadElement = document.createElement('a') // 创建下载的链接
let blob = this.base64ToBlob(content) // new Blob([content]);
const href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = '参保人相片.jpg' // 下载后的文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 下载
document.body.removeChild(downloadElement) // 下载完成 移除 a
window.URL.revokeObjectURL(href) // 释放blob对象
},
// base64转blob
base64ToBlob(code) {
let parts = code.split(';base64,')
let contentType = parts[0].split(':')[1]
let raw = window.atob(parts[1])
let rawLength = raw.length
let uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], {
type: contentType
})
},
// <button class="cancel-btn cursor" @click="downPhoto(dataDetail.photo64Byte)">下载图片</button>
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
30
31
32
33
sort 不传参数是比较的 ascall 码
如果要比较一个数组大小需要传递参数 .sort((a, b) => a-b)
html5 拖拽上传文件时,屏蔽浏览器默认打开文件
/**
* 页面禁用拖拽上传时 浏览器默认打开图片
*/
document.addEventListener(
'drop',
function (e) {
e.preventDefault()
},
false
)
document.addEventListener(
'dragover',
function (e) {
e.preventDefault()
},
false
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
移动端实现 1px 边框
https://www.jianshu.com/p/261ba7b17919https://blog.csdn.net/userkang/article/details/84338547
移动端粘黏吸顶效果的解决方案
ios 中 在 web 页面滚动时,不触发和执行 js 实现方式: 安卓和 ios 单独处理, ios 通过 position: sticky 进行粘性布局
//Android
.tab-box-fixed {
position: fixed;
z-index: 5;
}
//iOS
.tab-box-sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
left: 0;
z-index: 5;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
滚动条样式修改
作者:公众号-人生代码 链接:https: //zhuanlan.zhihu.com/p/144204013
scrollbar-arrow-color: red;
/*上下按钮上三角箭头的颜色*/
scrollbar-face-color: #CBCBCB;
/*滚动条凸出部分的颜色*/
scrollbar-3dlight-color: blue;
/*滚动条亮边的颜色*/
scrollbar-highlight-color: #333;
/*滚动条空白部分的颜色*/
scrollbar-shadow-color: yellow;
/*滚动条阴影的颜色*/
scrollbar-darkshadow-color: green;
/*滚动条强阴影的颜色*/
scrollbar-track-color: #eee;
/*滚动条背景颜色*/
scrollbar-base-color: black;
/*滚动条的基本颜色*/
Cursor: url(mouse.cur);
/*自定义个性鼠标*/
/*以上2项适用与:body、div、textarea、iframe*/
}
::-webkit-scrollbar {
/* 滚动条整体部分 */
width: 10px;
margin-right: 2px
}
::-webkit-scrollbar-button {
/* 滚动条两端的按钮 */
width: 10px;
background-color: yellow;
}
::-webkit-scrollbar:horizontal {
height: 10px;
margin-bottom: 2px
}
::-webkit-scrollbar-track {
/* 外层轨道 */
border-radius: 10px;
}
::-webkit-scrollbar-track-piece {
/*内层轨道,滚动条中间部分 */
background-color: #333333;
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
/* 滑块 */
width: 10px;
border-radius: 5px;
background: #CBCBCB;
}
::-webkit-scrollbar-corner {
/* 边角 */
width: 10px;
background-color: red;
}
::-webkit-scrollbar-thumb:hover {
/* 鼠标移入滑块 */
background: #909090;
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
gif 工具网站
阻止事件的 css 写法
pointer-events: none;
not 选择器的使用
//简洁写法
li:not(:last-child) {
border-right: 2px solid #d2d5e4;
}
//关于not的其他写法
li:not(.a) //not中放入其他选择器, 选中除了a标签以外的所有li
ui:hover li:not(:hover) {
opacity: 0.5;
}
2
3
4
5
6
7
8
9
10
11
js-cookie 使用
https://github.com/js-cookie/js-cookie
import Cookies from 'js-cookie'
Cookies.set('foo', 'bar')
Cookies.set('name', 'value', {
expires: 7
}) // 设置天数
Cookies.remove('name')
2
3
4
5
6
7
8
9
vue 自增组件
之前写过, 但是有一些问题
cnpm i vue-count-to - S
import CountTo from 'vue-count-to'
<count-to :start-val "0" :end-val "102400" :duration="2600" class="card-panel-num" / >
2
3
4
5
封装的 requestAnimationFrame 用于替代原生的 requestAnimationFrame
let lastTime = 0
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
let requestAnimationFrame
let cancelAnimationFrame
const isServer = typeof window === 'undefined'
if (isServer) {
requestAnimationFrame = function () {
return
}
cancelAnimationFrame = function () {
return
}
} else {
requestAnimationFrame = window.requestAnimationFrame
cancelAnimationFrame = window.cancelAnimationFrame
let prefix
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
for (let i = 0; i < prefixes.length; i++) {
if (requestAnimationFrame && cancelAnimationFrame) {
break
}
prefix = prefixes[i]
requestAnimationFrame =
requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
cancelAnimationFrame =
cancelAnimationFrame ||
window[prefix + 'CancelAnimationFrame'] ||
window[prefix + 'CancelRequestAnimationFrame']
}
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
if (!requestAnimationFrame || !cancelAnimationFrame) {
requestAnimationFrame = function (callback) {
const currTime = new Date().getTime()
// 为了使setTimteout的尽可能的接近每秒60帧的效果
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
const id = window.setTimeout(() => {
callback(currTime + timeToCall)
}, timeToCall)
lastTime = currTime + timeToCall
return id
}
cancelAnimationFrame = function (id) {
window.clearTimeout(id)
}
}
}
export { requestAnimationFrame, cancelAnimationFrame }
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
- 使用方法:
和原生的一样, 通过传入一个函数, 在该函数里面如果再次满足条件的时候再次执行 this.rAF = requestAnimationFrame(this.count)
函数体内
if (progress < this.localDuration) {
// 如果满足条件将会一直调用
this.rAF = requestAnimationFrame(this.count)
} else {
this.$emit('callback')
}
2
3
4
5
6
解决 vue 首屏加载太慢, 白屏时间太长
通过在 app 里面写入一个 loading 的动画, 不让页面白屏, 即使白屏也展示那个 loading 页面
但是中途网速慢的情况也会出现一会白屏, 最佳实践: 在 app 底部添加该 loading 元素, 然后设置对应的层级为 -1, 当 app 中有内容的时候就会把原有的 loading 图顶掉
<div id="app"></div>
<div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
<!-- loading样式自己写 -->
2
3
4
5
6
7
8
prefetch 和 preload 的区别
- preload 是告诉浏览器页面必定需要的资源,浏览器一定会加载这些资源;
- prefetch 是告诉浏览器页面可能需要的资源,浏览器不一定会加载这些资源。
在 vue 项目中 preload 用于加载 app.js 和 chunk-vendors.js, 对于路由懒加载通过 prefetch 进行加载
主动清除浏览器的缓存
升级了 js 文件,很多页面都引用了这个文件,需要主动清除浏览器缓存才会生效,有没有什么办法可以不主动清除就可以?
修改文件名,加上版本号,或 xxx.js?v=0.101
js 脚本加载顺序
从上到下依次加载如果遇到 pretch 会在页面空闲的时候加载, 对于 preload 的一定会在页面渲染完加载完毕
目前感觉最稳定的 cdn
移动端弹框 返回关闭弹框
/**只用于弹窗返回的时候直接跳转到上一个页面, 只需引入即可, 但弹窗名称必须和规定的一致 */
export default {
beforeRouteLeave(to, from, next) {
let index = this.popBackShowArr.indexOf(true);
index !== -1 ? (this.popBackShowArr = [], next(false)) : next();
},
data() {
return {
// popBackShowArr: [false, true], // 控制/弹窗
}
},
}
// 用法
computed: {
popBackShowArr: {
get: function() {
return [this.searBoxShow, this.isBox];
},
set: function(newValue) {
this.isBox = false;
this.searBoxShow = false;
this.serchKey = "";
},
},
},
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
配置 iview 和 element-ui 按需导入
babel.config.js
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [
[
'import',
{
libraryName: 'view-design',
libraryDirectory: 'src/components'
}
],
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
element 需要安装 cnpm install babel-plugin-component -D
微信支付流程
创建订单
- 先获取用户登录成功后的 token 值 -- 调用后端接口 前四个参数通过 button 的 open-type 中获取, 最后一个通过 wx.login 获取,跳转页面,点击按钮获取想要信息
调用获取用户信息按钮, 拿到前四个参数
调用登录接口获取信息
封装优化回调 优化后的代码 完整步骤 调用后台接口拿到订单编号
预支付 接口
返回数据
调用微信内支付,上面的数据用于这一步的参数
发起微信支付 返回支付成功或者失败
查询订单 调用接口,看看后台是否真的成功了,跳转到订单页面
微信复制
/**
* 复制
*/
copyText(e) {
wx.setClipboardData({
data: e.currentTarget.dataset.text,
success(res) {
console.log("success -> res", res)
}
})
},
2
3
4
5
6
7
8
9
10
11
返回上一页面并传参
// 直接调用它返回即可
_returnToPreviousPage() {
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];
if (prevPage) {
prevPage.setData({
isRresh: true
})
}
},
2
3
4
5
6
7
8
9
10
多行文本换行
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
2
3
4
5
前端规范
阿里 http://alloyteam.github.io/CodeGuide/ 百度 https://github.com/ecomfe/spec
vw vh 的扩展
- vMax vw 和 vh 中的较大的那个
- vMin vw 和 vh 中的较小的那个
vue 项目进入的时候没用动画
https://animista.net/play/entrances/slit-in 动画用它 vue 中添加动画, vue 动画
- 需要添加 appear,
- enter-active-class 表示进入的时候的效果
- leave-active-class 表示离开的时候的效果
注意千万要加 apper, 不然进入的时候会没有效果
<transition
enter-active-class="slide-in-bck-center"
duration="500"
appear
leave-active-class="flip-out-hor-top "
>
<div class="ceshi" v-if="show">dsjgiosd</div>
</transition>
2
3
4
5
6
7
8
大屏常用组件
vscode 插件编写
https://www.jianshu.com/p/e642856f6044
axios 多个前缀处理
终止端口号
- 查询
netstat -ano|findstr "9097"
- 终止
taskkill -F -PID 6832
echarts 饼状图 没有数据隐藏 label
data.echartsOptions.series[0].label = {
normal: {
position: 'inner',
formatter: (val) => {
let showStr = ''
showStr = val.value > 0 ? val.name : ''
return showStr
}
}
}
2
3
4
5
6
7
8
9
10
vue 图片懒加载
cnpm install vue-lazyload --save-dev
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
2
3
4
5
6
- 使用
<img v-lazy="'/static/img/' + item.productImage">
媒体查询
- 常用方式
@media screen and (min-width: 600px) and (max-width: 900px) {
body {
background-color: #f5f5f5;
}
}
2
3
4
5
- 通过不同的屏幕加载不同的样式
<link
rel="stylesheet"
media="screen and (max-device-width:480px)"
href="iphone.css"
/>
2
3
4
5
github 高级搜索
in:name React stars:>5000 forks:>3000
- 按照项目名/仓库名搜索(大小写不敏感)
in:name xxx
- 按照 README 搜索(大小写不敏感)
in:readme xxx
- 按照 description 搜索(大小写不敏感)
in:description xxx
- stars 数大于 xxx
stars:>xxx
- forks 数大于 xxx
forks:>xxx
- 编程语言为 xxx
language:xxx
- 最新更新时间晚于 YYYY-MM-DD
pushed:>YYYY-MM-DD
正则表达式在线调试模式
使用谷歌浏览器预览 markdown 文件
关于 element 弹窗中嵌套弹窗出现问题
// 在内部弹窗中使用属性 append-to-body
解决 element 表格不能对齐
.el-table th.gutter {
display: table-cell !important;
}
2
3
pdf 转 word pdf 工具
https://www.ilovepdf.com/zh-cn
Git 频繁提示输入账号密码
当我们操作 git pull/push 到远程的时候,总是提示我们输入账号和密码才能操作成功,频繁的输入账号和密码会很麻烦。
解决办法: git bash cd 进入你的项目目录,输入:
git config --global credential.helper store 然后再进行一次 git pull/push 一次代码,再输入一次账号和密码,就大工告成了
解决 element ui table 分页切换 页面打勾不丢失, 分页点击后, 选中数据丢失
<el-table :row-key="rowKey">
<el-table-column type="selection" :reserve-selection="true"></el-table-column>
</el-table>
2
3
methods: {
rowKey(row) {
return row.id
}
}
2
3
4
5
windows 10 常用快捷键
Win 键+I:打开 Windows 10 设置 Win 键+L:锁定屏幕 Win 键+P:投影屏幕 Win 键+X:打开高级用户功能 Win 键+1/2/3:打开任务栏中固定的程序,1 代表任务栏中第一个应用图标 Win 键+ shift +1/2/3 打开新的图标下的应用
keep-alive 缓存详情 控制是否加载数据
Vue 通过 keep-alive 缓存 Tab 页面
https://blog.csdn.net/qq_35459724/article/details/117220073
打字的时候看看自己输入的引文字符这样可以减少输入错误
手机 cpu 显卡排行榜
好用的工具 实用软件
音频合并
bat 使用什么打开应用 bat 的基础使用
对于中间有空格的使用引号包裹 第一个表示打开的应用 第二个地址表示要打开的应用 保存的使用要保存为 anis 的格式, 不能 utf-8
start C:\Users\Administrator\AppData\Local\Programs\"Microsoft VS Code"\Code.exe D:\项目
儿时游戏 经典
vconsole 快速使用, 移动端 console v-console 移动端打印
<script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
<script>
var vConsole = new window.VConsole()
</script>
2
3
4
h5 唤起 app
<script src="./scripts/callapp.js"></script>
<script>
function callApp(type) {
const options = {
scheme: {
protocol: 'shanghezhaopu://'
},
intent: {
package: 'com.somhe.zhaopu',
scheme: 'shanghezhaopu'
},
//apple store
appstore: 'https://apps.apple.com/cn/app/id1541586310',
//应用宝
yinyongbao: 'https://a.app.qq.com/o/simple.jsp?pkgname=com.somhe.zhaopu',
fallback: 'https://a.app.qq.com/o/simple.jsp?pkgname=com.somhe.zhaopu' //唤端失败后跳转的地址
}
const callLib = new CallApp(options)
callLib.open({})
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
调用 ios 方法
// postMessage里面必须传递参数, 而且还是json的不然ios那边接受不了
window.webkit.messageHandlers.close.postMessage(
JSON.stringify({
ceshi: ''
})
)
2
3
4
5
6
post 测试地址 postman 在线地址 测试接口
解决 flex 布局导致最后一个元素位置错乱问题
https://www.zhangxinxu.com/wordpress/2019/08/css-flex-last-align/
简单处理方案
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list {
background-color: skyblue;
margin: 10px;
}
/* 最后一项margin-right:auto */
.list:last-child {
margin-right: auto;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
通过伪元素
.container {
display: flex;
justify - content: space - between;
flex - wrap: wrap;
}
.list {
background - color: skyblue;
margin: 10 px;
}
/* 使用伪元素辅助左对齐 */
.container::after {
content: '';
flex: auto; /* 或者flex: 1 */
}
2
3
4
5
6
7
8
9
10
11
12
13
14
给盒子一个伪元素解决
&::after {
content: '';
flex: auto;
/* 或者flex: 1 */
}
2
3
4
5
frp 内网穿透
https://www.tenlonstudio.com/7639.html
内网穿透工具 - 路由侠
http://www.luyouxia.com/#package
分享, h5 分享, 朋友圈分享
https://github.com/fa-ge/NativeShare
前端学习路线
https://objtube.github.io/front-end-roadmap/#/
tree 转为数组
function flatten(data) {
return data.reduce(
(arr, { Id, Name, Pid, id, children = [] }) =>
arr.concat(
[
{
Id,
Name,
Pid,
id
}
],
flatten(children)
),
[]
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
抠图 背景图
element ui 验证滚动到第一个验证失败的位置
//在js方法中校验
this.$refs['form'].validate((valid) => {
if (valid) {
// 验证通过
} else {
this.$nextTick(() => {
let isError = document.getElementsByClassName('is-error')
isError[0].scrollIntoView({
// 滚动到指定节点
// 值有start,center,end,nearest,当前显示在视图区域中间
block: 'center',
// 值有auto、instant,smooth,缓动动画(当前是慢速的)
behavior: 'smooth'
})
})
return
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
点击外部不关闭 element 弹窗
import ElementUI from‘ element - ui’
ElementUI.Dialog.props.closeOnClickModal.default = false
2
微信分享图片不出问题排错
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#66
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
佛跳墙下载地址
https://github.com/getfotiaoqiang/download/
产品比价性能比价, 电子产品 耳机比较
https://versus.com/cn/categories
添加到 gitignore 仍然提交成功
git rm -r --cached src/views/test/index.vue
indexDB 数据存储
var data = [
{
id: 1,
name: 'Tom',
age: '18'
},
{
id: 2,
name: 'Tommy',
age: '16'
}
]
// 打开数据库,两个参数(数据库名字,版本号),如果数据库不存在则创建一个新的库
var request = window.indexedDB.open('myDatabase', '1')
// 数据库操作过程中出错,则错误回调被触发
request.onerror = (event) => {
console.log(event)
}
// 数据库操作一切正常,所有操作后触发
request.onsuccess = (event) => {
var db = event.target.result
// 数据读取
var usersObjectStore = db.transaction('users').objectStore('users')
var userRequest = usersObjectStore.get(1)
userRequest.onsuccess = function (event) {
console.log(event.target.result)
}
}
// 创建一个新的数据库或者修改数据库版本号时触发
request.onupgradeneeded = (event) => {
var db = event.target.result
// 创建对象仓库用来存储数据,把id作为keyPath,keyPath必须保证不重复,相当于数据库的主键
var objectStore = db.createObjectStore('users', {
keyPath: 'id'
})
// 建立索引,name和age可能重复,因此unique设置为false
objectStore.createIndex('name', 'name', {
unique: false
})
objectStore.createIndex('age', 'age', {
unique: false
})
// 确保在插入数据前对象仓库已经建立
objectStore.transaction.oncomplete = () => {
// 将数据保存到数据仓库
var usersObjectStore = db
.transaction('users', 'readwrite')
.objectStore('users')
data.forEach((data) => {
usersObjectStore.add(data)
})
}
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
vscode 正则匹配
// -----------------ceshi start[\s\S]*\n[\s\S]*end---------------------------$
正则匹配删除 log
console.log.+\)
爱奇艺 腾讯视频下载
破解版视频 https://www.luochenzhimu.com/videovip
https://www.bavei.com/? 全名解 可以下载破解视频
ts 忽略单行
// @ts-ignore
pingyin 拼音 转拼音
https://github.com/zh-lx/pinyin-pro 可以辨别多音字
vue3 资源
vuex 持久化 本地化
cpm install vuex - persistedstate - S
// 在store中引入
import createPersistedState from 'vuex-persistedstate'
// 注册使用
getters,
plugins: [createPersistedState()]
2
3
4
5
6
7
前端利用 jsencrypt.js 进行 RSA 加密
npm install jsencrypt
import JSEncrypt from 'jsencrypt'
var encryptor = new JSEncrypt() // 创建加密对象实例
//之前ssl生成的公钥,复制的时候要小心不要有空格
var pubKey = '-----BEGIGSIb3DQEBQIDAQAB-----END PUBLIC KEY-----'
encryptor.setPublicKey(pubKey) //设置公钥
var rsaPassWord = encryptor.encrypt('要加密的内容') // 对内容进行加密
var decrypt = new JSEncrypt() //创建解密对象实例
//之前ssl生成的秘钥
var priKey = '-----BEGIN RSA PRIVATrVv6kGqhEN+Q0blT/ueRk=-----END RSA PRIVATE KEY----'
decrypt.setPrivateKey(priKey) //设置秘钥
var uncrypted = decrypt.decrypt(encrypted) //解密之前拿公钥加密的内容
2
3
4
5
6
7
8
9
10
11
12
13
14
15
前端控制台展开对象和折叠对象不一样
前端电子书
https://www.dazhuanlan.com/eriliu/topics/1274909
抓包工具
https://segmentfault.com/a/1190000038422757
charles 下载 http://www.3h3.com/soft/156807.html
正则非贪婪模式匹配
+?,??,*?,{n}?,{n, }?,{n, m}?
https://dailc.github.io/2017/07/06/regularExpressionGreedyAndLazy.html
excel 转 json
https://www.bejson.com/json/col2json/
psp 游戏资源
https://www.oldmanemu.net/掌机游戏/psp/psp官方游戏全集 通过 psp 模拟器, 模拟器在坚果云, 天翼云种有
svg sprite svg 精灵图 实践使用
- 将 ui 制作的 svg 放到一个文件夹里面
- 准备 vscode 插件 SVG Sprite Viewer And Generator
- 生成精灵图
- 预览精灵图
在项目中安装 webpack 的 svg 插件 svg-sprite-loader
代码中使用
- 封装相应的 base-icon 组件
<!-- 基础图标, svg使用 -->
<div
@click="$emit('click')"
class="base-icon"
:style="{ cursor: pointer ? 'pointer' : 'default' }"
>
<svg
:width="width || (map[id] ? map[id].width : 20)"
:height="height || (map[id] ? map[id].height : '20')"
>
<use
:width="width || (map[id] ? map[id].width : 20)"
:height="height || (map[id] ? map[id].height : '20')"
:xlink:href="'#_sprite_' + id"
/>
</svg>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 最终使用
<base-icon id="excel" width="20" height="20"></base-icon>
ssh 上传文件到服务器 scp 上传文件
scp -i ~/.ssh/id_rsa -r ./dist/. root@42.173.17.21:/www/wwwroot/jslin.cn/
ssh -i ~/.ssh/id_rsa root@42.13.17.21
微信分享, 微信分享不出图片问题
var localUrl = encodeURIComponent(window.location.href)
// 获取分享所需参数
function wxShare({ title, content, adImgUrl, digest }) {
$.ajax({
type: 'get',
url: '//somhe.hmzcjt.com/shtip/mp/getJSApiTicket?url=' + localUrl,
contentType: 'application/json;charset=utf-8',
success: function (data) {
if (data.code == 200) {
// 调用微信分享功能
weChatShare({
appId: data.data.appid,
timestamp: data.data.timestamp,
nonceStr: data.data.nonceStr,
signature: data.data.signature,
title,
adImgUrl,
digest
})
}
}
})
}
// 微信分享功能
function weChatShare({
appId,
timestamp,
nonceStr,
adImgUrl,
signature,
title,
digest,
content
}) {
// 调用分享接口拿到需要字段
wx.config({
debug: false,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
// jsApiList: ["onMenuShareAppMessage", "onMenuShareTimeline"],
jsApiList: [
'onMenuShareAppMessage',
'onMenuShareTimeline',
'onMenuShareQQ',
'onMenuShareQZone'
]
})
wx.ready(function () {
var myUrl = window.location.href.split('#')[0]
var imgUrl = $('img')[0].src
var shareData = {
title: title,
link: myUrl,
imgUrl: adImgUrl,
type: 'link',
desc: digest,
success: function () {},
cancel: function () {}
}
//分享到朋友圈
wx.onMenuShareTimeline(shareData)
//分享给朋友
wx.onMenuShareAppMessage(shareData)
// 1.4.0 新接口 (只调用这个接口在安卓下是无效的)
wx.updateAppMessageShareData(shareData)
wx.updateTimelineShareData(shareData)
})
wx.error(function (res) {})
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
css 点击出现元素, 移开元素隐藏调试时, 要找到对应的事件, 然后打断点, 这样元素就不会消失
SM2 加密遇到的问题
由于和我们这边的后端配合起来贼不顺畅, 导致了半天时间再排 bug, 还是只怪我不会 java;
相关网站
注意问题
前端对于生成的公钥要加个 '04' 才能正常加密;
注意前端加密需要一对秘钥, 后端加密前端解密又需要一对秘钥, 所以一共需要两对.
后端 java 返回的具有密文含有 04, 要手动去干掉, 不然解密出来会是空字符串(它不报错是最恶心的), 最初也不知道后端手动加了个 04.或者后端轻描淡写的说了一句, 当时忙得压根就没注意.
另外如果用 vue 开发的时候, 改了代码一定要刷新, 不要热更新完就去操作, 不然会出现意想不到的问题.
vitepress 主题
https://github.com/Tyh2001/vitepress-template
网站: https://tianyuhao.cn/blog/docs/hello/hello.html
在线压缩混淆工具
https://www.lddgo.net/encrypt/js
git 自动化上传 自动部署
shell.exec("cd .. && git pull && git add . && git commit -m '自动提交' && git push")
Vue 导入 ElementUI 时报错:Module build failed: Error: No PostCSS Config found in:
module.exports = {
plugins: {
'autoprefixer': {browsers: 'last 5 version'}
}
};
2
3
4
5
6
注意:不是在你写的项目根目录下创建,而是在 node_modules 下上述根目录里创建.
转载于 https://blog.csdn.net/weixin_44791976/article/details/110916982
看博客一定要看评论
以后养成习惯了, 看博客时一定要看评论, 因为这里面的都是和你遇到同样问题的人.
买会员网站 视频会员 可靠性不知
公租房申请地址
https://auth.cq.gov.cn:81/sso/login?utype=0&redirect=istrue
资源网站
资源网站
TV 资源
将平时不敢发朋友圈的记录到小红书上吧
https://creator.xiaohongshu.com/creator/home
max-width 不生效
处理方法
display:block;
max-width:200px;
2
小红书发布网址
https://creator.xiaohongshu.com/publish/imgNote
gitee 提交代码 403
打开凭据管理器, 修改即可
import 无法延迟引入
通过 require 的方式
bios 设置定时开机
定时开机, 可以通过 bios 里面设置自启
测试号申请流程
测试号申请地址 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
内网部署微信测试号方式 https://blog.csdn.net/qq_34096082/article/details/79985141
微信公众平台测试号管理接口配置信息配置失败问题解决方案 https://blog.csdn.net/weixin_42475367/article/details/108217155
微信请求我们服务器, 需要给他返回他传递过来的 echostr https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
测试号申请流程重点注意:
- 需要 80 端口或者 443 端口
公众号内网映射 穿透 内网穿透
入门指南
https://natapp.cn/article/natapp_newbie
- 下载安装 natapp
- 购买免费版
- 本地开启服务, 比如开启 8080 端口, 然后在隧道修改中, 改为 8080 端口
- 在 natapp 安装目录下面, 新建一个 config.ini 文件, 写入 authtoken
双击 natapp.exe
把映射出来的地址填入微信公众号后台
- 点击保存,
微信将发送请求过来验证
- 按照要求给出响应就可以配置成功
其余内网穿透工具
无弹窗自动执行 cmd 命令
通过 .vbs 文件, 如果要用 win+r 中启动的话需要创建快捷方式, 不然貌似运行不成功
公众号没有 80 端口访问
思路:
- 保证手机和电脑在同一个网络, 修改电脑上面的 host, 比如 '127.0.0.1 cn.big.com', 当访问到 big.com 的时候, 会访问到电脑的本地的 80 端口,
- 然后通过 nginx 进行代理到其他端口 https://blog.csdn.net/qq_40196738/article/details/105188543
还是得处理通过域名访问到指定服务器的问题
手机调试
spy-debugger
https://blog.csdn.net/ran0926/article/details/104697696
手机输入法
蓝牙键盘连入的话, 推荐使用讯飞输入法, 使用比较流畅
sort 排序
arr.sort((a,b)=>{
return a.id > b.id
// 返回值是大于0的, 将是正序
// 如果是小于0, 倒序
// 等于0 不动
})
2
3
4
5
6
定时启动任务
win + X 打开定时任务
操作这里要注意两个都要修改, 第二个表示位置
博客自定义域名
需要注意一下几点
GIT pull 失败 : 'unable to unlink file: invalid argument'
文件被占用了, 全部删除再操作
js css 下载时出现 206 状态码的错误
原因: nginx 只下载了一部分文件
解决方案: 修改 nginx 配置如下
https://blog.csdn.net/huangbaokang/article/details/106318415
更改的是 default.conf 的配置
https://my.oschina.net/langgege/blog/1926010
ie 下面去除滚动条
* {
-ms-overflow-style: none;
}
2
3
ie, 火狐处理方案 https://www.cnblogs.com/qing1224/p/16650170.html
edge 下面的 ie 打开调试模式 打开控制台
%systemroot%\system32\f12\IEChooser.exe
公积金转移
https://new.qq.com/rain/a/20211120A064ZN00
公积金贷款条件
6 个月 50w 夫妻 100w 川渝互认互贷 在方阵金保网代缴公积金
前端的学习方法
https://www.zhihu.com/question/55058833
钉钉小程序授权登录
获取 cropid https://blog.csdn.net/louting249/article/details/108355553
锁屏启动
ios 锁屏启动
搜索
- 表示去除
+ 表示强制包含
"" 表示精确查找
2
3
https://blog.csdn.net/weixin_39825045/article/details/111390565
浏览器修改高级设置
https://www.howtoip.com/how-to-change-hidden-advanced-settings-in-any-browser/
ie 触摸屏幕下面, 滚动滚动条会导致页面滚动问题
修炼自制力
https://www.zhihu.com/question/19888447
关于 git 提示“warning: LF will be replaced by CRLF”终极解答
git config --global core.autocrlf false
ie 下面预览 pdf, pdfjs-dist 的使用
https://blog.csdn.net/qq_42221321/article/details/121995567
默认是传递 src 的, 传递一个 url 就可以了, 不要搞成对象
代码看查询机系统的 test 文件, 只需要 pdfjs-dist 就可以了
过程中找到的资源
https://github.com/coreprocess/pdfjs-dist-viewer-min-es5
build/minified-es5/web/viewer.html
axios 获取 Http 响应头
https://blog.csdn.net/buzhao1624/article/details/103871829
前端新技术
- Vue I18n 是 Vue.js 的国际化插件,如果你想做开源框架,国际化首选插件。
- ViteSSG,SEO 优化
- Vitest, 基于 Vite 的单元测试工具
浏览器缓存 缓存处理
https://blog.csdn.net/q1ngqingsky/article/details/119671083
批量复制选中的相册的脚本 照片
const fs = require('fs')
let dir = fs.readdirSync('./')
let goodPic = [
'DSC00013',
'DSC00017',
'DSC00019',
'DSC00023',
'DSC00025',
'DSC00026',
'DSC00031',
'DSC00036',
'DSC00037',
'DSC00038',
'DSC00040',
'DSC00044',
'DSC00043',
'DSC00045',
'DSC00048',
'DSC00054',
'DSC00060',
'DSC00063',
'DSC00065',
'DSC00066',
'DSC00072',
'DSC00082',
'DSC00088',
'DSC00093',
'DSC00100',
'DSC00112'
]
let goodPicList = goodPic
let newList = dir.map((item) => {
return item.split('.')[0]
})
let lastArr = []
goodPicList.forEach((item) => {
if (newList.includes(item)) {
lastArr.push(item)
copy('./' + item + '.ARW', './dist/' + item + '.ARW')
}
})
function copy(src, dst) {
fs.writeFileSync(dst, fs.readFileSync(src))
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
快速修改代码后生效的工具, http-server 的替代品 lite-server, 可以实时刷新
npm install -g lite-server
lite-server
Failed to mount component: template or render function not defined
引入的时候, 默认是引入的是 js, 然后再其他的文件, 所以确保要引入的文件的类型
nginx 下载安装
https://nginx.org/en/download.html
nginx.conf 修改监听端口
win10 开启 ftp 服务
https://blog.csdn.net/qq_34610293/article/details/79210539
https://www.cnblogs.com/ziyu-trip/p/7844162.html
获取轻轨站相近的轻轨站
<!-- 测试地址
https://developer.amap.com/demo/jsapi-v2/example/bus-search/plan-route-according-to-name -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="initial-scale=1.0, user-scalable=no, width=device-width"
/>
<title>地点关键字 + 公交路线规划</title>
<style type="text/css">
html,
body,
#container {
width: 100%;
height: 100%;
}
</style>
<style type="text/css">
#panel {
position: fixed;
background-color: white;
max-height: 90%;
overflow-y: auto;
top: 10px;
right: 10px;
width: 280px;
}
#panel .amap-call {
background-color: #009cf9;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
#panel .amap-lib-transfer {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
overflow: hidden;
}
</style>
<link
rel="stylesheet"
href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css"
/>
<script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
<script
type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=您申请的key值&plugin=AMap.Transfer"
></script>
<script
type="text/javascript"
src="https://cache.amap.com/lbs/static/addToolbar.js"
></script>
</head>
<body>
<div id="container"></div>
<div id="panel"></div>
<script type="text/javascript">
var map = new AMap.Map('container', {
resizeEnable: true,
center: [106.51478, 29.6227],
zoom: 13
})
var transOptions = {
map: map,
city: '重庆市',
panel: 'panel',
policy: AMap.TransferPolicy.LEAST_TIME //乘车策略
}
//构造公交换乘类
var transfer = new AMap.Transfer(transOptions)
var conformObj = {}
//根据起、终点名称查询公交换乘路线
var addArr = ['轨道圣泉寺站']
addArr.forEach((item, index) => {
transfer.search(
[
{
keyword: item,
city: '重庆'
},
//第一个元素city缺省时取transOptions的city属性
{
keyword: '轨道幸福广场',
city: '重庆'
}
//第二个元素city缺省时取transOptions的cityd属性
],
function (status, result) {
// result即是对应的公交路线数据信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_TransferResult
// console.log(JSON.stringify(result));
var time = (result.plans[0].time / 60).toFixed(2)
if (time < 40) {
conformObj[item] = time + '分钟'
}
if (index == addArr.length - 1) {
console.log(JSON.stringify(conformObj))
}
if (status === 'complete') {
log.success('绘制公交路线完成')
} else {
log.error('公交路线数据查询失败' + result)
}
}
)
})
setTimeout(() => {
console.log(JSON.stringify(conformObj))
}, 20000)
</script>
</body>
</html>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
{
"轨道两路口站": "16.53分钟",
"轨道小龙坎站": "34.15分钟",
"轨道曾家岩站": "29.93分钟",
"轨道黄泥磅站": "25.10分钟",
"轨道李子坝站": "28.35分钟",
"轨道沙坪坝站": "33.63分钟",
"轨道牛角沱站": "26.32分钟",
"轨道佛图关站": "27.92分钟",
"轨道工贸站": "24.78分钟",
"轨道大坪站": "26.53分钟",
"轨道嘉州路站": "19.93分钟",
"轨道铜元局站": "23.18分钟",
"轨道华新街站": "20.40分钟",
"轨道动物园站": "26.80分钟",
"轨道龙头寺站": "26.65分钟",
"轨道狮子坪站": "16.57分钟",
"轨道郑家院子站": "20.67分钟",
"轨道朝天门站": "11.78分钟",
"轨道园博园站": "36.30分钟",
"轨道南坪站": "25.22分钟",
"轨道湖霞街站": "36.22分钟",
"轨道重光站": "36.80分钟",
"轨道和睦路站": "32.58分钟",
"轨道五里店站": "15.58分钟",
"轨道大石坝站": "25.28分钟",
"轨道观音桥站": "16.42分钟",
"轨道重庆北站南广场站": "16.05分钟",
"轨道民安大道站": "31.08分钟",
"轨道唐家院子站": "20.08分钟",
"轨道红旗河沟站": "11.55分钟",
"轨道人和站": "28.18分钟",
"轨道小什字站": "4.40分钟",
"轨道冉家坝站": "25.10分钟",
"轨道九曲河站": "27.63分钟",
"轨道红土地站": "12.20分钟"
}
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
30
31
32
33
34
35
36
37
38
公网 ip 棒 小魔棒
- 找到小魔棒的 ip, 18 端口, 账号为 root, 密码为手机号码
ftp 内网穿透搭建
使用的 wing ftp 来搭建服务, 中途遇到穿透到外网无法访问问题, 通过以下教程解决, 思路是固定一个端口, 使用被动模式, 写入能够访问的外网地址
https://blog.csdn.net/cr898839618/article/details/115391782
https://jingyan.baidu.com/article/e75aca853f56bc142edac6ef.html
后端配置跨域失败的处理方案
https://blog.csdn.net/envon123/article/details/83270277?
vite 内网穿透后一直刷新
修改 node_modules 中的 vite/dist/client/client.mjs/ 中的 const socket = new WebSocket 为当前访问的; 并且还要去修改 vite.config.js 中
server: {
port: 5000,
disableHostCheck: true
}
2
3
4
以上方法都没效果, 直接去把上面所示的代码里面的 socket 全部注释掉就可以了
反向代理和正向代理解释
正向代理: fan 樯可以理解为正向代理, 中间服务器代理了客户端去访问目标服务器, 隐藏了真正的客户端
反向代理: 用于负载均匀, 中间服务器代理了目标服务器和客户端打交道, 然后分发到其他服务器上面, 隐藏了真正的目标服务器
https://cloud.tencent.com/developer/article/1418457
vue 的 mounted 周期拿不到路由参数
this.$router.onReady(() => {
// 需要等路由加载完毕
}
2
3
m3u8 下载
https://www.bigtspace.com/archives/7948.html
下载地址 https://github.com/nilaoda/N_m3u8DL-CLI/releases
vue 打包传参
// 需要安装依赖
devDependencies: {
"cross-env": "^7.0.3",
}
// package.json中的配置
"build:dev": "cross-env NODE_ENV=dev vue-cli-service build",
2
3
4
5
6
7
王者荣耀开启高帧率模式
- 淘宝花了 40 开启 然后 magisk, 里面有一个模块 小米 12Sultra「HuaZoffice」(http://jslin.cn/小米12Sultra「HuaZoffice」.zip)
https://magisk.suchenqaq.club/MagiskModule/Model.php
删除文件却删除不了
git 日志导出
git log --pretty=format:"%ai , %an: %s" --since=5day --author=958112850@qq.com --encoding=GBK >> D:/jianguoyun/我的坚果云/1work/work/git.log
复制
npm i vue-clipboard2
import Vue from 'vue'
import VueClipboard from 'vue-clipboard2'
VueClipboard.config.autoSetContainer = true // add this line
Vue.use(VueClipboard)
2
3
4
5
6
7
8
<el-input type="text" v-model="message">
<el-button type="button"
v-clipboard:copy="message" //message 要复制的内容
v-clipboard:success="onCopy" //复制成功的回调
v-clipboard:error="onError">Copy! //复制失败的回调
</el-button>
<script>
new Vue({
el: '#app',
template: '#t',
data: function () {
return {
message: 'Copy These Text'
}
},
methods: {
onCopy: function (e) {
alert('You just copied: ' + e.text)
},
onError: function (e) {
alert('Failed to copy texts')
}
}
})
</script>
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
阿里云盘吧
数字转金额 千分
(234234).toLocaleString()
vscode 配置 EditorConfig for VS Code
https://www.cnblogs.com/jiaoshou/p/11252055.html
在目录下面鼠标右键, 生成
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = crlf # lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
2
3
4
5
6
7
8
9
10
vue3 搭建项目
https://juejin.cn/post/7156957907890733063
vitepress 添加搜索功能
记录一下 vitepress 添加搜索功能过程中踩的坑, 踩过, 但感觉没有实际意义, 分享出来后来人可以避坑.
主要思路: 使用的 vitepress-plugin-search, 没有使用另外一个, 貌似要联网还要注册杂七杂八感觉麻烦.
vite.config.js 文件这么配置, vite.config.js 要和文档放在一块, 要是文档都在 docs 中, 就要吧 vite.config.js 放到 docs 里面, 具体多试试嘛, 以实际情况为准.
//vite.config.js
import { SearchPlugin } from 'vitepress-plugin-search'
import { defineConfig } from 'vite'
export default defineConfig({
base: './',
server: {
port: 3000,
hmr: false,
disableHostCheck: true
},
plugins: [
SearchPlugin({
encode: false,
tokenize: 'full' // 解决汉字不能多个输入
})
]
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
网上都说是按照上面这样配置, 但配置了不生效.
创建一个 Search 的组件, 直接去把它源码里面的 search.vue 文件拷贝出来了, 当然要配套拷出来.
我把他搞出来了, 然后放到 theme 里面, 最后在一个全局的 silder 组件中引用, 这样所有的页面都能生效. 最后我把这个组件展示搜索框的位置隐藏了, 通过 ctrl + k 来触发, 这样一般人就不知道怎么使用我的搜索功能拉.
博客模板代码: http://jslin.cn/vite.config-2023-02-17-17-04-46.zip
拖拽封装
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
.container {
width: 400px;
margin: 0 auto;
background: pink;
padding: 20px;
}
.list {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.list-item {
width: 100px;
height: 100px;
border: 1px solid #000;
background: #fff;
line-height: 100px;
text-align: center;
list-style: none;
user-select: none;
}
.active {
background: skyblue;
}
.clone-item {
position: fixed;
left: 0;
top: 0;
z-index: 1;
width: 100px;
height: 100px;
border: 1px solid #000;
background: #fff;
line-height: 100px;
text-align: center;
list-style: none;
user-select: none;
pointer-events: none;
opacity: 0.8;
}
</style>
</head>
<body>
<div class="container">
<ul class="list">
<li class="list-item">111</li>
<li class="list-item">222</li>
<li class="list-item">333</li>
<li class="list-item">444</li>
<li class="list-item">555</li>
<li class="list-item">666</li>
<li class="list-item">777</li>
<li class="list-item">888</li>
<li class="list-item">999</li>
</ul>
</div>
<script>
class Draggable {
containerElement = null
rectList = []
isPointerDown = false
drag = {
element: null,
index: 0,
firstIndex: 0
}
clone = {
element: null,
x: 0,
y: 0
}
diff = {
x: 0,
y: 0
}
referenceElement = null
lastPointerMove = {
x: 0,
y: 0
}
constructor(options) {
this.containerElement = options.element
this.init()
}
init() {
// 拿到所有子元素的位置
this.getRectList()
this.bindEventListener()
}
getRectList() {
this.rectList.length = 0
for (const item of this.containerElement.children) {
this.rectList.push(item.getBoundingClientRect())
}
}
onPointerDown(e) {
if (e.pointerType === 'mouse' && e.button !== 0) {
return
}
if (e.target === this.containerElement) {
return
}
this.isPointerDown = true
this.containerElement.setPointerCapture(e.pointerId)
this.lastPointerMove.x = e.clientX
this.lastPointerMove.y = e.clientY
this.drag.element = e.target
this.drag.element.classList.add('active')
const index = [].indexOf.call(
this.containerElement.children,
this.drag.element
)
this.drag.index = index
this.drag.firstIndex = index
this.clone.x = this.rectList[index].left
this.clone.y = this.rectList[index].top
this.clone.element = this.drag.element.cloneNode(true)
document.body.appendChild(this.clone.element)
this.clone.element.style.transition = 'none'
this.clone.element.className = 'clone-item'
this.clone.element.style.transform =
'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)'
for (const item of this.containerElement.children) {
item.style.transition = 'transform 500ms'
}
}
onPointerMove(e) {
if (this.isPointerDown) {
this.diff.x = e.clientX - this.lastPointerMove.x
this.diff.y = e.clientY - this.lastPointerMove.y
this.lastPointerMove.x = e.clientX
this.lastPointerMove.y = e.clientY
this.clone.x += this.diff.x
this.clone.y += this.diff.y
this.clone.element.style.transform =
'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)'
for (let i = 0; i < this.rectList.length; i++) {
if (
i !== this.drag.index &&
e.clientX > this.rectList[i].left &&
e.clientX < this.rectList[i].right &&
e.clientY > this.rectList[i].top &&
e.clientY < this.rectList[i].bottom
) {
if (this.drag.index < i) {
for (let j = this.drag.index; j < i; j++) {
if (j < this.drag.firstIndex) {
this.containerElement.children[j].style.transform =
'translate3d(0px, 0px, 0)'
} else {
const x =
this.rectList[j].left - this.rectList[j + 1].left
const y = this.rectList[j].top - this.rectList[j + 1].top
this.containerElement.children[j + 1].style.transform =
'translate3d(' + x + 'px, ' + y + 'px, 0)'
}
}
this.referenceElement = this.containerElement.children[i + 1]
} else if (this.drag.index > i) {
for (let j = i; j < this.drag.index; j++) {
if (this.drag.firstIndex <= j) {
this.containerElement.children[j + 1].style.transform =
'translate3d(0px, 0px, 0)'
} else {
const x =
this.rectList[j + 1].left - this.rectList[j].left
const y = this.rectList[j + 1].top - this.rectList[j].top
this.containerElement.children[j].style.transform =
'translate3d(' + x + 'px, ' + y + 'px, 0)'
}
}
this.referenceElement = this.containerElement.children[i]
}
const x =
this.rectList[i].left -
this.rectList[this.drag.firstIndex].left
const y =
this.rectList[i].top - this.rectList[this.drag.firstIndex].top
this.drag.element.style.transform =
'translate3d(' + x + 'px, ' + y + 'px, 0)'
this.drag.index = i
break
}
}
}
}
onPointerUp(e) {
if (this.isPointerDown) {
this.isPointerDown = false
this.drag.element.classList.remove('active')
this.clone.element.remove()
for (const item of this.containerElement.children) {
item.style.transition = 'none'
item.style.transform = 'translate3d(0px, 0px, 0px)'
}
if (this.referenceElement !== null) {
this.containerElement.insertBefore(
this.drag.element,
this.referenceElement
)
}
}
}
bindEventListener() {
this.containerElement.addEventListener(
'pointerdown',
this.onPointerDown.bind(this)
)
this.containerElement.addEventListener(
'pointermove',
this.onPointerMove.bind(this)
)
this.containerElement.addEventListener(
'pointerup',
this.onPointerUp.bind(this)
)
window.addEventListener('scroll', this.getRectList.bind(this))
window.addEventListener('resize', this.getRectList.bind(this))
window.addEventListener(
'orientationchange',
this.getRectList.bind(this)
)
}
}
new Draggable({
element: document.querySelector('.list')
})
</script>
</body>
</html>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
ipbox 使用
http://www.ipbox.top/study/shownews.php?id=30
http://jslin.cn/新版ip小魔棒介绍和使用教程(2022年6月22日后购买的)-ip小魔棒,固定ipbox,公网固定ip专家.pdf
端口为 11461-11465
549 544 542 540 531 534 528 524 518 515 509 506 500 496 480 470 468 464 462 461 460 454 448 446 444 438 433 432 430 427 420 417 416 409 408 403 398 397 394 388 383 378 377 376 374 366 365 362 361 359 357 355 352 351 348 344 343 339 336 334 331 324 323 320 318 309 308 306 292 282 279 247 243 238 232 229 227 225 220 215
js 解析 xml, 转为 dom 对象, 可以使用 dom 的方法
var parser=new DOMParser();//创建文档对象
var xmldoc=parser.parseFromString(val,'text/xml')
let res= xmldoc.getElementsByTagName("userTask")
2
3
防抖使用
返回的是一个函数, 需要通过这个函数来进行作用域链的延长, 因此不能直接调用
// 这样是不行的
onInput: (val)=>{
debounce(tset, 200)()
}
2
3
4
// 如果非要那样可以使用
onInput: (val)=>{
if(window.$test) {
window.$test();
} else {
window.$test = debounce(tset, 2000)
window.$test()
}
}
// 最正确的方法
watch: {
form1: {
handler (val, old) {
this.check(this, val)
},
deep: true
}
},
methods: {
// 将防抖函数写入方法中可以在Watch中随时调用
// debounceFn传入函数内部this的指向不是当前vue实例,我这里采用的是调用的时候讲this传入
check: debounceFn ((vm, val) => {
if (val.sum) {
vm.isSubmit = true
}
}, 500)
}
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
table 去掉间隙
border-collapse:collapse;
2
nginx 配置 不缓存, 清空缓存
https://www.yisu.com/zixun/357333.html
缓存问题, vue 版本更新后缓存问题
如何处理 vue 更新后, js 和 css 具有缓存问题 , 如何告知用户端 我升级了. 如何控制那些该缓存那些不该缓存, 如何知道那些文件变了 那些没有变.
思路: 在 public 中放一个 config.js 文件, 每次去请求这个文件, 拿去版本号之后, 再去加载对应版本号的文件
bpmn-js 流程图 获取当前节点以及上一个节点
// 递归寻找上一个节点是 bpmn:UserTask
function findPreNode(current, isFirst) {
if (!current) return false
if (!isFirst && current.type == 'bpmn:UserTask') return true
if (current.type == 'bpmn:SequenceFlow') {
return findPreNode(current.source)
} else {
return findPreNode(current.incoming[0])
}
}
let hasPre = false
// 获取所有节点
let allNord = this.modeler.get('elementRegistry')?._elements || {}
if (
allNord[this.formData.id]?.element &&
allNord[this.formData.id].element.type == 'bpmn:UserTask'
) {
hasPre = findPreNode(allNord[this.formData.id].element, true)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
子父组件执行顺序
// 父created => 子 created => 子mounted => 父 mounted;
// 但通过以下方式引入, 顺序会随机
// const searchFrame = () =>
// import("../../components/searchFrame/searchFrame.vue");
2
3
4
筛选树
// 结构
<el-input placeholder="输入关键字进行搜索" class="filter" v-model="filterText"> </el-input>
<el-tree
:data="treeData"
:props="defaultProps"
icon-class="tree-icon el-icon-caret-right"
:accordion="true"
:highlight-current="true"
:filter-node-method="filterNode"
ref="tree"
>
// 数据
filterText: "",
treeData: [
{
id: 1,
name: "一级1",
children: [
{
id: 4,
name: "二级1-1",
children: [
{
id: 9,
name: "三级1-1-1",
},
{
id: 10,
name: "三级1-1-2",
},
],
},
],
},
{
id: 3,
name: "一级3",
children: [
{
id: 7,
name: "二级3-1",
},
{
id: 8,
name: "二级3-2",
},
],
},
],
defaultProps: {
children: "children",
label: "name",
value: "id",
},
// 方法
filterNode(value, data, node) {
if (!value) return true;
function f(node) {
let res =
node.parent && node.parent.data && node.parent.data.name && node.parent.data.name.indexOf(value) !== -1;
if (node.parent) return f(node.parent) || res;
return res || data.name.indexOf(value) !== -1;
}
return f(node);
},
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
时钟翻页效果
https://github.com/Yuezi32/flipClock/blob/master/vue/src/components/Flipper.vue
https://mp.weixin.qq.com/s/sA9S-mYAqVd527uggGeLfA
linux 下安装 node , 配置环境变量
下载下来, 然后 tar 文件.xz 解压, 配置环境变量 ln -s /当前路径 /usr/bin/node , 同理配置 npm;
json 和 blob 转换
// 3、读文件的方法
var reader = new FileReader()
// 4、将文件转化为文本,两个参数,一个是读取内容,一个是编码格式
reader.readAsText(res.data, 'utf-8')
// 5、onload (文件读取成功)或onloadend (无论成功或失败都触发) 文件内容为 string 转 Object
reader.onload = function () {
try {
var result = JSON.parse(reader.result)
if (result.status == '101') {
return Message.error(
`错误${result.status}:${result.errors && result.errors[0].message}`
)
}
} catch (err) {
resolveBlob(res, mimeMap.zip)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
七牛云上传文件夹
七牛云图形化工具 KODO BROWSER
element ui 表格 合并相同内容
思路: 就是 element ui 不是要 传入 rowSpan 和 colSpan 来进行控制合并, 所以对数据进行了处理. 对于一列相同的数据给第一个设置 rowSpan, 后面几个相同的 rowSpan 设置为 0 用来隐藏.
直接上代码, 两个文件
// test.vue
<template>
<el-table
border
:data="tableData"
:span-method="objectSpanMethod"
style="width: 100%"
>
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
<el-table-column prop="num" label="数目"> </el-table-column>
</el-table>
</template>
<script>
//引入封装的js
import mergeSameData from "./tool.js";
export default {
data() {
return {
tableData: [
{
date: "date1",
name: "name",
address: "address2",
num: "num",
},
{
date: "date2",
name: "name",
address: "address2",
num: "num",
},
{
date: "date3",
name: "name",
address: "address3",
num: "num",
},
],
spanObj: {},
keyArr: ["date", "name", "address", "num"],
};
},
created() {
this.tableData = mergeSameData(this.tableData, this.keyArr);
console.log("created -> this.tableData", this.tableData)
//动态渲染 请渲染数剧结束后在执行此方法
// this.spanObj = dataMethod(this.tableData);
},
methods: {
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// rowspan 0, colspan 0的时候就会隐藏这个元素, rows为多少时, 就相当于多少行合并, cols多少列合并
return {
rowspan: row[column.property + "Row"],
colspan: row[column.property + "Row"] === 0 ? 0 : 1,
};
},
},
};
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// tool.js
function mergeSameData(tableData, keyArr) {
tableData.forEach((item, index) => {
keyArr.forEach((keyItem, keyIndex) => {
let preIndex = item[keyItem + 'Index'] || 0
if (
index > 0 &&
isNaN(item[keyItem]) &&
item[keyItem] === tableData[index - 1][keyItem]
) {
// 如果当前数据和上一条数据相同
tableData[index][keyItem + 'Row'] = 0
// 记住下标, 用于计算相同的
tableData[index + 1] &&
(tableData[index + 1][keyItem + 'Index'] = preIndex)
// 相同的row进行+1
tableData[preIndex][keyItem + 'Row'] =
(tableData[preIndex][keyItem + 'Row'] || 1) + 1
} else {
tableData[index + 1] &&
(tableData[index + 1][keyItem + 'Index'] = index)
// 对于不相同的, 直接返回1
tableData[index][keyItem + 'Row'] = 1
}
})
})
return tableData
}
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
30
31
实现效果:
问题记录:
bpmn.js 获取上一级节点
judgeHasPrePerson() {
// 递归寻找上一个节点是 bpmn:UserTask
function findPreNode(current, isFirst) {
if(!current) return false
if(!isFirst &¤t.type == "bpmn:UserTask") return true;
if(current.type=='bpmn:SequenceFlow') {
return findPreNode(current.source)
} else {
return findPreNode(current.incoming[0])
}
}
let hasPre = false;
// 获取所有节点
let allNord = this.modeler.get('elementRegistry')?._elements ||{};
if (allNord[this.formData.id]?.element && allNord[this.formData.id].element.type=='bpmn:UserTask') {
hasPre = findPreNode(allNord[this.formData.id].element, true)
}
if (hasPre) {
// 有上一个节点
} else {
}
}
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
vitepress 文档
https://process1024.github.io/vitepress/
vitepress 引入全局组件
// .vitepress\theme\index.js
import DefaultTheme from 'vitepress/theme'
import CodeGroup from '../../../components/CodeGroup.vue'
export default {
...DefaultTheme,
enhanceApp({ app }) {
app.component('CodeGroup', CodeGroup)
}
}
2
3
4
5
6
7
8
9
10
vpn 机场
https://suyunti.com/user/shop 速云梯 https://okokcloud.net/ www.okyun01.com okcloud https://mojie.la/#/plan 魔界
indexDB
插件 localForage , 像 localstorage 一样使用
auto.js 已死, 平替软件
Autox.js 文档: http://doc.autoxjs.com/ AutoJs6 项目文档:https://github.com/SuperMonster003/AutoJs6 RobotJs 项目文档:https://yooge.github.io/robot-docs/startnow.html Hamibot 项目地址:https://github.com/hamibot/hamibot
auto js 的案例https://blog.csdn.net/snailuncle2/article/details/115278704
赚钱
这篇文章的回答, 我相信你会有所收获
https://www.zhihu.com/question/348757572
索尼调成和佳能一样肤色
佳能肤色更红, 对比度平滑一点
vitepress 文档
https://process1024.github.io/vitepress/
https://github.com/process1024/vitepress
动态创建脚本
let script = document.createElement('script')
script.type = 'text/javascript'
script.src = src
document.getElementsByTagName('head')[0].appendChild(script)
2
3
4
vite 引入文件夹下面的全部文件
const mixins = import.meta.globEager('./mixins/*.js')
mixins: Object.values(mixins).map(item=>item.default),
2
3
4
blob 转 base64
/**
* base64 to blob二进制
*/
function dataURItoBlob(dataURI) {
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] // mime类型
var byteString = atob(dataURI.split(',')[1]) //base64 解码
var arrayBuffer = new ArrayBuffer(byteString.length) //创建缓冲数组
var intArray = new Uint8Array(arrayBuffer) //创建视图
for (var i = 0; i < byteString.length; i++) {
intArray[i] = byteString.charCodeAt(i)
}
return new Blob([intArray], { type: mimeString })
}
/**
*
* blob二进制 to base64
**/
function blobToDataURI(blob, callback) {
var reader = new FileReader()
reader.onload = function (e) {
callback(e.target.result)
}
reader.readAsDataURL(blob)
}
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
vant 结合 Compressor 进行图片压缩
/**
* 附件上传
* @param name 描述信息
* @return {*}
*/
afterRead(file) {
if (file.type == "application/pdf") {
// 对于pdf 不压缩
this.$set(this.form, "files", [
{
fileName: file.file.name,
fileContent: file.content
}
]);
return;
}
new Compressor(file.file, {
quality: 0.6,
success: result => {
var reader = new FileReader();
reader.onload = e => {
this.$set(this.form, "files", [
{
fileName: file.file.name,
fileContent: e.target.result
}
]);
};
reader.readAsDataURL(result);
},
error(err) {
console.log(err.message);
}
});
},
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
30
31
32
33
34
35
36
vue keep-alive include 不生效问题
- 检查 name 注意, 不是 router.js 中的 name, 而是单个 vue 组件中的 name 属性.
建议将 router.js 中的 name 和 vue 组件的 name 保持一致, 不要混乱.
export default {
name: 'index'
}
2
3
多层嵌套 网上的答案几乎都是检查 vue 组件的 name 属性, 但还是有一个巨坑.
那就是多级嵌套
<router-view></router-view>
,但凡有超过两个以上的 router-view 且是父子级关系,请都加上 keep-alive,只加一个不会生效.
// app.vue
<keep-alive include="app,index">
<router-view></router-view>
</keep-alive>
// other.vue
<keep-alive include="app,index">
<router-view></router-view>
</keep-alive>
2
3
4
5
6
7
8
9
vue env 全局变量
必须以 VUE_APP_
开头
在线听歌 下载音乐
免费证书 https 证书
sass 因为 node 版本导致项目报错, nvm 切换终极使用方案
问题: 因为 vite 或 sass 导致要切换版本, 并且 nvm 比较麻烦;
思路以及实践过程
想到的方法是通过 nvm 来进行 node 版本管理, 可是这样, 每次都要去 nvm use 一下, 实属麻烦, 有的时候可能会因为忘记 use 一下, 导致项目启了半天, 最后来个报错. 人都傻了.
为此, 搜寻了相关博客. 如下解决方案, 也想到了先 nvm use 一下, 然后再启动项目, 可是会出现报错问题. 'npm' 不是内部或外部命令,也不是可运行的程序或批处理文件。
"start": "nvm use v14.16.0 && npm run serve",
最终处理
想着可能是 nvm 切换的时候, 可能还没切换成功, 就执行了 npm, 所有准备搞个定时器, 搜索相关 bat 脚本的定时器语句.
"start": "nvm use v14.16.0 && timeout /t 3 && npm run serve",
2
ElementUI 上传文件按钮之选取文件按钮禁用后仍可点击
不仅给按钮加 disabed, 还要给 el-upload 加 disabed
微前端
综合考虑, 只是一个工具, 实现多项目的合并, 想着以最低成本来实现它, micro-app 便是最好的工具
使用简单
micro-app 没有任何依赖,这赋予它小巧的体积和更高的扩展性。
格式化文件夹 vscode 插件
Format Files 选中文件夹, 然后直接格式化即可
vscode 常用的快捷键
ctrl + L 选中当前行
ctrl + alt + L 打印
ctrl + shift + f 格式化
ctrl + ↑/↓ 移动可视区域
alt + ↑/↓ 移动当前行的位置
ctrl + alt + ↑/↓ 复制一行并移动
ctrl + c 没有选中文字的情况下复制当前行 , 选中后, 复制
ctrl + v 粘贴
ctrl + 2 窗口分为两行
ctrl + j 打开终端
ctrl + p 查找文件
ctrl + shift + p 搜索配置
ctrl + f 查找
ctrl + shift + f 当前项目全局查找
ctrl + h 替换
ctrl + + shift + h 当前项目全局替换
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vue 通过 js 的方式调用组件
https://blog.csdn.net/qq_42991509/article/details/103927293
流程管理
https://site.logic-flow.cn/examples/#/gallery
自定义表单
提取网页为 word, 存储网页
对于不需要复制的可以直接导出为 pdf 最省事
- 通过另存为保存网页
- 将保存的网页 html, 通过 word 打开, 然后另存为 word 即可
vue 同个组件使用 debounce 导致问题, 采用以下写法
export default {
created() {
// 每个实例都有了自己的预置防抖的处理函数
this.debouncedClick = _.debounce(this.click, 500)
},
unmounted() {
// 最好是在组件卸载时
// 清除掉防抖计时器
this.debouncedClick.cancel()
},
methods: {
click() {
// ... 对点击的响应 ...
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
win10 搭建 ftp
链接:https://pan.baidu.com/s/1fNfLKoCgSUNPsoyDT-XaVQ?pwd=ppqv 提取码:ppqv --来自百度网盘超级会员 V5 的分享
sideproject 做小而美的产品
程序员接单平台
https://www.jianshu.com/p/f0db1da647eb
https://www.zhihu.com/question/516024833
鲁大师绿色版
在线听歌网
https://zhuanlan.zhihu.com/p/166166968
AMD 设置缓存
https://www.123pan.com/s/poNZVv-qWmWA.html
语音播报
var utterThis = new window.SpeechSynthesisUtterance('张三,扫码成功!');
window.speechSynthesis.speak(utterThis); //这样就会有个美女姐姐语音朗读 张三,扫码成功!
2
3
flex 布局, 设置 flex: 1 后仍被子元素撑开内容
给 flex: 1 的那个元素设置 width: 0, 和 min-width:0 https://juejin.cn/post/6974356682574921765
vue 同一个组件的 debounce 相互影响
通过在 created 的时候定义这个函数
created() {
this.queryList = debounce(() => {
this.handlePicLoad();
}, 800);
},
2
3
4
5
实时语音转文字, 提取视频音频字幕
Whisper 结合模型
WhisperDesktop.zip https://dailin.lanzout.com/ihlw91exrned
链接:https://pan.baidu.com/s/13BnzZL7O-MR9S3NtZ-odJg?pwd=qwer 提取码:qwer --来自百度网盘超级会员 V5 的分享
操作步骤
链接:https://pan.baidu.com/s/1S6lfQdgcXWyRAlrjuZghzg?pwd=vyct 提取码:vyct --来自百度网盘超级会员 V5 的分享
- 选择模型
- 选择要读取的媒体文件以及存储文字的文件
美化滚动条
elementui 里面有这个组件 el-scrollbar
交警手势
总结一下, 自己总结的才是自己的
ipv6 开启
https://zhuanlan.zhihu.com/p/638004070
![基于ipv6实现几乎零成本的内网穿透方案,小白的踩坑历程与经验分享 - 知乎](https://jslin.cn/img/基于ipv6实现几乎零成本的内网穿透方案,小白的踩坑历程与经验分享 - 知乎.pdf)
https://hin.cool/posts/ddnsipv6.html
vxetable 虚拟表格 虚拟列表
https://vxetable.cn/v3/#/table/base/scrollStyle
border-image-slice 使用, 一张图片适配不同分辨率
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
}
.outer {
width: 100%;
height: 100%;
border: 2px solid #ccc;
}
.inner {
width: 100%;
height: 100%;
border-image-source: url('https://jslin.cn/img/next_new.259578d9.png');
/* border-image-slice: 400 50% 200 50% fill; */
border-image-slice: 800 100% 300 0% fill;
border-image-width: auto;
}
</style>
<body>
<div class="outer">
<div class="inner"></div>
</div>
</body>
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
30
31
32
33
chatgpt4 体验
资源
https://www.wanrenmi8.com/cn/index.html
git log 导出到文件里面
git log --pretty=format:"%ai,%s" --since=1day --author=zhangdailin --no-merges --encoding=GBK >> D:/jianguoyun/我的坚果云/1work/work/git.log
4kni01
929023000203756
音频压缩工具
https://zh-cn.aiseesoft.com/audio-compressor/
markdown 文件代码段不生效问题
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.renderWhitespace": "all",
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
"editor.acceptSuggestionOnEnter": "on"
},
2
3
4
5
6
7
8
9
10
11
cpu gpu 显卡排行榜
https://topic.expreview.com/CPU/
鼠标录制 宏录制
element ui 列表中的 tooltip 无法选中
import { getCell, getColumnByCell } from 'element-ui/packages/table/src/util'
import { getStyle, hasClass } from 'element-ui/src/utils/dom'
import { Table } from 'element-ui'
Object.assign(Table.components.TableBody.methods, {
handleCellMouseLeave() {
const tooltip = this.$refs.tooltip
if (tooltip && tooltip.expectedState) {
tooltip.setExpectedState(false)
clearTimeout(tooltip._timeoutLeave)
tooltip._timeoutLeave = setTimeout(() => {
if (!tooltip.expectedState) {
tooltip.handleClosePopper()
}
}, 150)
}
const cell = getCell(event)
if (!cell) return
const oldHoverState = this.table.hoverState || {}
this.table.$emit(
'cell-mouse-leave',
oldHoverState.row,
oldHoverState.column,
oldHoverState.cell,
event
)
},
handleCellMouseEnter(event, row) {
const table = this.table
const cell = getCell(event)
const tooltip = this.$refs.tooltip
if (cell) {
const column = getColumnByCell(table, cell)
const hoverState = (table.hoverState = { cell, column, row })
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event)
}
// 判断是否text-overflow, 如果是就显示tooltip
const cellChild = event.target.querySelector('.cell')
if (!(hasClass(cellChild, 'el-tooltip') && cellChild.childNodes.length)) {
setTimeout(() => {
tooltip.setExpectedState(false)
tooltip.handleClosePopper()
}, 600)
return
}
const range = document.createRange()
range.setStart(cellChild, 0)
range.setEnd(cellChild, cellChild.childNodes.length)
const rangeWidth = range.getBoundingClientRect().width
const padding =
(parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
(parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0)
if (
(rangeWidth + padding > cellChild.offsetWidth ||
cellChild.scrollWidth > cellChild.offsetWidth) &&
this.$refs.tooltip
) {
// TODO 会引起整个 Table 的重新渲染,需要优化
const showTooltip = () => {
this.tooltipContent = cell.innerText || cell.textContent
tooltip.referenceElm = cell
tooltip.$refs.popper && (tooltip.$refs.popper.style.display = 'none')
tooltip.doDestroy()
tooltip.setExpectedState(true)
this.activateTooltip(tooltip)
}
clearTimeout(tooltip._timeoutEnter)
tooltip._timeoutEnter = setTimeout(() => {
!tooltip.expectedState && showTooltip()
}, 500)
}
}
})
const ElTable = { extends: Table }
// const ElTableColumn = { extends: TableColumn }
components: {
BaseForm,
TableColumn,
ElTable,
// ElTableColumn,
},
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
前端 vue 上传时获取文件的 md5 哈希值
npm install spark-md5 --save
import SparkMD5 from "spark-md5";
2
//以下获取文件哈希值方法
var fileReader = new FileReader()
var spark = new SparkMD5.ArrayBuffer()
// 获取文件二进制数据
fileReader.readAsArrayBuffer(file)
fileReader.onload = (e: any) => {
spark.append(e.target.result)
var fileHash = spark.end()
console.log(fileHash, '文件哈希值')
}
//
2
3
4
5
6
7
8
9
10
11
无 js 实现左右拖拽 纯 css
https://www.zhangxinxu.com/study/201903/css-idea/behavior-stretch.php?aside=0
<div class="column">
<div class="column-left">
<div class="resize-bar"></div>
<div class="resize-line"></div>
<div class="resize-save">
左侧的内容,左侧的内容,左侧的内容,左侧的内容
</div>
</div>
<div class="column-right">右侧的内容,右侧的内容,右侧的内容,右侧的内容</div>
</div>
2
3
4
5
6
7
8
9
10
.column {
overflow: hidden;
}
.column-left {
height: 400px;
background-color: #fff;
position: relative;
float: left;
}
.column-right {
height: 400px;
padding: 16px;
background-color: #eee;
box-sizing: border-box;
overflow: hidden;
}
.resize-save {
position: absolute;
top: 0;
right: 5px;
bottom: 0;
left: 0;
padding: 16px;
overflow-x: hidden;
}
.resize-bar {
width: 200px;
height: inherit;
resize: horizontal;
cursor: ew-resize;
cursor: col-resize;
opacity: 0;
overflow: scroll;
}
/* 拖拽线 */
.resize-line {
position: absolute;
right: 0;
top: 0;
bottom: 0;
border-right: 2px solid #eee;
border-left: 1px solid #bbb;
pointer-events: none;
}
.resize-bar:hover ~ .resize-line,
.resize-bar:active ~ .resize-line {
border-left: 1px dashed skyblue;
}
.resize-bar::-webkit-scrollbar {
width: 200px;
height: inherit;
}
/* Firefox只有下面一小块区域可以拉伸 */
@supports (-moz-user-select: none) {
.resize-bar:hover ~ .resize-line,
.resize-bar:active ~ .resize-line {
border-left: 1px solid #bbb;
}
.resize-bar:hover ~ .resize-line::after,
.resize-bar:active ~ .resize-line::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
bottom: 0;
right: -8px;
background: url(./resize.svg);
background-size: 100% 100%;
}
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
百度网盘批量转存
看电视网站
缓存问题处理
不能使用$destory, 摧毁后, 将不能再缓存, 点击关闭的时候加入 keep-alive 的 exclude 中, 然后再移除掉
js 控制光标和获取光标位置
<body>
<input id="box"/>
<button onclick="test()">
获取光标位置
</button>
<button onclick="test2()">
设置光标位置为第一个字符与第二个字符之间
</button>
<script>
function test() {
const input = document.getElementById('box')
console.log(input.selectionStart)
}
function test2(index) {
const input = document.getElementById('box')
input.focus() // 如果是vue项目, 需要在nexttick中触发
input.setSelectionRange(1, 2)
}
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
对于页面缓存问题,有的时候不会执行到 beforeRouterEnter 这些页面内的路由, 通过在 beforeEach 里面写方法控制
如果下一个页面不缓存的话, 调用关闭 tab 清空当前页面缓存的方法, 清空当前页面的缓存, 可以使用将这个路由放到 exclude 里面, 然后再移除
table 导出为 excel
<template>
<div class="demo">
<table id="TableToExport">
<tr>
<td>name</td>
<td>sex</td>
</tr>
<tr>
<td>张三</td>
<td>女</td>
</tr>
</table>
<button id="sheetjsexport"><b>Export as XLSX</b></button>
</div>
</template>
<script>
// iui
export default {
mounted() {
document.getElementById('sheetjsexport').addEventListener('click', function () {
/* Create worksheet from HTML DOM TABLE */
var wb = XLSX.utils.table_to_book(document.getElementById('TableToExport'));
/* Export to file (start a download) */
XLSX.writeFile(wb, 'SheetJSTable.xlsx');
});
},
}
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
浏览器批量发送请求
通过复制为 fetch , 然后在控制台粘贴, 并修改要改的内容
修改 elementui 的组件
import { Button } from 'element-ui'
import { debounce } from '@u/tools'
console.dir(Button)
console.log(Button.methods.handleClick)
Object.assign(Button.methods, {
handleClick: debounce(function (evt) {
this.$emit('click', evt)
}, 300)
})
const ElButton = { extends: Button }
2
3
4
5
6
7
8
9
10
11
npm 发布自己的包
- npm login
- npm publish
- 注意包名不要和别人的冲突
vue 控制列表进修改页面后, 列表刷新
// store/module/refresh
const state = {
refreshList: [],
};
const mutations = {
ADD_PAGE: (state, name) => {
state.refreshList.push(name);
console.log("TCL: state.refreshList", state.refreshList)
},
REMOVE_PAGE: (state, name) => {
state.refreshList = state.refreshList.filter(item=>item!==name)
},
};
const actions = {
addRefreshPage({ commit }, name) {
commit('ADD_PAGE', name);
},
removeRefreshPage({ commit }, name) {
commit('REMOVE_PAGE', name);
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
// 控制的地方
// 刷新下个页面
this.$store.dispatch('refresh/addRefreshPage', 'ProjectEstablishmentReview');
// 刷新的地方
activated() {
let refreshList = this.$store.state.refresh.refreshList;
if (refreshList.includes(this.$route.name)) {
this.$store.dispatch('refresh/removeRefreshPage', this.$route.name);
// 刷新当前页面
console.log('TCL: 刷新');
// do something
}
console.log('TCL: 不需要刷新');
},
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
vue 处理更新后不刷新问题, 更新刷新缓存
// version.js
var extra = {
version: '0.1.1'
}
try {
global && (global.version = extra.version)
} catch {}
2
3
4
5
6
7
8
// 打包后的index.html
<script>
function createTag({ elementTag, src, type, rel, href, as }, actionFn) {
let script = document.createElement(elementTag);
type && (script.type = type); // "text/javascript"
src && (script.src = src);
rel && (script.rel = rel);
href && (script.href = href);
as && (script.as = as);
document.getElementsByTagName('head')[0].appendChild(script);
if (actionFn) {
if (window.all) {
// 对ie进行单独处理
script.onreadystatechange = function () {
if (script.readyStatus === 'loaded' || script.readyState === 'complete') {
// 执行后续事件
actionFn();
}
};
} else {
// 谷歌火狐
script.onload = function () {
// 执行后续操作。
actionFn();
};
script.onerror = function (val, err) {
console.log('script.onerror -> val', val);
console.log('script.onerror -> err', err);
};
}
}
}
</script>
<script>
createTag({ elementTag: 'script', src: 'version.js?t=' + +new Date(), type: 'text/javascript' }, getScript);
function getScript() {
var version = window.extra.version;
var linkArr = [
'chunk-00e7e416',
'chunk-03009f50',
'chunk-089dab5f',
'chunk-0b7d0906',
'chunk-13479358',
];
for (var index = 0; index < linkArr.length; index++) {
createTag({ elementTag: 'link', href: `assets/js/${linkArr[index]}_${version}.js`, rel: 'prefetch' });
}
var scriptArr = ['chunk-common', 'chunk-vendors', 'index'];
for (var index = 0; index < scriptArr.length; index++) {
createTag({ elementTag: 'script', src: `assets/js/${scriptArr[index]}_${version}.js` });
}
}
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
git 只合并部分代码 git merge
// 合并dev分支下面的所有文件
git merge dev src/views/**
2
jsx 在 vue 中使用
{
name: "BaseTable",
methods: {
sizeChange(size) {
this.$emit("update:pageSize", size);
this.pageChange();
},
currentChange(current) {
this.$emit("update:currentPage", current);
this.pageChange();
},
pageChange() {
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = null;
this.$emit("pageChange", this.currentPage, this.pageSize);
}, 50);
},
doLayout() {
this.$refs.elTable.doLayout();
},
getColumns(h, list) {
return list.map(item => {
const scopedSlots = {
header: props =>
this.$scopedSlots[item.label]
? this.$scopedSlots[item.label](props)
: item.label,
};
if (!item.type && !item.formatter) {
scopedSlots["default"] = props =>
this.$scopedSlots[item.prop]
? this.$scopedSlots[item.prop](props)
: props.row[item.prop];
}
return item.vif !== false ? (
<el-table-column
{...{
attrs: {
...item,
},
scopedSlots,
}}
>
{item.children ? this.getColumns(h, item.children) : []}
</el-table-column>
) : (
""
);
});
},
},
render(h) {
return (
<div class="base-table">
{this.$scopedSlots.add || this.$scopedSlots.sub ? (
<div class="add-row">
<div class="left">
{this.$scopedSlots.add ? this.$scopedSlots.add() : ""}
</div>
<div class="right">
{this.$scopedSlots.sub ? this.$scopedSlots.sub() : ""}
</div>
</div>
) : (
""
)}
<el-table
ref="elTable"
{...{
attrs: {
stripe: true,
headerCellStyle: this.headerRowStyle,
...this.$attrs,
},
on: {
...this.$listeners,
},
}}
>
{this.getColumns(this.$createElement, this.list)}
</el-table>
<el-pagination
{...{
attrs: {
small: true,
background: true,
pageSize: this.pageSize,
currentPage: this.currentPage,
total: this.total,
pageSizes: this.pageSizes,
layout: "total, sizes, prev, pager, next, jumper",
},
on: {
"size-change": this.sizeChange,
"current-change": this.currentChange,
},
}}
/>
</div>
);
},
};
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
git 合并部分文件
思路就是在当前分支上创建一个合并分支, 再去其他分支 merge 代码, 这时候是合并所有的, 然后在返回原分支去 git checkout 需要合并的文件就行了
对接小爱同学
https://blog.csdn.net/qq_32299035/article/details/104897710
https://blog.51cto.com/u_16213421/9084315
备份系统盘 , 重装系统
目前用的是 PE 系统里面的磁盘和磁盘表备份, 然后再新的磁盘里面拷贝, 然后再使用傲梅里面有一个创建启动的.
windows 防止自动更新教程
把自动设置时间关闭, 选择时间为 2038 年以前, 38 年以后会出问题, 系统会一直刷新, 然后去更新里面选择更新时间.