React知识点

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引入antdantd-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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容