Yet another bootstrap theme.

2022-08-26
使用Css提升页面滚动性能

一般情况下 CSS 并不会影响 JS 事件,但有一个 CSS 属性则比较特殊,那就是 pointer-events,它可以用来规避鼠标事件,其中大部分属性值只适用于 SVG(可缩放矢量图形)操作,而我们只需要关注其 none 属性值,该值表示鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。

我们经常会碰到类似设置半透明遮罩的需求,通常是绝对定位一个div盖在元素上方,这时遮罩层的鼠标事件优先级会更高,使得打上遮罩的元素无法进行正常交互行为,此时只需给遮罩设置 pointer-events: none; 即可”穿透”遮罩与元素交互.
重点来了,既然该属性可以阻止元素成为鼠标事件,那么修改页面该属性值为 none,就能避免在滚动时鼠标频繁触发包括hover在内的任何鼠标事件,从而提升了页面滚动时的性能。

1
2
3
body {
pointer-events: none;
}

使用滚动监听事件可实现灵活控制:

1
2
3
4
5
6
7
8
let timer = null
window.addEventListener("scroll", function () {
document.body.style.pointerEvents = 'none'; // 滚动时禁用鼠标事件
if (timer) { clearTimeout(timer) }
timer = setTimeout(() => {
document.body.style.pointerEvents = 'auto'; // 释放
}, 100);
})

如果是移动端网页,没有鼠标事件是不是就不能用上面的属性来优化滚动了呢?确实不可以,但移动端则有另外一个特殊属性具有异曲同工之处,那就是 touch-action。
顾名思义,该属性是用于设置触摸屏如何操纵元素区域动作,同样的,touch-action 可以禁用浏览器在移动端处理手势的事件,进而提高页面滚动性能,同时它还能解决移动端 点击延迟问题(很多人可能只知道viewport meta标签,或fastclick)。不过需要注意的是,虽然该属性也有 none 值,但在这里并不适用,因为”滚动”也属于手势的一种,应该使用 manipulation 这个值,意为只允许进行滚动和持续缩放操作,也就相当于禁用了其他页面手势。
全局生效要写在 html 上:

1
2
3
html {
touch-action: manipulation;
}

类似的,如果移动端有自定义拖动的需求,也可以用这个 CSS 来优化性能,当我们需要完全阻止原生touch事件时JS设置 touch-action 为 none,不需要再还原即可。

1
2
3
4
5
6
7
8
// 在需要时主动触发对全局的手势禁用
document.documentElement.style.touchAction = 'none'
// 或者独立禁用某一片区域的手势操作
document.getElementById('xxx').style.touchAction = 'none'
// 不需要时还原,例如在抬手事件中处理
document.addEventListener('touchend', function (event) {
document.documentElement.style.touchAction = 'manipulation' // 或 auto
});

可能有的朋友就会问了,如果我们在 touchstart 或 touchmove 事件中用 event.preventDefault() 阻止系统默认事件,不就可以阻止手势操作吗?
preventDefault()能阻止默认事件,当然包括手势事件,但是如果在 windiw document body 这些地方直接使用,不仅没有效果,浏览器还会出现红字严重报错,这是因为 touch 监听事件都是先进行了”触摸”才能执行回调,如果需要阻止默认事件,那么就必须在触摸开始前就检查是否需要阻止,滑动响应的优先级反而降低了,Google为了保证滑动流畅性就默认取消了这一机制。
所以从 chrome56 开始,如果你在全局 touch 事件中不声明这是”非被动”操作,那么chrome浏览器会默认不执行并报错。

1
2
window.addEventListener('touchmove', e => e.preventDefault()) // 无效,并报错
window.addEventListener('touchmove', e => e.preventDefault(), { passive: false }) // 有效

注:在Vue中有这样一个修饰符讲的也是同一件事情

而这个时候 touch-action 就发挥作用了,它相当于先声明了元素的可用触摸事件,这样浏览器就不会报错了,preventDefault() 也不会影响到触摸的事件,这两者可以结合来使用。(touch-action: none 会阻止任何触摸行为,但 touch 事件是正常触发的)

1
2
3
4
// 以下代码效果:在滑动时阻止系统默认事件,且页面可以正常滑动
document.documentElement.style.touchAction = 'manipulation'
window.addEventListener('touchmove', e => e.preventDefault())
// 将 manipulation 值改为 none,就可以完全阻止滑动默认事件,看情况来,毕竟 touch-action 还有很多可选值

相关资料传送门:
MDN - CSS - pointer-events
MDN - CSS - touch-action

Read More

2021-10-09
移动端页面底部安全距离

移动端页面 在全面屏手机(如:iPhone X等型号)上可能会出现页面底部有操作条。如果不进行兼容,会导致底部操作区域被遮挡。

1
2
env(safe-area-inset-bottom) // or -top
需要搭配 meta标签使用、并设置为 viewport-fit=cover
Read More

2021-09-25
移动端伪类不生效

Ios 移动端伪类不生效

经过一番查找,之后在mozilla开发社区找到了:active不起作用的答案:
[1] By default, Safari Mobile does not use the :active state unless there is a touchstart event handler on the relevant element or on the .

1
2
3
4

看来在iOS系统的移动设备中,需要在按钮元素或body/html上绑定一个touchstart事件才能激活:active状态。

