Typescript声明

namespace相当于给一个对象添加属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

declare const jQuery: (sel: string) => any;

type HttpMethods = 'GET' | 'POST';
declare function Fetch<T = any>(url: string, method: HttpMethods, data?: any): Promise<T>

// 相当于给Fetch对象添加属性
declare namespace Fetch {
const get: <T = any> (url: string) => Promise<T>
const post: <T = any> (url: string, data: any) => Promise<T>
}

export {
jQuery,
Fetch
}

solid.js学习

For

的数据项是固定的, 索引是 Signal.

根据引用来管理dom. 原数据项引用的位置改变了, dom的位置也随之改变. 原数据项引用的内容改变了, dom的内容也随之改变

<For> is “keyed by reference”: each node that it renders is coupled to an element in the array. In other words, if an element changes placement in the array, rather than being destroyed and recreated, the corresponding node will move too and its index will change.

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
import { render } from "solid-js/web";
import { createSignal, For } from "solid-js";

function App() {
var a = { id: "J---aiyznGQ", name: "Keyboard Cat" };
var b = { id: "J---aiyznGQ", name: "Keyboard Cat1" };
var c = { id: "J---aiyznGQ", name: "Keyboard Cat2" };

const [cats, setCats] = createSignal([a, b, c]);

return (
<ul>
<li onClick={() => { setCats([b,c,a]); }}>
使用原对象引用
</li>
<li
onClick={() => {
setCats([
{ id: "J---aiyznGQ", name: "Keyboard Cat2" },
{ id: "J---aiyznGQ", name: "Keyboard Cat" },
{ id: "J---aiyznGQ", name: "Keyboard Cat1" },
]);
}}
>
使用新对象
</li>
<For each={cats()}>
{(cat, i) => (
<li>
<a
target="_blank"
href={`https://www.youtube.com/watch?v=${cat.id}`}
>
{i() + 1}: {cat.name}
</a>
</li>
)}
</For>
</ul>
);
}

render(() => <App />, document.getElementById("app"));

在浏览器的dom对象中观察,使用原对象引用,solid只是将原dom进行移动, 而使用新对象,则会删除重新创建.

在模板里面数组的index使用signal来输出, 个人猜测这样写的原因是, 节点的复用会导致顺序的混乱, 所以index没有跟着节点走

Index

的数据项是 Signal ,并且索引是固定的。

使用位置来管理dom. 所以这里的index不再是 Signal, 而数据项是 Signal. 节点模板代码里, 数据项变更的时候, 只会更改节点的值和内容, 不再移动节点.

问题: 如果删除了数据中间第三个数据项, 会删除对应第三个的节点, 还是最后一个节点?
答案: 会删除最后一个节点, 然后更新第三个节点后的所有节点.

在solid的新旧数据比较过程中, 使用的是引用进行比较的, 但是字符串进行引用比较没有意义,因为在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
import { render } from 'solid-js/web';
import { createSignal, Index } from 'solid-js';

function App() {
const [cats, setCats] = createSignal([
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
]);

return (
<ul>
<li onClick={() => { setCats(cats()); }}>
使用原对象引用
</li>
<Index each={cats()}>
{(cat, i) => (
<li>
<a target="_blank" href={`https://www.youtube.com/watch?v=${cat().id}`}>
{i + 1}: {cat().name}
</a>
</li>
)}
</Index>
</ul>
);
}

render(() => <App />, document.getElementById('app'))

组件中, 每一项的更新由自己决定, 并不会影响数组中的其他数据

react宽度可拖拽组件

了解拖拽之前先了解两个api

element.setCaptureelement.releaseCapture

setCapture: 在处理一个 mousedown 事件过程中调用这个方法来把全部的鼠标事件重新定向到这个元素,直到鼠标按钮被释放或者 document.releaseCapture() 被调用。
releaseCapture: 如果该 document 中的一个元素之上当前启用了鼠标捕获,则释放鼠标捕获

核心逻辑

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
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
import React, { Component } from 'react';
import './index.scss';
import {Card,Icon,Input, Layout } from 'antd';
import TreeOrganize from './treeOrganize';
const { Sider, Content } = Layout;
let dragBtn, dragDom, dragCollDom;

