https://react.docschina.org/docs/create-a-new-react-app.html
安裝react 腳手架
npx create-react-app damon-cms-react
cd damon-cms-react
npm start
ant.design
安裝antd
yarn add antd react-app-rewired customize-cra babel-plugin-import less less-loader
修改package.josn
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
}
根目錄config-overrides.js 創建文件配置如下
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
module.exports = override(
//寫了下面這個部分,就實現了按需加載,再也不需要再每個頁面裏面都引入“antd/dist/antd.css”啦
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true //這裏一定要寫true,css和less都不行哦
}),
addLessLoader({
javascriptEnabled: true,
//下面這行很特殊,這裏是更改主題的關鍵,這裏我只更改了主色,當然還可以更改其他的,下面會詳細寫出。
modifyVars: { "@primary-color": "#f47983"}
})
)
初始化工程目錄
public
favicon.ico ------ 瀏覽器頭部logo
index.html ------ 項目首頁模板
manifest.json ------ PWA serviceWoker 網頁用戶訪問存儲到手機的參數配置 在後臺管理項目中沒有作用
api
home.json ------ 測試數據
src
index.js ------ 程序入口文件
pages ------ 各個展示頁面
home
store ------ 存儲單獨頁面數據
actionCreators.js
constants.js
index.js
reducer.js
index.js ------ home頁面
store
index.js ------ redux 入口文件
reducer.js ------ 改變state函數
node_modules ------ 依賴第三方包文件
.gitignore ------ git 忽略文件
package.json ------ node包文件
README.md
yarn.lock ------ 項目依賴安裝包版本號
安裝 redux 和 react-redux 和 redux-thunk 和 axios 和 immutable 和 redux-immutable
npm install --save redux
npm install --save react-redux
npm install --save redux-thunk
npm install --save axios
npm install --save immutable
npm install --save redux-immutable
使用 redux
public>api>home.json 文件內容
{
"success": true,
"data": {
"topicList": [{
"id": 1,
"title": "社會熱點",
"imgUrl": "//upload.jianshu.io/collections/images/261938/man-hands-reading-boy-large.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/64/h/64"
}, {
"id": 2,
"title": "手手繪",
"imgUrl": "//upload.jianshu.io/collections/images/21/20120316041115481.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/64/h/64"
}],
"articleList": [{
"id": 1,
"title": "胡歌12年後首談車禍",
"desc": "文/麥大人 01 胡歌又刷屏了。 近日他上了《朗讀者》,而這一期的主題是“生命”,他用磁性的嗓音,朗讀了一段《哈姆雷特》中的經典獨白,相當震撼:...",
"imgUrl": "//upload-images.jianshu.io/upload_images/15631385-387601b6c91b14f7?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
} ]
}
}
src>store>index.js 文件內容
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(
applyMiddleware(thunk)
));
export default store;
src>store>reducer.js 文件內容
import { combineReducers } from 'redux-immutable'
import {reducer as homeReducer } from '../pages/home/store/'
export default combineReducers({
home:homeReducer,
})
home>index.js 文件內容
import React from 'react';
import { connect } from 'react-redux';
import { actionCreators } from './store';
class Home extends React.Component {
render() {
const { topicList } = this.props
return (
<div>
{
topicList.map((item, index) => {
return (
<div key={index} to={'/detail/' + item.get('id')}>
<div >
<img alt='' className='pic' src={item.get('imgUrl')} />
<div>
<h3 className='title'>{item.get('title')}</h3>
<p className='desc'>{item.get('desc')}</p>
</div>
</div>
</div>
);
})
}
</div>
)
}
componentDidMount() {
this.props.changeHomeData();
}
}
const mapState = (state) => ({
topicList: state.getIn(['home', 'topicList']),
})
const mapDispatch = (dispatch) => ({
changeHomeData() {
dispatch(actionCreators.getHomeInfo());
},
});
export default connect(mapState, mapDispatch)(Home);
src>App.js
import React from 'react';
import store from './store';
import { Provider } from 'react-redux';
import Home from './pages/home'
function App() {
return (
<Provider store={store}>
<div className="App">
<Home></Home>
</div>
</Provider>
);
}
export default App;
src>pages>home>store>actionCreators.js
import axios from 'axios';
import * as constants from './constants';
import { fromJS } from 'immutable';
const changHomeData = (result) => ({
type: constants.CHANGE_HOME_DATA,
topicList: result.topicList,
articleList: result.articleList,
recommendList: result.recommendList
});
const addHomeList = (list, nextPage) => ({
type: constants.ADD_ARTICLE_LIST,
list: fromJS(list),
nextPage
})
export const getHomeInfo = () => {
return (dispatch) => {
axios.get('/api/home.json').then((res) => {
const result = res.data.data;
dispatch(changHomeData(result));
});
}
}
export const getMoreList = (page) => {
return (dispatch) => {
axios.get('/api/homeList.json?page=' + page).then((res) => {
const result = res.data.data;
dispatch(addHomeList(result, page + 1));
});
}
}
src>pages>home>store>constants.js
export const CHANGE_HOME_DATA = 'home/CHANGE_HOME_DATA';
export const ADD_ARTICLE_LIST = 'home/ADD_ARTICLE_LIST';
src>pages>home>store>index.js
import reducer from './reducer';
import * as actionCreators from './actionCreators';
import * as constants from './constants';
export { reducer, actionCreators, constants };
src>pages>home>store>reducer.js
import { fromJS } from 'immutable';
import * as constants from './constants';
const defaultState = fromJS({
topicList: [],
articleList: [],
articlePage: 1,
});
const changeHomeData = (state, action) => {
return state.merge({
topicList: fromJS(action.topicList),
articleList: fromJS(action.articleList),
recommendList: fromJS(action.recommendList)
});
};
const addArticleList = (state, action) => {
return state.merge({
'articleList': state.get('articleList').concat(action.list),
'articlePage': action.nextPage
});
};
export default (state = defaultState, action) => {
switch(action.type) {
case constants.CHANGE_HOME_DATA:
return changeHomeData(state, action);
case constants.ADD_ARTICLE_LIST:
return addArticleList(state, action);
default:
return state;
}
}