本地管理多个镜像npm源
安装nrm
:
npm install nrm -g --save
查看现有源:
执行命令:nrm ls
npm -------- https://registry.npmjs.org/
yarn ------- https://registry.yarnpkg.com/
cnpm ------- http://r.cnpmjs.org/
taobao ----- https://registry.npm.taobao.org/
nj --------- https://registry.nodejitsu.com/
npmMirror -- https://skimdb.npmjs.com/registry/
edunpm ----- http://registry.enpmjs.org/
切换源:nrm use cnpm
使用nrm add
添加公司的私有源:
nrm add xxxx https://xxxx.xx.xx.com/
组件二次封装思路
封装弹窗
同时兼顾代码量和调用方便的方式是使用函数实现调用
比如像element-plus
的信息弹窗,支持通过this.$message(options)
或this.$confirm(options)
的方式调用
对于开发中的业务类弹窗,也可以基于这个思想封装出一个函数并导出使用
拿react
举例就是:
import { Modal } from 'antd';
import { useState } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import styles from './index.less';
import { CloseCircleOutlined } from '@ant-design/icons';
import { SUNGENT_IMAGE } from '@/constants/images';
const createDivAndAppend = () => {
const div = document.createElement('div');
div.style.display = 'none'; // 让这个div不要引起页面的重绘和重排
document.body.appendChild(div);
return div;
};
const destroyModal = (ele: Element) => {
unmountComponentAtNode(ele); // 及时销毁react组件
document.body.removeChild(ele); // 及时销毁dom节点
};
interface ModalHeaderConfig {
title: string;
onClose?: () => void;
showInfoIcon?: boolean;
}
interface ModalConfigs extends Pick<ModalHeaderConfig, 'title'> {
subTitle?: string | (() => JSX.Element);
imgUrl?: string;
content: string;
afterClose?: () => void;
}
const ModalHeader: React.FC<ModalHeaderConfig> = ({
title,
onClose,
showInfoIcon = true,
}) => {
return (
<div className={styles.title}>
{showInfoIcon && (
<img
className={styles['info-icon']}
src={SUNGENT_IMAGE.EVENT}
alt={title}
/>
)}
<div>{title}</div>
<CloseCircleOutlined
className={styles.icon}
onClick={onClose}
style={{ color: '#0bd6e2' }}
/>
</div>
);
};
const InfoModal: React.FC<ModalConfigs> = (props) => {
const { title, afterClose, subTitle, content, imgUrl } = props;
const [modalIsOpen, setModalIsOpen] = useState(true);
const handleClose = () => {
setModalIsOpen(false);
};
const subTitleJsx = subTitle
? typeof subTitle === 'function'
? subTitle()
: subTitle
: undefined;
return (
<Modal
classNames={{
header: styles.header,
body: styles.body,
wrapper: styles.wrapper,
}}
afterClose={afterClose}
open={modalIsOpen}
footer={null}
title={<ModalHeader onClose={handleClose} title={title} />}
onClose={handleClose}
closeIcon={null}
width={877}
>
{subTitleJsx && <div className={styles.subtitle}>{subTitleJsx}</div>}
<div className={styles.content}>
{imgUrl && <img className={styles.img} src={imgUrl} alt={title} />}
<div>{content}</div>
</div>
</Modal>
);
};
const renderModal = (configs: ModalConfigs) => { // 导出函数而不是导出函数组件
const { afterClose, ...rest } = configs;
const ele = createDivAndAppend(); // 这里则创建一个div元素并怼到body上,同时把该div元素设为`display:none`即可
render( // 核心在此,通过react的render方法把组件挂载到自己创建的div元素上
<InfoModal
{...rest}
afterClose={() => {
afterClose?.();
destroyModal(ele);
}}
/>,
ele,
);
};
export default renderModal;
react - ahooks库
useRequest
useRequest
同时暴露出数据、请求与loading
(要找时间看看人家是怎么封装这个自定义
hook
的)
useDebounce
最常用的就是控制输入框的关键字输入防抖,向上抛出防抖的关键字来控制搜索
useUpdateEffect
使用它可以声明一个仅在依赖项更新时才调用的副作用
useEffect
和useLayoutEffect
都必定会在组件第一次渲染时调用一次,相当于是vue
里的watch
配置了immediate
,所以需要一个真正意义上的 “普通的watch
”,即useUpdateEffect