export default class SelectDept extends Component {

componentDidMount() {
this.setSiderWidth();
}

// 设置侧边栏宽度
setSiderWidth = () => {
dragBtn = document.getElementById('drag-tip');
dragDom = document.getElementById('drag-area');
dragCollDom = document.getElementById('collapse_sider');
var siderWidth = Number(window.localStorage.getItem(this.props.SiderWidthDivide));
if (siderWidth == 0) {
this.setMaxValue(256);
} else {
if (siderWidth < 256) {
this.setMinValue(32);
} else {
this.setMaxValue(siderWidth);
}
};
}

isIE = () => navigator.userAgent.toLowerCase().indexOf('trident') > -1 ? true : false;

MouseDown = (e) => {
// 鼠标的X轴坐标
let clientX = e.clientX;
// 拖动块距离屏幕左侧的偏移量
let offsetLeft = dragBtn.offsetLeft;

// 鼠标移动
document.onmousemove = (e) => {
let curDist = offsetLeft + (e.clientX - clientX), // 拖动块的移动距离
maxDist = 700; // 拖动块的最大移动距离
// 边界值处理
if (curDist < 243) {
// 设置值(保证拖动块一直在拖动盒子的相对位置)
curDist < 32 && (curDist = 32);
this.setMinValue(curDist);
return false
}
curDist > maxDist && (curDist = maxDist);
this.setMaxValue(curDist);
return false;
};
// 鼠标松开
document.onmouseup = (e) => {
let curDist = offsetLeft + (e.clientX - clientX); // 拖动块的移动距离
if (curDist < 243) {
this.setMinValue(32);
}
document.onmousemove = null;
document.onmouseup = null;
// 释放鼠标
dragBtn.releaseCapture && dragBtn.releaseCapture();
};
// 捕获鼠标
dragBtn.setCapture && dragBtn.setCapture();
return false;
};

setMinValue = (curDist) => {
window.localStorage.setItem(this.props.SiderWidthDivide, '32');
if (this.isIE()) {
dragBtn.style.cssText = `left:${curDist}px;`;
dragCollDom.style.cssText = `flex:0 0 ${curDist}px;width:${curDist}px`;
dragDom.style.cssText = 'flex:0 0 0px;width:0px';
} else {
dragBtn.style.left = dragCollDom.style.width = curDist + 'px';
dragCollDom.style.flex = `0 0 ${curDist}px`;
dragDom.style.flex = '0 0 0px';
dragDom.style.width = '0px';
}
}

setMaxValue = (curDist) => {
window.localStorage.setItem(this.props.SiderWidthDivide, curDist);
// 设置值(保证拖动块一直在拖动盒子的相对位置)
if (this.isIE()) {
dragBtn.style.cssText = `left:${curDist}px;`;
dragDom.style.cssText = `flex:0 0 ${curDist}px;width:${curDist}px`;
dragCollDom.style.cssText = 'flex:0 0 0px;width:0px';
} else {
dragBtn.style.left = dragDom.style.width = curDist + 'px';
dragDom.style.flex = `0 0 ${curDist}px`;
dragCollDom.style.flex = '0 0 0px';
dragCollDom.style.width = '0px';
}
}

render() {
const { nodeClick, children, urlMatch,moreAction } = this.props;
return (
<Layout id="drag-content" >
<div id="collapse_sider" style={{ width: 0 }} >
<div id="collapse_sider_box">
<div className="base">组<br />织<br />架<br />构</div>
<Icon className="collapse_icon"
type="iconfont iconzhankai2"
onClick={() => this.setMaxValue(256)}
/>
</div>
</div>
<Sider id="drag-area" className="sider" >
<div className="whiteBox">
<TreeOrganize
type="sync"
urlMatch={urlMatch}
onTreeNodeClick={nodeClick}
setMinValue={this.setMinValue}
moreAction={moreAction}
/>
</div>
</Sider>
<div id="drag-tip" onMouseDown={this.MouseDown}>
<Icon className="drag_icon" type="iconfont icontuozhuai" />
</div>
<Layout style={{ paddingLeft: 24, overflowY: 'auto' }}>
<Content>
<Card bordered={false}>
{children}
</Card>
</Content>
</Layout>
</Layout>
);
}
}

样式

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
@import "src/scss/variables";
#drag-content {
position: relative;
height: calc(100vh - 180px);
background: none;
.ant-layout {
background: none;
}

/*鼠标移入显示可拖动样式*/
#drag-tip {
top: 0;
width: 24px;
left: 256px;
height: 100%;
position: absolute;
background-color: transparent;
z-index: 1000;
transition: all 0s;
.drag_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
font-size: 13px;
color: rgba(216, 216, 216, 1);
}
&:hover {
cursor: col-resize;
}
}

.sider {
box-shadow: none;
max-width: initial !important;
min-width: initial !important;
transition: all 0s;
background: rgba(238, 240, 243, 1);
.ant-layout-sider-children {
overflow: hidden;
}
}
#collapse_sider {
background: rgba(238, 240, 243, 1);
#collapse_sider_box {
position: relative;
height: 100%;
overflow: hidden;
}
.base {
position: absolute;
width: 100%;
top: 50%;
transform: translateY(-50%);
text-align: center;
}
.collapse_icon {
position: absolute;
width: 100%;
bottom: 10px;
text-align: center;
font-size: 12px;
color: #577ac7;
cursor: pointer;
}
}
.whiteBox {
width: 100%;
height: 100%;
padding: 0px 8px;
background-color: #eef0f3;
transition: width 0.3s;
overflow: hidden;
}
}

mac备忘录

mac开发软件

  1. Robo 3T

    免费mongodb数据库链接管理软件

  1. SwitchHost

    免费的hots编辑管理软件

  2. ClearviewX

    pdf阅读器, App store安装

  3. ApiPost6

    类似postman软件, 支持国产

  4. iTerm

    终端美化软件

  5. OmniGraffle

    图示/图表/流程图等绘制,破解版

  6. NTFS for Mac

    mac支持移动硬盘文件转移软件, 不过目前没有破解, 试用期有10天, 如还有需要继续购买

  1. Cisdem PDFMaster

    pdf拼接,转换等功能,不晓得好不好用

  2. Infuse(https://www.macwk.com/soft/infuse)

    视频播放器,用着还不错,可以记录播放历史,就是控制播放速度不太方便

glob用法

glob多用于路径匹配,具体用法和字符如下

1
2
3
4
5
const glob = require('glob');

glob('**/*.js', { ignore: ['node_modules/**',] }, function (err, file) {
console.log(err, file);
})

* 匹配任意 0 或多个任意字符
? 匹配任意一个字符
[...] 若字符在中括号中,则匹配。若以 ! 或 ^ 开头,若字符不在中括号中,则匹配
!(pattern|pattern|pattern) 不满足括号中的所有模式则匹配
?(pattern|pattern|pattern) 满足 0 或 1 括号中的模式则匹配
+(pattern|pattern|pattern) 满足 1 或 更多括号中的模式则匹配
*(a|b|c) 满足 0 或 更多括号中的模式则匹配
@(pattern|pat*|pat?erN) 满足 1 个括号中的模式则匹配
** 跨路径匹配任意字符