document.body.addEventListener('touchstart', function () { //...空函数即可});

将上述事件监听代码加上后,Safari Mobile上就可以看到按钮按下后的切换效果了。

Read More

2021-09-15
小程序fixed定位失效

fixed失效

元素的父级元素设置了transform: translate(0, 0)属性,该属性设置之后,子元素固定定位失效
解决方法一:对父级元素设置transform: none; 或者display:inline

Read More

2021-07-09
排序

桶排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @description 桶排序
* @author ZhangYu
* @date 09/07/2021
* @param {number[]} arr
* @return {*} {number[]}
*/
function sort(arr: number[]): number[] {
const countArr = Array.from({ length: 11 }).fill(0) as number[]
arr.forEach(v => {
countArr[v]++
})
const res: number[] = []
countArr.forEach((v, i) => {
if (v) {
for (let j = 0; j < v; j++) {
res.unshift(i)
}
}
})
return res
}

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @description 冒泡排序
* @author ZhangYu
* @date 10/07/2021
* @param {number[]} arr
* @return {*} {number[]}
*/
function bubbleSort(arr: number[]): number[] {
for (let i = 0; i < arr.length; i++) {
for (let j = i; j < arr.length - 1; j++) {
if (arr[i] > arr[j + 1]) {
[arr[i], arr[j + 1]] = [arr[j + 1], arr[i]]
}
}
}
return arr
}

快速排序

1
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
/**
* @description 快速排序
* @author ZhangYu
* @date 10/07/2021
* @param {number[]} arr
* @return {*} {number[]}
*/
function quickSort(arr: number[]): number[] {
let len = arr.length
let jizhunNum: number | null = null
const leftArr: number[] = []
const rightArr: number[] = []

if (len <= 1) return arr

jizhunNum = arr.splice(0, 1)[0]
len -= 1

for (let i = 0; i < len; i++) {
const num = arr[i]
if (num > jizhunNum) {
rightArr.push(num)
} else {
leftArr.push(num)
}
}

return [...quickSort(leftArr), jizhunNum, ...quickSort(rightArr)]
}
Read More

2021-06-15
Mongo DB 基本操作

导入、导出数据库

1
2


显示所有数据库

1
show dbs

选择/切换 或者 创建数据库 如果没有这个数据库名称 将会进行创建

1
use {databaseName}

显示当前使用的数据库

1
db

删除数据库 databseName为要删除的数据库名称

先要使用use 选择要删除的某个数据库

1
2
use {databaseName}
db.dropDatabase()

显示数据库中的所有集合

1
show collections

删除集合 study为要删除的集合名称

1
db.{study}.drop()

向study集合中插入一条数据(如果没有study集合将会进行创建)

1
db.{study}.insert({‘name’: ‘test’})

从study集合中删除符合 {name:zhangsan} 条件的数据

1
db.{study}.remove({“name”: “zhangsan”})

查询sutdy集合中所有的数据(并且进行格式化)

1
db.{study}.find().pretty()

查询sutdy集合中前num条数据 (num 表示 查询几条)

1
db.{study}.find().limit(num)

从num条开始查询sutdy集合中的数据 (num表示 从第几条开始查询)

1
db.{study}.find().skip(num)

从study集合中修改符合 name:zhangsan 条件的第一条数据 并且改成 {name:wanglaowu} (会将满足条件的数据全部替换成这条数据,之前的数据会丢失)

1
db.{study}.update({“name”: “zhangsan”}, {‘name’: ‘wanglaowu’})

从study集合中修改符合 {name:zhangsan} 条件的第一条数据 并且改成 {name:wanglaowu}

1
db.{study}.update({“name”: “zhangsan”}, {$set : {‘name’: ‘wanglaowu’}})

从study集合中修改符合 {name:zhangsan} 条件的所有数据 并且改成 {name:wanglaowu}

1
db.{study}.update({“name”: “zhangsan”}, {$set : {‘name’: ‘wanglaowu’}}, {multi: true})
Read More

2021-05-21
mysql 联表查询出错为: only_full_group_by

在mysql8.x版本以上
联表查询出现了以下错误

1
2
3
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated
column 'db_instagram.VisitRecord.id' which is not functionally dependent on columns in
GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

这时候可以去 my.cnf文件中找到

1
2
3
my.cnf文件 存在位置
/etc/my.cnf
/etc/mysql/my.cnf
1
[mysqld]

设置

1
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

然后保存

重启mysql 服务就可以了

1
systemctl restart mysqld
Read More

2020-11-30
下载npm包很慢

打开终端,输入下面命令。设置npm仓库镜像地址。

1
npm config set registry http://registry.npm.taobao.org
Read More

2020-11-30
下载node-sass慢

打开终端,输入下面命令, 设置 node-sass 下载镜像地址。

1
npm config set sass-binary-site http://npm.taobao.org/mirrors/node-sass
Read More

2020-06-15
iOS中 Safari中点击态去除

在iOS的 Safari浏览器中默认点击超链接按钮时会有点击态,这个就比较讨厌了。

去除iOS在 Safari中默认点击态

点击态示例

1
2
3
* {
-webkit-tap-highlight-color: transparent;
}

通过设置 -webkit-tap-highlight-color 这个私有属性可以去除点击态

Read More