0%

显示项目的所有文件列表及行数

1
git ls-files | xargs wc -l

只统计项目代码的总行数

1
git ls-files | xargs cat | wc -l

只查看项目文件列表

1
git ls-files

后记

转载来源

补充

也可以装一个 VSCode 插件,叫做 VS Code Counter,可以统计项目

问题

群友大佐出了一道题

1
2
3
add[1] + 1 // 2
add[1][2][3] + 4 // 10
add[10][-5][3][100] * 2 // 216

解答

阅读全文 »

浮点数

代码

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
30
31
32
33
34
35
36
37
void day2() {
// 定义一个浮点数 π
float pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286f;
// 定义一个双精度浮点数 π
double pi2 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286;
// 定义一个长双精度浮点数 π
long double pi3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286l;

// 打印浮点数
cout << pi << endl;
// 打印双精度浮点数
cout << pi2 << endl;
// 打印长双精度浮点数
cout << pi3 << endl;

// setprecision() 设置精度
cout << setprecision(100) << pi << endl;
cout << setprecision(100) << pi2 << endl;
cout << setprecision(100) << pi3 << endl;

// 完整的打印出来
cout.precision(100);
cout << pi << endl;
cout << pi2 << endl;
cout << pi3 << endl;

// 打印结果如下
// 3.14159
// 3.14159
// 3.14159
// 3.1415927410125732421875
// 3.141592653589793115997963468544185161590576171875
// 3.141592653589793115997963468544185161590576171875
// 3.1415927410125732421875
// 3.141592653589793115997963468544185161590576171875
// 3.141592653589793115997963468544185161590576171875
}
阅读全文 »

前言

大佐在群里出了一道题是在页面上显示一个毫秒级的定时器,下面是大佐发的答案,赶紧收藏起来

示例

代码

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
<StrictMode>
<App />
</StrictMode>
);

App.js

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
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
import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import "./styles.css";

export default function App() {
const phase = useRef("idle");
const base = useRef();
const [btnText, setBtnText] = useState("Start");
const [accTime, setAccTime] = useState(0);
const [elsTime, setElsTime] = useState(0);

const time = useMemo(() => accTime + elsTime, [accTime, elsTime]);

useEffect(() => {
let stopped = false;

(function tick() {
if ("running" === phase.current) {
setElsTime(performance.now() - base.current);
}
!stopped && requestAnimationFrame(tick);
})();

return () => (stopped = true);
}, []);

const onClickButton = useCallback(() => {
phase.current = {
idle: "running",
paused: "running",
running: "paused"
}[phase.current];

setBtnText(
{
idle: "Start",
paused: "Resume",
running: "Pause"
}[phase.current]
);

if ("running" === phase.current) {
base.current = performance.now();
} else if ("paused" === phase.current) {
setAccTime(time);
setElsTime(0);
}
}, [time]);

return (
<div className="App">
<h1>{(time * 1e-3).toFixed(3)}</h1>
<button onClick={onClickButton}>{btnText}</button>
</div>
);
}

styles.css

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
30
31
32
33
34
* {
box-sizing: border-box;
}

