React项目的前几步(聊天系统)
提要:本例程是为了个人复习巩固react基础,尤其是如何开始、标准化去建设react项目,这里没有过深的知识点和技巧,只有按部就班和规矩办事,顺带复习了redux和路由的构建,在第二章之后的内容,不会在此博客呈现,属于私人部分,如果你没有学过react,你应该先去官网了解学习
1. 搭建项目和打包发布
使用create-react-app脚手架
npm install -g create-react-app
// 全局下载工具
create-react-app project_name
//下载模板项目
cd 文件名
npm start
//访问: localhost:3000
1)编码测试
npm start
//访问localhost:3000
2)打包发布
npm run build
npm install -g serve
serve build
//访问localhost:5000
项目目录设置和杂项
一般来说,建设一个React前端包含以下几个目录
- node_modules
这是调用外部、架构等模块的代码块 - public
这是主页index.html模块 - src
这是最重要的模块,当你去做一个标准的项目,这个模块应该包含以下几个文件(需要自己根据需求设置添加,不需要严格一样)
- package.json
这是你的模块描述文件,请注意,这个文件代码禁止注释
2. 引入外部资源(如需要)
引入antd-mobile(UI资源)
我们知道,在设计一个优秀的展示界面时,UI及其重要,这是用户与程序员交互的First-layer。
所以我们假设需要antd-mobile的资源时,需要先引入,当然,你可能并不知道或者不太清楚antd的过多知识,打开蚂蚁金服UI官网去学习。
1)引入antd-mobile
在你的项目下,打开终端,输入
npm install antd-mobile--save
除此之外,你需要在index.html中将react官方案例修改,因为你调用了不同的script
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
if(!window.Promise) {
document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');
}
</script>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
2)这个UI组件库如此宏大,如果你把所有的组件引入,但是你又不需要,非常浪费资源,增加了加载速度,所以你在引入antd-mobile之后,可以引入组件按需打包的功能
npm install--save-dev babel-plugin-import react-app-rewired
同时,你需要在定义加载、配置js的模块的config-overrides.js文件增加:
const {injectBabelPlugin} = require('react-app-rewired');
module.exports = function override(config, env)
{ config = injectBabelPlugin
(['import',
{libraryName: 'antd-mobile', style: 'css'}],
config);
return config;
}
别忘了package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject" }
当然,这样做可能会有版本冲突,也许需要升降版本。
3)在这些组件引入后、配置完按需加载后,你可能需要试一试效果,那就去你的入口文件(一般都是在src下面的index.js)写入
其中getElementById后面的Id是你index.html中div中的那个Id
import React from 'react'
import ReactDOM from 'react-dom' import {Button} from 'antd-mobile'
ReactDOM.render( <Button type='primary'>学习</Button>, document.getElementById('root') )
你应该可以看到一个学习的按钮。
我们可以看看antd-mobile的类似组件:
自定义主题
我们都知道,在各式UI组件中, 按钮的primary一般都是蓝色的,这是因为,整个主题颜色是蓝色,但是很明显不能每个软件/界面都是这种千篇一律的主题,你可能需要变色,那么如何做?
less,是一种css预编译器,你可以在预编译器里面修改主题颜色。
首先下载相应组件
npm install--save-devless@2.7.3 less-loader
好了,下载完组件,我们可以在config-override中配置,这是最终config-override的所有代码
const {injectBabelPlugin, getLoader} = require('react-app-rewired');
const fileLoaderMatcher = function (rule) {
return rule.loader && rule.loader.indexOf(`file-loader`) != -1;
}
module.exports = function override(config, env) {
// babel-plugin-import
config = injectBabelPlugin(['import', {
libraryName: 'antd-mobile',
//style: 'css',
style: true, // use less for customized theme
}], config);
// customize theme
config.module.rules[1].oneOf.unshift(
{
test: /\.less$/,
use: [
require.resolve('style-loader'),
require.resolve('css-loader'),
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
{
loader: require.resolve('less-loader'),
options: {
// theme vars, also can use theme.js instead of this.
modifyVars: {
"@brand-primary": "#1cae82", // 正常
"@brand-primary-tap": "#1DA57A", // 按下
},
},
},
]
}
);
// css-modules
config.module.rules[1].oneOf.unshift(
{
test: /\.css$/,
exclude: /node_modules|antd-mobile\.css/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
modules: true,
importLoaders: 1,
localIdentName: '[local]___[hash:base64:5]'
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
]
}
);
// file-loader exclude
let l = getLoader(config.module.rules, fileLoaderMatcher);
l.exclude.push(/\.less$/);
return config;
};
请注意,这里
“@brand-primary”: “#1cae82”, // 正常
“@brand-primary-tap”: “#1DA57A”, // 按下
我修改了主题颜色的primary和按下
引入路由
路由,是各式各类框架里最重要的一部分,在react中,你需要先引入
npm install--save react-router-dom
想象一下,至少一个正常的聊天系统,需要登陆、注册、和主界面(实际上还有更多)。但是我们先假设这三个界面 ,我们在index.js里设置路由,同时,在src的containers目录下分别创建login/login.jsx、register/register.jsx 、main/main.jsx
import Login from './containers/login/login'
import Register from './containers/register/register'
import Main from './containers/main/main'
ReactDOM.render((
<HashRouter>
<Switch>
<Route path='/login' component={Login}/>
<Route path='/register' component={Register}/>
<Route component={Main}/>
</Switch>
</HashRouter> ), document.getElementById('root'))
这里要强调一下除了react-router-dom还有react-router,他们区别如下:
- react-router:提供了router的核心api。如Router、Route、Switch等,但没有提供有关dom操作进行路由跳转的api;
- react-router-dom:提供了BrowserRouter、Route、Link等api,可以通过dom操作触发事件控制路由。
路由并不难,实际上,react有一个常用但是不好理解的是Redux,但是Redux你未必用得到,正如一句老话:如果你不知道是不是需要Redux,那你就不需要Redux。那接下来,就稍微谈一谈这个东西。
引入Redux
说起redux,就不得不谈一谈这个图片
我相信学过或者了解react的同学大多都见过这个图片。我们都知道,react本身是可以管理状态的,例如这个页面,UI是否被点击,POST/GET请求是否被发送,服务器有无响应等等。但是如下所说的问题,值得深思。
管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state在什么时候,由于什么原因,如何变化已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。
而Redux的解释、学习需要长篇大论,我建议直接看阮一峰的redux博客来的更快。
同样,我们引入redux,请注意,很多情况为了方便使用,还会引入react-redux,他们之间没有太多区别,详细区别为点我
npm install--save redux@3.7.2 react-redux redux-thunk
npm install--save-dev redux-devtools-extension
这里不得不再说说redux-thunk
Redux store 仅支持同步数据流。使用 thunk 等中间件可以帮助在 Redux 应用中实现异步性。可以将 thunk 看做 store 的 dispatch() 方法的封装器;我们可以使用 thunk action creator 派遣函数或 Promise,而不是返回 action 对象。
我们知道,redux包含
- Reducers
import {combineReducers} from 'redux'
function xxx(state = 0, action) {
return state
}
function yyy(state = 0, action) {
return state
}
//返 回 合 并 后 的 reducer函 数
export default combineReducers({
xxx,
yyy
})
其中,combineReducers方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。
- Store
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension' import reducers from './reducers'
export default createStore(reducers, composeWithDevTools(applyMiddleware(thunk)))
这个时候我们发现还引入了applyMiddleware()
Redux里我们都知道dispatch一个action,就会到达reducer,而middleware就是允许我们在dispatch action之后,到达reducer之前,搞点事情。比如:打印,报错,跟异步API通信等等
如果还想继续了解Redux请打开这个连接,同时,我们也发现上面还引入了composeWithDevTools,他是为了更好的查看redux中状态的变化,如果了解请打开这个连接。
3.index.js
需要在入口js中加入
import {Provider} from 'react-redux'
import store from './redux/store'
在render里面加入
<Provider store={store}>