沙雕爹爹

Stay foolish, stay humble.


  • Home

  • Archives

5个避免react-hooks坑的技巧

Posted on 2019-08-13

5个避免react-hooks坑的技巧

  1. 阅读官网的FAQ
  2. 下载和使用 hooks 的 ESLint 插件
  3. 不要用生命周期的逻辑去思考,用副作用是同步修改state的逻辑去思考
  4. 明白 react 很快,在做不成熟的性能优化前做些深挖
  5. 避免过度测试,没必要测得太细节

第一篇 Hexo使用说明

Posted on 2019-08-13

Hexo的使用说明,包括一些常用命令。

开发流程

初始化项目

全局安装hexo-cli:npm install -g hexo-cli
生成项目:hexo init <folder name>
进入文件目录并初始化:cd <folder name> && yarn/npm i

维护

拉仓库代码 git clone git@github.com:buptlyz/blog.git
进入文件目录并初始化 cd blog && yarn 或者 cd blog && npm install

Hexo常用命令

创建新的post

1
$ hexo new "我的新post"

更多信息: 写作

启动服务

1
$ hexo server

更多信息: 服务

生成静态文件

1
$ hexo generate

更多信息: 生成

部署到远程站点

1
$ hexo deploy

更多信息: 部署

TypeScript Module Resolution(译)

Posted on 2019-06-01

原文地址

tsconfig.json Compiler Options(译)

Posted on 2019-05-29

原文地址

Option Type Default Description
–allowJs boolean false 允许编译Javascript文件
–allowSyntheticDefaultImports boolean module === ‘system’ 或者 –esModuleInterop 允许在没有default export的时候从modules中default import。这不影响代码输出,只影响类型检查

tsconfig.json(译)

Posted on 2019-05-29

原文地址

tsconfig.json文件通常放在工程根目录下,用来定义编译的配置。

使用

  • 不提供任何输入文件的配置,直接调用tsc,compiler会找tsconfig.json,从当前文件夹开始,找不到就往父目录找。
  • 不提供任何输入文件的配置,使用—project或者-p,调用tsc,指定一个包含tsconfig.json文件的文件夹路径,或者一个包含配置信息的合法.json文件的路径。

如果指定了输入文件,那么tsconfig.json文件会被忽略。

示例

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
// 使用 file
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": [
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts"
]
}

