0%

React tips collection

Actrually they are some snippets in case of forgetting.

  1. 组件声明
1
2
3
4
5
6
7
8
9
10
11
 //纯组件
const eg1 = ({msg}:{message:string})=><div>{msg}</div>
//SFC
const eg2: React.SFC<Msg>=({message,children})=><div>{children}}</div>
//class
class Eg extends React.Component<PropsType,StateType>{
// const {message = 'default'} = this.props; for function component
static defaultProps: Partial<PropsType>={
key: value
}
}
  1. 函数组件的默认属性
1
2
3
4
5
6
7
8
type Props = { age: number } & typeof defaultProps;
const defaultProps = {
who: "Johny Five",
};
const Greet = (props: Props) => {
/*...*/
};
Greet.defaultProps = defaultProps;
  1. class 组件
1
2
3
4
5
6
7
8
9
10
type State = typeof initialState;
type Props = { someProps: string } & typeof defaultProps;

const initialState = { count: 0 };
const defaultProps = { who: "Nico" };

class Greet extends React.Component<GreetProps> {
static defaultProps = defaultProps;
/*...*/
}
  1. ref 的 typescript 写法
1
2
3
4
5
6
class CssThemeProvider extends React.PureComponent<Props> {
private rootRef: React.RefObject<HTMLDivElement> = React.createRef();
render() {
return <div ref={this.rootRef}>{this.props.children}</div>;
}
}
  1. create-react-app my-project --use-npm 选定使用 npm.
  2. 联合类型声明,对于原始类型,ts 可以自动识别
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
interface Bird {
fly();
layEggs();
}

interface Fish {
swim();
layEggs();
}

function getSmallPet(): Fish | Bird {
// ...断言
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
} else {
(<Bird>pet).fly();
}
}
//自定义
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
  1. 使用 tabIndex 可以控制 TAB 光标选中
  2. 默认设置组件不加载
1
2
3
4
5
6
7
const MessageBox = ({ open, text, buttons }) =>
open ? (
<div>
{text}
{buttons(Button)}
</div>
) : null;
  1. 高阶组件的 ts 写法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from "react";

function wrapPicker<T>(Component: React.ComponentType<T>) {
return class extends React.Component {
componentWillReceiveProps(
nextProps: React.ComponentProps<typeof Component>
) {}

render() {
const props = this.props;
return <Component {...(props as T)} />;
}
};
}

export default wrapPicker;
  1. 对于有底部 border 的 input 在 hover 时 border 的 width 变化,行高可能会出现变化,解决: _ 在其父级加入 after 伪类做 border-bottom,不要用 input 的 border,另外 input 加伪类不生效. _
  2. less 有关
1
2
3
4
5
6
7
8
width: ~calc(100px - 20px) // ~意思是避免编译
@selectors: primary, secondary, tertiary,black,gray;
each(@selectors,{
.@{value}-color{
@cur-color: '@{value}-color';
color: @@cur-color;
}
})
  1. 窗口的滚动
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
滚动的高度 = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
//兼容性的话,可以使用document.scrollingElement.scrollTop

窗口的高度 = window.innerHeight || document.documentElement.clientHeight;
//普通元素的高度获取:clientHeight 是不包含border-box, offsetHeight包含边框
scrollHeight,getBoundingClientRect().height

document.documentElement.offsetHeight居然是包含浏览器滚动高度的完整高度,

feature: // 平滑滚动: html, body { scroll-behavior:smooth; }

手动平滑 记住一个formula: A = A + (B-A)/(RATE||2)
Math.easeout = function (A, B, rate, callback) {
if (A == B || typeof A != 'number') {
return;
}
B = B || 0;
rate = rate || 2;

var step = function () {
A = A + (B - A) / rate;

if (A < 1) {
callback(B, true);
return;
}
callback(A, false);
requestAnimationFrame(step);
};
step();
};
  1. 防抖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Throttle(fn, delay) {
let last = 0,
timer = null;
return function () {
let context = this,
args = arguments,
now = +new Date();
if (now - last < delay) {
clearTimeout(timer);
timer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, delay);
} else {
last = now;
fn.apply(context, args);
}
};
}
  1. 直接获取表单 dom: document.forms['loginForm']
  2. 获取类似 get 的格式化语句
1
2
3
4
5
6
7
8
9
Object.entries(object1)
.map((kv) => `${kv[0]}=${encodeURIComponent(kv[1])}`)
.join("&");
//解析
var urlSearchParams = new URLSearchParams(urlString);
var urlObj = {};
for (let [key, value] of urlSearchParams.entries()) {
urlObj[key] = value;
}
  1. React-transition-group 使用方法,css-transition 第一次调用,使用的类是 appear,后面几次才会使用 enter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//首先,transition是基础,他可以吐出四个不同的状态'entering'|entered|exiting|exited
