这个例子的模板的三元大佬写的小册,之前用js写过了一遍,最近在看ts,就试着写了一个推荐页面。demo地址
一、初始化项目配置less
首先使用React的官方脚手架创建项目
npx create-react-app demo --typescript
cd demo
npm run eject //将webpack,babel等相关配置的封装弹射出来,注意此操作不可逆
在config文件夹中打开webpack.config.js文件,在此文件里面,getStyleLoaders函数接受两个参数,第一个为传入css-loader的Options,第二个为可选,就是需要添加的loader,最后返回配置后的loader数组。我们添加如下代码:
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
然后在oneOf数组中,添加如下代码:
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
// modules: true, ////使用模块方式访问样式
sourceMap: isEnvProduction && shouldUseSourceMap,
},
"less-loader"
),
sideEffects: true,
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
// modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
"less-loader"
),
},
这里面的modules: true
,如果设置了在文件中需要这么使用less
:
import styles from './style.less';
<div className={styles.div}></div>
如果不设置此项,则按照使用css
的方式即可:
import './style.less';
<div className='div'></div>
需要注意的是,如果没有配置modules: true
,在组件中引入第三方库的css样式时,要在.less
文件中引入。比如一个轮播图组件需要引入swiper
的样式,那么就要在该组件引入的.less
文件中引入如下代码:
@import '../../../node_modules/swiper/css/swiper.css';
最后,在src目录下的react-app-env.d.ts文件添加如下代码即可使用less
declare module "*.less" {
const less: any;
export default less;
}
二、react-router
HashRouter和BrowserRouter
HashRouter
前面的Hash
属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分),即它的路径包含了#
,都是ip:port/#/xx
的形式,无论#
后面的路径怎么变化,请求的资源路径永远为/
,相当于index.html
,后端API接口不会和/
冲突,可以很容易进行前后端不分离的部署。
BrowserRouter
原理是H5的history API,IE9一下不兼容,需要web server
支持。它的请求路径都是ip:port/xxx
的形式。
BrowserRouter
进行组件跳转时可以传递任意参数实现组件间的通信,而HashRouter
不行(除非手动拼接URL字符串),因此一般配合Redux使用,实现组件间的数据通信。HashRouter
不需要web server支持
,常用来兼容旧版本浏览器。
BrowserRouter
的使用方法
import { createBrowserHistory } from "history";
<Router history={history}>
<Route path="/" component={Layout}></Route>
</Router>
三、连接react-redux并使用immer
创建store
文件,引入组件的reducer
,使用combineReducers
将所有的reducer
合成一个大的reducer
;applyMiddleware
中间件的作用是将redux
中的action => reducer
的过程变成了action => middleware => reducer
,我们可以用它来实现异步action、打印日志、错误报告等功能。具体代码如下:
import { createStore, compose, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import recommendReducer from './page/Recommend/store/reducer';
const Reducer = combineReducers({
recommend: recommendReducer,
});
export const Store = createStore(
Reducer,
compose(applyMiddleware(thunk))
);
export type initState = ReturnType<typeof Reducer>;
这里面的initState
就是reducer
里面的初始state
,不同于js版本,我们把它的定义放在具体的reducer里面。在组件的mapStateToProps
方法中可以用到它:
const mapStateToProps = (state: initState) => ({
bannerList: state.recommend.bannerList,
recommendList: state.recommend.recommendList,
});
当然,如果嫌麻烦,你可以直接用any
代替。
接下来就需要把store注入到全局中了,在index
文件中,我们需要借助Provider
组件。
Provider
原理是React组件的context属性,源码如下:
class Provider extends Component {
getChildContext() {
return {
store: this.props.store
};
}
render() {
return this.props.children;
}
}
Provider.childContextTypes = {
store: React.PropTypes.object
}
上面代码中,store放在了上下文对象context上面。然后,子组件就可以从context拿到store;
index
的代码如下:
const history = createBrowserHistory();
ReactDOM.render(
<Provider store={Store}>
<Router history={history}>
<Route path="/" component={Layout}></Route>
</Router>
</Provider>,
document.getElementById("root")
);
immer
网上关于immer的讲解已经很多了,这里就不在赘述,直接贴代码,在reducer
中使用
import * as actionTypes from './actionType';
import produce from 'immer';
import { RecommendStateType } from './data';
const defaultState: RecommendStateType = {
bannerList: [],
recommendList: [],
}
export default (state = defaultState, action: any) => {
return produce(state, draft => {
switch (action.type) {
case actionTypes.CHANGE_BANNER:
draft.bannerList = action.data;
break;
case actionTypes.CHANGE_RECOMMEND_LIST:
draft.recommendList = action.data;
break;
default:
return state;
}
})
}
四、总结
总的来说,用redux
写会觉得有些繁琐,因此社区中出现了很多基于redux
封装的框架,这里我推荐dva
。三元大佬的小册,我写的js版本就是使用了dva
。当然诚如我的一个同学说的,面试的时候,他们会问你redux
的东西,不会问你dva
,所以就算是对redux
进行复习了吧。
笔者还是个前端小萌新,难免会有纰漏错误,欢迎大佬们进行指点!