1.使用@引用路径
当我们引用一个工具类的方法,如果你的页面层层嵌套,那么你就可能要一直../../../
甚至还会找错路径,但是我们开发时候多数是在src
目录下做文章,我可以配置一个@作为src目录的别称
在根目录下:创建一个config-overrides.js
const { override, addWebpackAlias, fixBabelImports, addLessLoader, addDecoratorsLegacy } = require('customize-cra');
const path = require('path')
module.exports = override(
fixBabelImports('antd-mobile', {
style: true
}),
fixBabelImports('antd', {
libraryDirectory: 'es',
style: true
}),
addLessLoader({
javascriptEnabled: true,
}),
addDecoratorsLegacy(),
addWebpackAlias({
"@": path.resolve(__dirname, "src")
}),
);
在package.json
或者tsconfig.json
文件中添加:
"paths": {
"@/*": [
"./src/*"
]
},
如果在tsconfig
中重新运行文件,这句被自动删除的话
解决方法:
新建文件,并引入到tsconfig.json
文件中
// path.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
// tsconfig.json
"extends": "./path.json",
参考文章
在页面中使用:
import tools from "@/lib";
2.引入多个UI库
在config-overrides.js
中,使用fixBabelImports
引入antd
和antd-mobile
antd-mobile引入方式
const { override, fixBabelImports } = require('customize-cra');
const path = require('path')
module.exports = override(
fixBabelImports('antd-mobile', {
style: true
}),
fixBabelImports('antd', {
libraryDirectory: 'es',
style: true
}),
...
);
// .babelrc文件配置,引入UI库
{
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css" // `style: true` 会加载 less 文件
}
],
[
"import",
{
"libraryName": "antd-mobile",
"style": "css"
}
] // `style: true` 会加载 less 文件
]
}
设置组件使用的语言,可以在入口函数中使用:
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
3.使用less和关闭source-map
- 安装
yarn add less less-loader -D
//或者
yarn add less less-loader --save-dev
在config-overrides.js
中的设置如1中所示
当我们打包时,不想要很多map文件,则可以选择不要,配置如下
process.env.GENERATE_SOURCEMAP = "false";
4. 页面缓存方式
当我们从一个页面点击详情,跳转到另一个页面再返回时,我们像保留上次页面的状态,但是很遗憾,在react中会重新刷新一遍页面,并不会保留,但是在vue中,就支持<keep-alive><Component/><keep-alive>,来保持缓存组件(页面)
不过react中需要自己配置,官方暂时没有提供页面缓存的机制,理由是避免内存泄漏。。。
我们就先采用大神写的react-keep-alive
github地址
(1)先引入Provider
// index.js
import { Provider } from 'react-keep-alive';
ReactDOM.render(<Provider> <App /> </Provider>,
document.getElementById('root'));
(2)包裹组件
// App.js
import { KeepAlive } from 'react-keep-alive';
...
<Route path="/calendar/:userId" render={
({ match, history }) => {
return (
<KeepAlive name="Calendar">
<Calendar match={match} history={history} />
</KeepAlive>
)
}
}>
</Route>
被KeepAlive包裹的组件就是要缓存的页面,需要注意的是,像<Calendar>组件属于子组件,没有权利访问到路由,所以就无法做到跳转,需要由当前页面,传递match(用于获取匹配参数), history获取路由信息,跳转路由等等。这样在子组件中就可以正常使用this.props.history.push('....')
接下去在Provider中定义需要被包含加载缓存的地方:
// index.js
import { Provider } from 'react-keep-alive';
ReactDOM.render(<Provider includes={["Calendar"]}> <App /> </Provider>,
document.getElementById('root'));
多个页面需要缓存,则以数组的方式设置
(3)生命周期
-
componentDidActivate
在组件刚挂载或从未激活状态变为激活状态时执行
返回到当前页面,componetnDidMount不会执行,但是这个地方会被执行 -
componentWillUnactivate
离开该页面时候会执行,此时的componentWillUnmount无法使用,除非禁用缓存
具体使用:
import { bindLifecycle } from 'react-keep-alive';
@bindLifecycle
class Calendar extends Component {
...
componentDidActivate () {
console.log("come")
}
componentWillUnactivate () {
console.log("leave")
}
}
(4)装饰器支持
如果不出意外的话,会报错:
Support for the experimental syntax 'decorators-legacy' isn't currently enabled
那是因为没有配置支持装饰器的环境,配置方式如下:
先安装:
yarn add @babel/plugin-proposal-decorators
// or
npm install @babel/plugin-proposal-decorators
在.babelrc中配置:
{
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
]
],
"presets": [
"react-app"
]
}
进过一顿操作,最好还是重启一下。
经过实践发现页面缓存,并不会缓存上次滚动条滑动的位置,还需要缓存数据到本地。
4. 前端图片压缩(iOS图片旋转问题)
移动端拍照上传,或者图片选择上传,往往会因为图片太大,造成上传服务器缓慢,用户体验很不好,那么我们可以选择压缩,当压缩完成之后,开开心心掏出手机测试,结果。。。凉了,竖着拍,图片旋转了。
在网上发现一篇很不错的文章,介绍得很详细传送门
那就一起搞
- file类型转为base64
export function turnToBase64(file, callback) {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function () {
let image = e.target.result; // image就是转成的base64
callback(image)
}
}
- base64转为file
使用atob()方法解码 使用base64编码的字符串
export function turnToFile(dataurl, filename) { //将base64转换为文件
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
- 获取ios照片选择方向的方法
通过第三方库exif-js
来获取图片的旋转方向信息,这样我们就可以调整到正常的位置
下载:
npm install exif-js -D
代码:
import Exif from 'exif-js';
export const getImageTag = (file, tag) => {
if (!file) return 0;
return new Promise((resolve, reject) => {
Exif.getData(file, function () {
const o = Exif.getTag(this, tag);
resolve(o);
});
});
};
const or = await getImageTag(file, 'Orientation');
- 判断是否支持base64图片压缩
if (typeof(FileReader) === 'undefined') {
turnToBase64(file, callback);
return
}
- 使用canvas画图压缩
需要注意的是,当按比例显示图片时,width的值会大于height,如果竖着拍,要用height和屏幕宽度screenwidth做比较,因为默认图片是顺时针旋转90度的。
5.代理配置与打包
如果只有一个代理,则最简单,在package.json中配置:
"proxy": "http://abc.com/test"
如果有多个代理,由于最新版本的react-router-script
>= 4的proxy配置仅支持字符串,那么我们需要用到http代理中间件:http-proxy-middleware
安装方式:
yarn add http-proxy-middleware -D
// or
npm install http-proxy-middleware --save-dev
在src目录下创建一个setProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
createProxyMiddleware('/test', {
target: 'http://192.168.2.1:8088',
changeOrigin: true,
})
);
app.use(
createProxyMiddleware('/api', {
target: 'http://192.168.2.2:8088',
changeOrigin: true,
pathRewrite: {
'/api': ''
}
})
);
};
解释:
(1)当api请求匹配到有/test的,指定代理到http://192.168.2.1:8088的地址,并拼接到后面,
假如请求是:/test/getList
,那么实际上是请求:
http://192.168.2.1:8088/test/getList
(2)当api请求匹配到有/api的,指定代理到http://192.168.2.2:8088
的地址,使用pathRewrite: { '/api': '' }
,表示重写,将/api替换成空的字符串
假如请求是: /api/project/check
,那么实际上是请求:
http://192.168.2.2:8088/project/check