// 使用 include 和 exclude
{
"compilerOptions": {
"module": "system",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outFile": "../../built/local/tsc.js",
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}

细节

compilerOptions可以忽略,compiler会使用默认配置。Compiler Options

files接收一组相对/绝对路径。include/exclude接受一组glob-like file pattern。支持的glob通配符如下:

  • *匹配0或多个字符(除了文件夹分隔符)
  • ?匹配任意1个字符(除了文件夹分隔符)
  • **/递归匹配任意子目录

如果某glob pattern只包含*/.*,那么默认包含的文件为所有扩展名为.ts/.tsx/.d.ts的文件。(如果allowJs为true,那么扩展名为.js/.jsx的文件也被包含在内)

如果files/include都没有指定值,那么compiler默认包含文件夹/子文件夹下的所有TypeScript文件。(扩展名为.ts/.tsx/.d.ts的文件。如果allowJs为true,那么扩展名为.js/.jsx的文件也被包含在内)

exclude可以过滤掉include指定的文件,但不能过滤掉files指定的文件。如果exclude没有指定值,默认包含node_modules/bower_components/jspm_packages/<outDir>。

被包含的文件引用的文件,也被包含在内,不会被exclude过滤掉,除非引用它的文件被过滤掉了。

compiler会过滤掉那些可能成为输出文件的输入文件。例如,同一目录下同时有[name].ts/[name].d.ts/[name].js,那么[name].d.ts/[name].js会被忽略。

tsconfig.json可以是一个空文件,compiler会使用默认配置。

@types,typeRoots和types

默认情况下,只有@types目录下的包会被包含在compilation里。例如,./node_modules/@types/../node_modules/@types/../../node_modules/@types。

如果指定了typeRoots的值,那么只有typeRoots目录下的包会被包含进来。

例如:

1
2
3
4
5
{
"compilerOptions": {
"typeRoots": ["./typings"]
}
}

只有./typings目录下的包会被包含进来,./node_modules/@types目录下的包不会被包含进来。

如果指定了types的值,那么只有列举出来的包会被包含进来。

1
2
3
4
5
{
"compilerOptions": {
"types": ["node", "lodash", "express"]
}
}

只有./node_modules/@types/node/./node_modules/@types/lodash/./node_modules/@types/express会被包含进来,其它./node_modules/@types/*目录下的包不会被包含进来。

指定types值为[],将会自动过滤所有@types包。

使用extends继承配置文件

例如:

configs/base.json

1
2
3
4
5
6
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true
}
}

tsconfig.json

1
2
3
4
5
6
7
{
"extends": "./configs/base",
"files": [
"main.ts",
"supplemental.ts"
]
}

tsconfig.nostrictnull.json

1
2
3
4
5
6
{
"extends": "./configs/base",
"compilerOptions": {
"strictNullChecks": false
}
}

compileOnSave

告诉IDE,在保存文件的时候使用给定的tsconfig.json处理所有的文件。

1
2
3
4
5
6
{
"compileOnSave": true,
"compilerOptions": {
"noImplicitAny": true
}
}

Schema

单点登录SSO

Posted on 2019-05-18

article

移动端适配

Posted on 2019-05-18

article

flex布局

Posted on 2019-05-18

概念

  • 主轴
  • 垂直轴

  • flex container

  • flex item

默认行为

flex item的默认行为:

  • 按行排列 flex-direction: row;
  • 沿着主轴起始边界开始排列 justify-content: flex-start;
  • 主轴方向不会膨胀,但会缩小 flex-grow: 0; flex-shrink: 1; flex-basis: auto;
  • 垂直轴会膨胀填满空间 align-items: stretch;
  • flex-basis: auto;
  • flex-wrap: nowrap;

属性默认值,可选值

flex container

  • flex-direction: row;
  • flex-wrap: nowrap; (wrap)
  • align-items: stretch; (flex-start, flex-end, center)
  • justify-content: flex-start; (flex-end, center, space-around, space-between, space-evenly)

flex item

  • flex-basis: auto; (inherit, initial, unset)
  • flex: initial; (= 0 1 auto) (auto = 1 1 auto, none = 0 0 auto)

array-prototype-reduce

Posted on 2019-05-18

reduce方法对数组中的每个元素执行一个由我们定义的reducer函数(升序执行),将其结果汇总为单个返回值。

reducer函数接收4个参数:

  1. Accumulator(acc)(累计器)
  2. Current Value(cur)(当前值)
  3. Current Index(idx)(当前索引)
  4. Source Array(src)(源数组)

polyfill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Array.prototype.reduce = function(callback) {
var arr = this, len = arr.length;
var idx = 0, value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while(idx < len && !(idx in arr)) {
idx++;
}
if (idx >= len) {
throw new TypeError('empty array');
}
value = arr[idx++];
}
while(idx < len) {
if (idx in arr) {
value = callback(value, arr[idx], idx, arr);
}
idx++;
}
return value;
};

示例

按顺序执行Promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Runs Promise from array of functions that can return promises in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFn) => promiseChain.then(currentFn),
Promise.resolve(input)
);
}

runPromiseInSequence([getUser, getAuth, getData], {});

功能型函数管道

1
2
3
4
5
6
7
8
9
10
11
12
13
var double = x => x*2
var triple = x => x*3
var quadruple = x => x*4

var pipe = (...fns) => input => fns.reduce(
(acc, fn) => fn(acc),
input
);

var multiply6 = pipe(double, triple);
var multiply9 = pipe(triple, triple);
var multiply16 = pipe(quadruple, quadruple);
var multiply24 = pipe(quadruple, multiply6);

函数式编程第二章——高阶JavaScript

Posted on 2019-05-17

2.1 为什么要使用JavaScript

2.2 函数式与面向对象的程序设计

面向对象的应用程序大多是命令式的,因此在很大程度上依赖于使用基于对象的封装来保护其自身和继承的可变状态的完整性,再通过实例方法来暴露或修改这些状态。

其结果是,对象的数据与其具体的行为以一种内聚的包裹的形式紧耦合在一起。

函数式编程不需要对调用者隐藏数据,通常使用一些更小且非常简单的数据类型。由于一切都是不可变的,对象都是可以直接拿来使用的,而且是通过定义在对象作用域外的函数来实现的。

换句话说,数据与行为是松耦合的。

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
class Person {
constructor(firstname, lastname, ssn) {
this._firstname = firstname;
this._lastname = lastname;
this._ssn = ssn;
this._address = null;
this._birthYear = null;
}

get ssn() {
return this._ssn;
}

get firstname() {
return this._firstname;
}

get lastname() {
return this._lastname;
}

get address() {
return this._address;
}

get birthYear() {
return this._birthYear;
}

set birthYear(year) {
this._birthYear = year;
}

set address(address) {
this._address = address;
}

toString() {
return `Person(${this._firstname}, ${this._lastname})`;
}

peopleInSameCountry(friends) {
var result = [];
for (let friend of friends) {
if (this.address.country === friend.address.country) {
result.push(friend);
}
}
return result;
}
}

class Student extends Person {
constructor(firstname, lastname, ssn, school) {
super(firstname, lastname, ssn);
this._school = school;
}

get school() {
return this._school;
}

studentInSameCountryAndSchool(friends) {
var closeFriends = super.peopleInSameCountry(friends);
var result = [];
for (let friend of closeFriends) {
if (friend._school === this._school) {
result.push(friend);
}
}
return result;
}
}

函数式

1
2
3
4
5
6
7
8
9
10
function selector(country, school) {
return function(student) {
return student.address.country() === country &&
student.school() === school;
}
}
function findStudentsBy(friends, selector) {
return friends.filter(selector);
}
findStudentsBy([...], selector('China', 'BUPT'));
12…6

沙雕爹爹

Personal tech blog.

55 posts
45 tags
© 2019 沙雕爹爹
Powered by Hexo
|
Theme — NexT.Muse v5.1.4