body {
background-color: #444;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}

h1 {
background-color: #222;
color: white;
padding: 12px 20px;
min-width: 200px;
text-align: center;
}

button {
padding: 8px 32px;
border: none;
background-color: slateblue;
color: white;
cursor: pointer;
min-width: 200px;
font-size: 16px;
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
"Lucida Sans", Arial, sans-serif;
}

知识点

requestAnimationFrame

requestAnimationFrame() 方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。

performance.now()

MDN - performance.now()

performance.now() 方法返回一个 DOMHighResTimeStamp,以毫秒为单位,精确度可达 5 微秒(在实现中,将时间戳的第 12 位四舍五入到最接近的整数)。

useCallback

useCallback 会返回一个 memoized 回调函数。

在这里使用 useCallback 的原因是因为 onClickButton 函数会在每次渲染时都会被创建,如果不使用 useCallback 的话,每次渲染都会创建一个新的函数,这样会导致每次渲染都会触发 useEffect,这样就会导致页面卡顿。

useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

在这里使用 useRef 的原因是因为 useRef 返回的 ref 对象在组件的整个生命周期内保持不变,这样就可以保证 phase.current 的值在每次渲染时都不会被重置。

useMemo

useMemo 会在渲染期间执行,它会返回一个 memoized 值。

在这里使用 useMemo 的原因是因为 useMemo 会在渲染期间执行,它会返回一个 memoized 值,这样就可以保证 time 的值在每次渲染时都不会被重置。

进制转换

十进制转二进制

十进制转二进制的方法是:除 2 取余,直到商为 0 为止,然后把余数倒过来就是二进制数。

比如:十进制数 10 转二进制数

1
2
3
4
10 / 2 = 5 余 0
5 / 2 = 2 余 1
2 / 2 = 1 余 0
1 / 2 = 0 余 1

所以 10 的二进制数为 1010

阅读全文 »

问题

在开发过程中,我们经常需要查看 Sequelize 生成的 SQL 语句,以便于调试。

解决

主要是添加 logQueryParameters: truelogging: true 这两个参数

1
2
3
4
5
6
7
var sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mysql',
host: 'localhost',
port: 3306,
logQueryParameters: true,
logging: true
});

其中 logQueryParameters 表示是否打印参数,logging 表示是否打印 SQL 语句

但实际上会出现这样的状况,会发现控制台打印的参数无法在 SQL 里面执行。

1
2
UPDATE `users` SET `age`=10;
INSERT INTO `UserData` (`id`,`name`,`phone`,`provinceCode`,`cityCode`,`createdAt`,`updatedAt`) VALUES (DEFAULT, '张三', '12345678901', '11', '1101', '2023-08-04 05:21:59', '2023-08-04 05:21:59');

会变成

1
2
3
UPDATE `users` SET `age`=?; 10
INSERT INTO `UserData`
(`id`,`name`,`phone`,`provinceCode`,`cityCode`,`createdAt`,`updatedAt`) VALUES (DEFAULT,?,?,?,?,?,?); "张三", "12345678901", "11", "1101", "2023-08-04 05:21:59", "2023-08-04 05:21:59"

对于使用 Sequelize 进行插入操作,日志输出会显示带有占位符的 SQL 查询语句,这是因为 Sequelize 会使用参数化查询来防止 SQL 注入攻击,并提高查询的性能。

然后我去看了源码

https://github.com/sequelize/sequelize/blob/345981f2eb4c1aa709d5b831136b8dbbb32e72b8/lib/dialects/mysql/query.js#L37

1
const complete = this._logQuery(sql, debug, parameters);

https://github.com/sequelize/sequelize/blob/60d16a34562d4f7ed0fa74ede65a9c641a7e6a95/packages/core/src/dialects/abstract/query.js#L361

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
_logQuery(sql, debugContext, parameters) {
const { connection, options } = this;
const benchmark = this.sequelize.options.benchmark || options.benchmark;
const logQueryParameters = this.sequelize.options.logQueryParameters || options.logQueryParameters;
const startTime = Date.now();
let logParameter = '';

if (logQueryParameters && parameters) {
const delimiter = sql.endsWith(';') ? '' : ';';

logParameter = `${delimiter} with parameters ${NodeUtil.inspect(parameters)}`;
}

const fmt = `(${connection.uuid || 'default'}): ${sql}${logParameter}`;
const queryLabel = options.queryLabel ? `${options.queryLabel}\n` : '';
const msg = `${queryLabel}Executing ${fmt}`;
debugContext(msg);
if (!benchmark) {
this.sequelize.log(`${queryLabel}Executing ${fmt}`, options);
}

return () => {
const afterMsg = `${queryLabel}Executed ${fmt}`;
debugContext(afterMsg);
if (benchmark) {
this.sequelize.log(afterMsg, Date.now() - startTime, options);
}
};
}

