前端开发冷门小技巧 (持续更新...)
#react #interview #javascript
jerrywu001
创建时间:2023-09-05 05:57:56
React中实现vue的computed
const [message, setMessage] = useState('hello');
// computed state
const reversedMessage = useMemo(() => message.split('').reverse().join(''), [message]);
React class component 中使用导航事件
react-router@v5
import { Component } from 'react'; // react17不需要导入react
import { RouteComponentProps } from 'react-router';
interface IProp extends RouteComponentProps {
name: string;
}
export default class Test extends Component<IProp> {
constructor(props: IProp) {
super(props);
this.goToNextPage = this.goToNextPage.bind(this);
}
goToNextPage() {
this.props.history.push('/xxx'); // 这里ts可以做到自动推导
}
render() {
return <div onClick={this.goToNextPage}>test</div>
}
}
react-router@v6
做不到直接使用,不做可以间接使用
import Home from '@/views/home/Home';
import { useEffect } from 'react';
import mitt, { Emitter, EventType } from 'mitt';
import {
NavigateOptions,
To,
useLocation,
useNavigationType,
} from 'react-router';
import {
HashRouter as Router,
Route,
Routes,
Navigate,
useNavigate,
} from 'react-router-dom';
const Msg: Emitter<Record<EventType, any>> = mitt();
// 这里还可以直接定义个变量,将useNavigate()赋值给它,然后export进行使用
// https://reactrouter.com/docs/en/v6
function AppRoutes() {
return (
<Routes>
<Route path="/" element={<Navigate to="/home" replace />} />
<Route path="home" element={<Home />} />
<Route path="*" element={<NoMatchPage />} />
</Routes>
);
}
export default function App() {
return (
<Router>
<AppContainer />
</Router>
);
}
function AppContainer() {
const navigate = useNavigate();
const location = useLocation();
const action = useNavigationType();
useEffect(() => {
Msg.on('navigate::push', ({ to, options = {} }: { to: To; options?: NavigateOptions; }) => {
navigate(to, { ...options, ...{ replace: false } });
});
Msg.on('navigate::back', () => {
navigate(-1);
});
Msg.on('navigate::replace', ({ to, options = {} }: { to: To; options?: NavigateOptions; }) => {
navigate(to, { ...options, ...{ replace: true } });
});
}, []);
useEffect(() => {
const { pathname = '', search = '' } = location;
console.log(`navigate change: ${action}, url: ${pathname}${search}`);
});
return <AppRoutes />;
}
export function Push<State>(to: To, state?: State) {
Msg.emit('navigate::push', { to, options: { state } });
}
export function Back() {
Msg.emit('navigate::back');
}
export function Replace<State>(to: To, state?: State) {
Msg.emit('navigate::replace', { to, options: { state } });
}
// useage
import { Component } from 'react'; // react17不需要导入react
interface IProp {
name: string;
}
export default class Test extends Component<IProp> {
constructor(props: IProp) {
super(props);
this.goToNextPage = this.goToNextPage.bind(this);
}
goToNextPage() {
Push('/xxx', { iAmState: { xx: 'hello' } });
}
render() {
return <div onClick={this.goToNextPage}>test</div>
}
}
usePreviousProps
function usePreviousProps(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
// useage
function Test(props) {
const preProps = usePreviousProps(props);
}
继承html attributes
import { HTMLAttributes } from 'react';
interface IAAAProp extends HTMLAttributes<JSX.Element> {
/** 姓名 */
name: string;
}
export default function AAA({ name, id, className, style, children }: IAAAProp) {
return (
<div>test</div>
)
}
快速查看react属性类型定义
举个例子,经常使用 const xxx = useRef
(); 中的泛型T怎么写??
直接hover查看即可
// useage
import { MouseEvent } from 'react';
const Test = () => {
function doClick(e: MouseEvent<HTMLDivElement>) {
e.stopPropagation();
}
return (
<div onClick={doClick}>test click</div>
);
};
使用hooks实现下拉加载下一页数据
文档注释规范
获取二月份天数
// 方案1:
// 判断闰年
// https://blog.csdn.net/td939155634/article/details/114654346
// 方案2:
new Date(new Date().getFullYear(), 3, -31).getDate()
// 方案3:
function getFebruaryDays(year = new Date().getFullYear()) {
const date = new Date(year, 1, 29).getDate();
return date !== 29 ? 28 : date;
}
平滑滚动效果
兼容性:Can I use... Support tables for HTML5, CSS3, etc
- css
scroll-behavior - CSS(层叠样式表) | MDN
- js
Window.scroll() - Web API 接口参考 | MDN
domXXX.scroll({ top: 100, behavior: 'smooth' });
js实现数组扁平化
[1,2, [3,4,[5,6]]].toString().split(',');
// or
[1,2, [3,4,[5,6]]].join(',').split(',');
// or es6
[1,2, [3,4,[5,6]]].flat(Infinity);
请求体中的undefined参数会被浏览器自动抛弃
const xxx = 1;
const queryParam = {
userId: 'A001',
age: xxx !== 1 ? xxx : undefined,
};
XxxService.queryUsers(queryParam);
// 这意味着我们不需要通过delete或者if判断去手动增加或删除age参数
// 因为age === undefined时,age参数会自动被浏览器丢弃
// 去浏览器network中可以看到请求参数: { userId: 'A001' }
webpack魔法注释
动态加载异步组件时可以使用魔法注释
// build之后chunk文件名不再是数字,而是Test.min.[hash].js
// webpackPrefetch:浏览器空闲时候才会加载对应脚本,并缓存
// webpackPreload:浏览器会异步加载对应脚本,并缓存
const Test = loadable(() => import('./xxx/xxx/Test.tsx'/* webpackChunkName: 'Test', webpackPrefetch: true */));
module.(less/scss)中使用普通class
import styles from './Test.module.scss';
function Test() {
return <div className={`${styles.demo} normal-a normal-b`}>test</div>
}
.demo { font-size: 12px; }
(:global)(.noraml-a) {
cursor: pointer;
}
:global {
.normal-b {
border: 1px #ddd solid;
}
}
特殊场景不让postcss-to-rem将px转成rem
.auto-to-rem {
font-size: 12px; /* 会被自动转换 */
}
.not-to-rem {
font-size: 12PX; /* 不会被自动转换,只要一个字母大写即可跳过转换 */
}
判断数据类型
async function AA {}
const a = Promise.resolve()
Object.prototype.toString.call(Symbol('')) // [object Symbol]
Object.prototype.toString.call(AA) // [object AsyncFunction]
Object.prototype.toString.call(a) // [object Promise]
// ...
// TIPS: class 的实例化对象请使用instanceof (传入class本身会返回function)
快速Float转Integer
console.log(23.9 | 0); // Result: 23
快速向下取整
~~12.8 // 12
原生方法创建36位随机数
URL.createObjectURL(new Blob()).substr(-36)
从整数的末尾删除任意数量的数字
// 删除1位
console.log(1221 / 10 | 0) // Result: 122
// 删除2位
console.log(1221 / 100 | 0) // Result: 12
// 删除3位
console.log(1221 / 1000 | 0) // Result: 1
json使用缩进格式化
console.log(JSON.stringify({ a: { b: 'hello' }}, null, 2));
console.log(JSON.stringify({ a: { b: 'hello' }}, null, '\t'));
图片转矢量图
图片优化
react 动画库
react 使用immer管理不可变数据
一种简单的方式管理mono repo
配置参考:https://classic.yarnpkg.com/en/docs/workspaces/
TIPS: 如果使用pnpm,需要添加pnpm-workspace.yaml
packages:
- workspace name
- pnpm使用方式
pnpm run --filter=[workspace name] dev
- npm/yarn使用方式:
npm run [script] --workspace=[workspace name]
# or
npm run [script] --workspace [workspace name]
# or
npm -C [workspace name] run [script]
# or
yarn workspace [workspace name] run [script]