#基于react+js+Ant Design的后台管理系统#
1,react没有双向数据绑定,需要监听
<Input
className="from__item"
suffix={<i className="icon-Key"></i>}
placeholder="请输入登录密码"
type="password"
value={passWord}
onChange={ e => this.passWordChanged(e) }
/>
// 有时候会出现这种情况,获取到的target为null
// 因为React里面的事件并不是真实的DOM事件,
// 而是自己在原生DOM事件上封装的合成事件。
// 使用e.persist();将当前的合成事件从事件池中移除了就可以获取到了
handleKeyword = e => {
e.persist();
this.setState({
keyword: e.target.value,
})
}
2,this的指向可以通过箭头函数来保持原来的指向,也可以用bind(this, data)直接绑定this的指向,在handleSubmit(this, data)里面,this一定是第一个参数!
<Button
type="primary"
className="cert-btn"
onClick={this.handleSubmit.bind(data, this)}
>
登录
</Button>
3,利用mock.js来实现假数据测试
(1),首先还是先安装依赖 npm install -D mockJs
(2),新建mock文件夹,新建mock.js文件
(3),编写mock
`
import Mock from 'mockjs';
Mock.mock(/\/todoList.mock/, {
code': 0,
'data': {
'list|1-10': [{
// 属性 id 是一个自增数,起始值为 1,每次增 1
'id|+1': 1,
'title': '前端人人@id',
'status': 1
}]
},
'message': '操作成功',
'systemDate': new Date().getTime()
});
4,redux-persist
redux-persist会将redux的store中的数据缓存到浏览器的localStorage中。
实现方式主要是依靠两个方法:persistStore和persistReducer,使用persistReducer时需要指定persistConfig,这一项就是你需要缓存的数据处理项,它有着黑白名单的处理方式,还需要一个storage的协助:
在main.js中用标签包着
import store from "./store";
import { persistStore } from 'redux-persist'; //从redux-persist解构出persistStore()方法,该方法结合PersistGate标签使用会将redux的数据缓存到localStorage
//引入PersistGate标签
import { PersistGate } from 'redux-persist/es/integration/react';
const persistor = persistStore(store);
ReactDOM.render(
<Provider store={store}>
<PersistGate persistor={persistor}>
<Routes />
</PersistGate>
</Provider>,
document.getElementById('root'),
)
在store.js文件中引用
import { createStore, applyMiddleware } from 'redux' //异步 actions
import rootReducer from '@reducers'
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/es/storage'
// BLACKLIST
const persistConfig = {
key: 'root', // key是放入localStorage中的key
storage: storage, // storage简单就可以理解成localStorage的功能封装吧,不过有时候由于版本问题,必要在后一个storage上加一个default属性,可以在console中打出来判断是否需要加
blacklist: ['navigation']//navigation不会被存入缓存中,其他会,适用于少部分数据需要实时更新
};
// WHITELIST
const persistConfig = {
key: 'root',
storage: storage,
whitelist: ['navigation']
};
<!--可直接使用-->
const reducer = persistReducer(persistConfig, rootReducer);
<!--使用combineReducers-->
const reducers = combineReducers({
depReducer: persistReducer(persistConfig, depReducer)
});
<!--使用中间件applyMiddleware创建store-->
const store = createStoreWithMiddleware(persistReducer(storageConfig, rootReducer), initialState)
5,当路由发送改变时页面置顶
生命周期componentDidUpdate()与生命周期componentWillReceiveProps()的区别:
componentDidUpdate()---是在组件接受新的props之后触发,并且更新状态是同步的;
componentWillReceviceProps()---是在组件接受新的props之前触发,并且更新状态是异步的;
这点区别非常重要,也是componentWillReceiveProps生命周期被废弃的重要原因(可能导致某些问题), 所以推荐使用componentDidUpdate
app.js文件,在componentDidUpdate生命周期进行判断当前路由是否是上一个路由,如果不是则获取当前页面的dom节点置顶
componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
document.getElementById("page-content").scrollTo(0, 0);
}
}
6,react的生命周期
react可分为三个状态:
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
react生命周期的方法有:
- componentWillMount 在渲染前调用,在客户端也在服务端。
- componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
- componentWillReceiveProps 在组件接收到一个新的 prop (更新前)时被调用。这个方法在初始化render时不会被调用。
- shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
- componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。是在组件接受新的props之前触发,并且更新状态是异步的。
- componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。是在组件接受新的props之后触发,并且更新状态是同步的。
- componentWillUnmount在组件从 DOM 中移除之前立刻被调用。
栗子:
class Content extends React.Component {
componentWillMount() {
console.log('Component WILL MOUNT!')
}
componentDidMount() {
console.log('Component DID MOUNT!')
}
componentWillReceiveProps(newProps) {
console.log('Component WILL RECEIVE PROPS!')
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('Component WILL UPDATE!');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component DID UPDATE!')
}
componentWillUnmount() {
console.log('Component WILL UNMOUNT!')
}
render() {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
}
7,二级菜单的路由配置
import React from 'react'
import { Router, Route, IndexRoute, hashHistory, Redirect, IndexRedirect } from 'react-router'
import { base } from '@configs/base'; //基础管理的相关页面总入口文件
import { routes } from './router.js'; //引入路由文件
export function fliterRouter(routers, arr) { // 过滤路由
routers.forEach((item) => {
<!--含有子菜单的一级菜单-->
if (item.children) {
<!--配置show字段用于判断是否需要显示该一级菜单-->
if (!item.show){
const router = <Route key={item.path} path={item.path} component={item.component} onEnter={requireAuth} config={item} />
arr.push(router)
}
fliterRouter(item.children, arr)
} else {
const router = <Route key={item.path} path={item.path} component={item.component} onEnter={requireAuth} config={item} />
arr.push(router)
}
})
return arr
}
export default () => (
<Router history={hashHistory}>
<Route path="/" component={base.app} onEnter={requireAuth}>
<IndexRedirect to="/business/busManagement" />
{fliterRouter(routes, [])}
</Route>
<Route path="/test" component={base.example} />
<Route path="/login" component={base.loginFrom} />
<Route path="*" component={base.notfound} />
</Router>
)
8,redux的简单使用
在action.js文件中使用createAction创建action
import { createAction } from 'redux-actions'
// login 登陆
export const requestLogin = createAction('request login')
export const recevieLogin = createAction('receive login')
export const loading = createAction('loading')
在reducer.js文件中使用handleActions处理action
import {handleActions} from 'redux-actions'
// 登陆返回结果
const loginState = () => ({loading: false})
export const loginResponse = handleActions({
'request login'(state, action) {
return {...state, loading: true}
},
'receive login'(state, action) {
// eslint-disable-next-line no-unused-vars
console.log(action);
const {req, res} = action.payload
return {menu: res.data.menu,userName:res.data.userName ,loading: false}
},
'loading'(state, action) {
return {loading: false}
}
}, loginState())
在login.js文件中通过this.props.dispatch调用action的login()方法,保存数据(修改/更新数据)到store里
this.props.dispatch(login(formData, (res) => {
<!--登录成功跳转到首页-->
hashHistory.push("/business/busManagement")
}, (res) => {
message.warning(res.msg);
this.props.dispatch(loading({loading: false}))
}))