//unmountOnExit 这个属性可以控制dom节点要不要unmount,就是document上需不需要
// cssTransition 是通过样式控制在不同的状态显示的样式动画,所以classnames是一个需要定义的属性,其和css是相关联的
//着重说一下怎么样和animation.css结合
<cssTransition
in={state}
classNames={{
enter: "animated",
enterActive: "rubberBand",
exit: "animated",
exitActive: "slideOutRight",
}}
>
<div>...</div>
</cssTransition>
  1. 命名方式: camelCase, PascalCase, kebab-case
  2. 深层过滤器
1
2
3
4
5
6
7
var res = input.filter(function f(o) {
if (o.value.includes("Hit")) return true;

if (o.children) {
return (o.children = o.children.filter(f)).length;
}
});
  1. 几种类型的操作:

  2. Exclude 排除
    Exclude<keyof Props, keyof ExtractName> extractName 为想要排除掉的 props

  3. Pick为只选用其中的一些属性

    Pick<User,"name"|"age"> 只选用 name 和 age 这两个属性

  4. 复制文本并选中 textarea$.select(); document.execCommand('copy');

  5. bind,call,apply

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
    var car = {
registrationNumber: "GA12345",
brand: "Toyota",
displayDetails: function(){
console.log(this.registrationNumber + " " + this.brand);
}
}

// 1. bind 将会创建一个重新绑定this的函数

const myCarDetail = car.displayDetails; //这样的myCarDetail在调用时内部的this指向window
const myCarDetailWithBind = car.displayDetails.bind(car); //重新指定了this为car
const myCarDetailBindParam = car.displayDetails.bind(car,args); //需要传参的情况

// 2. call and apply

var car = {
registrationNumber: "GA12345",
brand: "Toyota"
}

function displayDetails(ownerName) {
console.log(ownerName + ", this is your car: " + this.registrationNumber + " " + this.brand);
}
displayDetails.call(car,'nico')
displayDetails.apply(car,['nico'])
```

bind主要用于以一个指定的值做为一个函数的value.并没有执行,还可以借用和复用一个方法,
或者给一个方法赋给一个变量
call,apply 第一个参数用于设置this, 后面的值作为参数传入函数,也可以借用函数,
方式更多样化.(类数组可以借用Array.prototype的方法,还有函数的参数arguments)
  1. 一些 ts 的片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// variables
const variableName: varType;
const name: string;
const disabled: boolean;

// functions (and function variables)
function funcName(arg1: argType, arg2: argType): returnType {}
const funcName: (arg1: argType) => returnType;
function split(str: string, delim: string): string[] {}
function map<T, U>(array: T[], iterator: (item: T, index: number) => U): U[];

// interfaces describe plain objects
// (we use the convention that interfaces begin with "I")
interface IOption {
label: string;
value: string;
}
const option: IOption = { label: "Name", value: "Gilad" };
  1. 函数的安全调用
1
2
3
4
5
6
export function safeInvoke(func: Function | undefined, ...args: any[]) {
if (isFunction(func)) {
return func(...args);
}
return undefined;
}
  1. export 的一些用法
1
2
3
4
5
6
7
8
9
10
11
12
// some var
export default someVar = 123;

// some function
export default function someFunction() {}

// some class
export default class someClass {}

export default { module1, module2, module3 };

import * as all from "./test";
  1. 一款工具可以监听文件变化,并重启服务器: nodemon

  2. 对象转化为字面量类型: keyof typeof Type

  3. webpack 使用小结

  4. 配置 config

  5. tsconfig. 这里遇到 moment 无法识别: 添加配置:
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,

  6. 如果要导出声明文件需配置
    //tsconfig "declaration": true
    //package.json tsc --emitDeclarationOnly

  7. 对于打包的声明文件有两种形式,一个是单独发一个包名@types/package_name,里面只有声明文件.另一种形式就是与包一起发,index.js 并列一个 index.d.ts.

  8. key 在渲染时如果每次都跟着变,就会重复渲染,会有性能问题,注意既要保持 key 唯一,也要保证其不会一直刷新

  9. ts 当中 key in 和 key of

1
2
3
4
5
6
7
8
9
10
type key = "vue" | "react";

type MappedType = { [k in key]: string }; // { vue: string; react: string; }

interface Student {
name: string;
age: number;
}

type studentKey = keyof Student; // "name" | "age"
  1. 如何使用 git reset: https://www.codenong.com/cs105557977/
  2. get all export var from current folder, import * as _adapter from "./data" ;
  3. process.argv 返回一个数组,这个数组包含了启动 Node.js 进程时的命令行参数。
  4. Array.from({ length: 2 }, () => 'jack') 生成数组 或者 new Array(9).fill('item')
  5. .show-grid [class*="span"] 类似于正则匹配
  6. 只要一个匹配成功,后面就不管了,可以这样用:
1
2
3
4
let diffed = false;
const activated = matched.filter((c, i) => {
return diffed || (diffed = prevMatched[i] !== c);
});
  1. 导入后紧接着又导出去
1
2
3
4
5
6
import App from "./App";

export default App;

//可以一句话
export { default as App } from "./App.js";