发现它并没有直接把参数替换掉,而是传入到了数组中,最后调用了 mysql2 的 execute 方法

https://github.com/sidorares/node-mysql2/tree/cf1a8b7d4c3bb4ee13e4362d85419efe9fb80202/documentation/zh-cn#sql预处理的使用

1
2
3
4
const [rows, fields] = await connection.execute(
'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
['Morty', 14]
);

使用 MySQL2,您还可以提前准备好SQL预处理语句。 使用准备好的SQL预处理语句,MySQL 不必每次都为相同的查询做准备,这会带来更好的性能。 如果您不知道为什么它们很重要,请查看这些讨论:

所以我只简单的修改了一下源码,添加了一个输出实际 SQL 的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const mysql = require('mysql2');

const connection = mysql.createConnection({
host: 'your_mysql_host',
user: 'your_mysql_username',
password: 'your_mysql_password',
database: 'your_mysql_database',
});

const sql = 'SELECT * FROM your_table WHERE column = ?';
const values = ['some_value'];

connection.execute(sql, values, (err, results) => {
if (err) {
console.error('Error executing query:', err.message);
return;
}

console.log('Query:', connection.format(sql, values)); // 打印查询语句
console.log('Results:', results);
});

connection.end();

起因

我司的网真是一言难尽,有时候会出现网速很慢的情况需要开手机热点,但是调用接口上传代码又需要内网,所以需要双网卡。

方案

设置双网卡

  1. 有线网卡连公司内网
  2. 无线网卡连手机热点

刚好我是苹果手机,所以又有了另一个更好的方案,这样就不用拉公司的网线了哈哈哈哈哈。

  1. 无线网卡连公司内网
  2. iPhone USB 连接电脑,开启 USB 共享网络

设置优先级

如图所示设置一下优先级,让网络优先走我的手机 iPhone USB

设置网卡优先级

设置网卡优先级

设置路由

想让公司的内网走无线网卡,其它的走手机,所以需要设置一下路由。

先查看一下路由表

1
netstat -nr

查看路由表

可以看到有两个 default,其中第一个就是我的手机(iPhone USB),第二个就是公司内网(无线网卡)。

1
2
3
4
Internet:
Destination Gateway Flags Netif Expire
default 172.20.10.1 UGScg en7
default 10.1.17.254 UGScIg en0

然后可以用 nslookup 命令查看一下公司内网的域名解析

1
nslookup www.baidu.com

拿到IP地址后,添加路由

1
sudo route add -net 解析到的IP地址 -netmask 你要转发的网关 你的手机IP地址

网关可以在网络设置中查看,我的是 255.255.255.0

1
2
sudo route add -net 192.168.1.123 -netmask 255.255.255.0 10.1.17.254
sudo route add -net 192.168.1.100 -netmask 255.255.255.0 10.1.17.254

恢复路由

https://discussionschinese.apple.com/thread/250389463

有时候公司WIFI会断掉,这时候就需要恢复路由了,不然会导致无法访问外网。

1>先获得当前的路由表:

1
netstat -nr

2> 然后手动清楚路由表,最好运行多次,直到控制台不打印任何信息为止

1
sudo route -n flush

参考

问题

Webpack 中配置了路径的别名 @ ,但是在使用的时候,Eslint 报错了:

1
import { useAppSelector, useAppDispatch } from '@/redux/hooks'; // error TS2307: Cannot find module '@/redux/hooks'

解决问题

在 tsconfig.json 中配置 paths

1
2
3
4
5
6
7
8
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}

项目中总是用 ../../../ 很烦,所以决定用别名来解决这个问题。

配置

1
2
3
4
5
6
7
8
9
10
// webpack.config.js
const path = require('path')

module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}

使用

1
import { a } from '@/a.js'