☼ 注:笔者的文章是根据自己当前项目做的笔记,具体应用请参照自己实际项目情况
1、创建应用
npx create-react-app my-app
cd my-app
npm start
2、热加载,src/index.js文件
function render() {
ReactDOM.render(
<App />,
document.getElementById('root'))
}
render()
if (module.hot) {
module.hot.accept(() => {
render()
})
}
3、配置eslint代码规范
⑴ 在根目录新建.eslintrc.js文件
const pkg = require('./package.json')
const reactVersion = () => {
if (pkg.dependencies && pkg.dependencies.react) {
return { version: pkg.dependencies.react.replace(/[^0-9.]/g, '') }
}
if (pkg.devDependencies && pkg.devDependencies.react) {
return { version: pkg.devDependencies.react.replace(/[^0-9.]/g, '') }
}
}
module.exports = {
"parser": "babel-eslint",
// 配置规则
"rules": {
"strict": 0,
"no-console": 0,
"global-require": 0,
"jsx-a11y/href-no-hash": 0,
"react/forbid-prop-types": 0,
"jsx-a11y/no-static-element-interactions": 0,
'import/no-dynamic-require': 0,
"import/no-extraneous-dependencies": 0,
"max-len": ["error", 240],
"linebreak-style":0,
"no-eval": 2,
"indent": ["error", 4, { "SwitchCase": 1 }],
"no-tabs": 0,
"comma-dangle": 0,
"no-array-index-key": 0,
"arrow-parens": 0,
"object-shorthand": 0,
"react/jsx-filename-extension": 0,
"react/jsx-indent": 0,
"react/jsx-indent-props": 0,
"react/require-default-props": 0,
"react/no-array-index-key": 0,
"no-prototype-builtins": 0,
"no-continue": 0,
"no-restricted-globals": [0],
"quotes": ["error", "single"],
"keyword-spacing": ["error", { "before": true }],
"no-var": 1,
"semi": ["error", "never"],
"key-spacing": ["error", { "afterColon": true }],
"comma-spacing": ["error", { "before": false, "after": true }],
"arrow-spacing": ["error", { "before": true, "after": true }],
"no-multi-spaces": ["error"],
"no-trailing-spaces": ["error", { "skipBlankLines": true }],
},
"env": {
"browser": true,
"node": false
},
"plugins": [
"react",
"jsx-a11y",
"import"
],
"globals": {
"DEBUG": false,
"NORMAL_SERVER": true,
"CUSTOMER_FLAG": true,
"IS_USE_NATIVE_CAMERA": true,
"TOMCAT_SERVER_SIGN_ADDRESS": true,
"TOMCAT_SERVER_ACCOUNT_HINT_ADDRESS": true,
"UPLOAD_IMG_OVER_TIME": true,
"IS_NEED_CREATE_HISTORY": true,
},
'settings': {
'react': {
...reactVersion()
}
}
}
⑵ 打开【文件】→【首选项】→【设置】→【用户】或【工作区】→【扩展】→【ESLint】→【setting.json】,添加以下代码
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
(3) 在【用户】→【扩展】→【ESLint】把【Auto Fix On Save】勾上,就可以在保存代码时自动修复eslint警告了
⑷ 配置eslint检查忽略的文件路径,在根目录新建.eslintignore文件
# product path
build
# lib path
node_modules
config
scripts
☆ 以上配置步骤针对vscode,并且确保已经安装了【ESLint】插件
4、异步加载组件
见笔者文章《react异步加载组件》
5、配置axios
⑴ 安装
npm install axios --save
npm install qs --save
⑵ 在src目录下新建api目录,在api目录下新建一个axios.js文件用于配置axios拦截器
⑶ 在api目录下新建一个config.js
export const HOST = window.location.origin
// 不同环境
export const apiUrl = HOST.includes('cms') ? 'v1/xxx' : 'c/xxx'
⑷ 把项目中需要用到的接口按模块划分,分别新建一个js文件
import axios from '../axios'
import { apiUrl } from '../config'
export default {
/***
* 登录检查
* @method post
* @return JSON data :{"username":account,"password":devpasword};
* */
loginCheck: data => axios.post(apiUrl+'/common/admin/loginCheck.do', data),
/***
* 登录
* @method post
* @return JSON data :{};
* */
login: data => axios.get(apiUrl+'/admin/login.do', data),
}
6、配置proxy跨域代理
见笔者文章《create-react-app和vue-cli配置跨域代理》
7、代理到本地mock数据
⑴ 在config文件夹下新建一个mock.js(名字无所谓,自己起)
const glob = require('glob')
const fs = require('fs')
const files = glob.sync('mock/**/*.json')
module.exports = function (app) {
files.forEach(file => {
let data = fs.readFileSync('./' + file, 'utf8')
app.all(file.slice(4, -5), (req, res) => {
console.log('req', req.originalUrl)
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'DELETE,GET,HEAD,POST,PUT,OPTIONS,TRACE')
res.setHeader("Access-Control-Allow-Headers", "X-Custom-Header,accept, Content-Type")
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Content-Type', 'application/json;charset=UTF-8')
res.status(200).send(data)
})
})
}
⑵ 在webpackDevServer.config.js文件中,找到before函数,引入mock.js
before(app, server) {
// 当使用mock数据的时候打开
require('./mock.js')(app)
}
⑶ 在项目的根目录下【注意是根目录,不是src目录】,新建一个mock文件夹,然后在mock文件夹下按照接口地址新建一个json文件,把模拟的数据写在json文件里即可,例如:
接口地址为:'/clife-estate-api-web-admin/estate/menuMgr/queryMenuResource.do'
文件目录为:'mock/clife-estate-api-web-admin/estate/menuMgr/queryMenuResource.do.json'
数据内容为:
{
"data": {
"record": [],
"totalRows": 0
},
"code": 0
}
⑷ 每次添加mock数据后,重新启动项目, 项目启动默认是走mock数据,如果没有mock数据的就走后台接口
8、配置mobx
见笔者文章《create-react-app中配置less和mobx》
⑴ 在src目录下新建一个store目录,在store目录下按大模块划分文件夹,再按小模块分别新建一个文件用来处理接口
import merchantMng from '@/api/merchantMng'
import {observable, action, computed} from 'mobx'
import {dateFormat} from '@/utils/date'
export default class MerchantMng {
@observable totalRows = 0
@observable merchantList = []
// 商户管理--查询
@action queryMerchant = async (params) => {
const data = await merchantMng.queryMerchant(params)
try {
this.merchantList = data.data.record
this.totalRows = data.data.totalRows
} catch (e) {
console.log(e)
}
}
@computed get merchantData() {
try {
return this.merchantList.map((item, index) => {
return {
...item,
createTime: dateFormat(item.createTime, 'yyyy-MM-dd HH:mm:ss')
}
})
} catch (e) {
return []
}
}
// 商户管理--新增
@action addMerchant = async (params) => {
return await merchantMng.addMerchant(params)
}
}
新建一个index.js
import MerchantMng from './merchantMng'
class Community {
constructor() {
this.MerchantMng = new MerchantMng()
}
}
export default Community
⑵ 在store目录下新建index.js
import Community from './community'
class RootStore {
constructor() {
this.Community = new Community()
}
}
const rootStore = new RootStore()
export default rootStore
⑶ 把store注入全局
// src/index.jsx文件
import { Provider } from 'mobx-react'
import rootStore from './store'
function render() {
ReactDOM.render(
<Provider {...rootStore}>
<App />
</Provider>,
document.getElementById('root'))
}
render()
if (module.hot) {
module.hot.accept(() => {
render()
})
}
⑷ 在页面中调用接口
import React, { Component } from 'react'
import { observer, inject } from 'mobx-react'
@inject('Community') // 给组件注入其需要的 store(利用 React context 机制)
@observer // 监听store的变化, 同时更新视图的变化
class MerchantManage extends Component {
/**
* 查询商户
* @param {Number} pageIndex 当前页码
* @param {Object} carParkMerchant 参数对象
*/
queryMerchant = (pageIndex = 1, carParkMerchant = {}) => {
const { MerchantMng } = this.props.Community
const params = {
// post和get请求都把参数写在param里
param: {
data: {
carParkMerchant,
pager: {
pageRows: 10,
pageIndex,
paged: true
},
orderBy: {
orderColumn: 't.createTime',
orderType: 'desc'
}
}
}
// headers: { 'content-type': 'application/json' } 请求头需要传参写在这里
}
MerchantMng.queryMerchant(params).then(() => {
this.setState({
tbodyData: MerchantMng.merchantData,
totalRows: MerchantMng.totalRows,
currentPage: pageIndex
})
})
}
}
9、配置rem
⑴ 在public/index.html添加以下代码
<script>
function remFont() {
var html = document.getElementsByTagName("html")[0];
var width = document.documentElement.clientWidth;
var font_Size = 0;
if(width >= 1366){
font_Size = 100/1920 * width;
}else{
font_Size = 100/1920 * 1366;
}
html.style.fontSize = font_Size + "px";
}
remFont()
window.addEventListener('resize', function () {
remFont()
})
</script>
⑵ 在App.scss中设置html字体大小
html {
font-size: 100px;
}
10、配置px2rem
⑴ 安装
npm install postcss-px2rem-exclude --save
⑵ 在webpack.config.dev.js和webpack.config.prod.js的"getStyleLoaders"方法中添加以下代码
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
// 配置px2rem
require('postcss-px2rem-exclude')({
remUnit: 100,
exclude: /node_modules/i,
})
],
sourceMap: shouldUseSourceMap,
},
},
11、引入阿里iconfont
⑴ 在src文件夹下新建一个assets文件夹,再新建一个iconfont文件夹,把阿里图库生成的文件放到文件夹下
⑵ 在App.jsx中引入
import './assets/iconfont/iconfont.css'
12、引入antd,配置按需加载
⑴ 安装
npm install antd --save
npm i babel-plugin-import --save
⑵ 在webpack.config.dev.js和webpack.config.prod.js中找到"oneOf",在"customize"下方的"plugins"中添加以下代码
["import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css"
}]
⑶ 使用组件
import { Layout } from 'antd'
13、去除build生成的.map文件
打开文件webpack.config.prod.js,搜索"shouldUseSourceMap",找到第一个结果,注释掉这一行,另起一行把它的值改为false
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
const shouldUseSourceMap = false;
14、打包后首页空白
// package.json中添加
"homepage": "."
15、浏览器es6兼容
⑴ 安装babel-polyfill
npm install --save-dev babel-polyfill
⑵ 在src/index.js引用
import 'babel-polyfill'
16、其他目录结构
⑴ 在src目录下新建一个pages目录,用来存放开发的页面
⑵ 在src目录下新建一个components目录,用来存放封装的组件
⑶ 在src目录下新建一个static目录,用来存放本地媒体资源文件
⑷ 在src目录下新建一个utils目录,用来存放封装的公共方法,项目中常用的公共方法可参考笔者文章《封装项目中常用的工具函数》
网友评论