前言:React专注View层,一切皆组件;全部使用ES6语法,最新版本为React16。
Redux是专注于状态管理的库,和react解耦;单一状态,单向数据流。【独立团github地址】
一、React基础知识
??? React基础语法
- render函数返回值就是输出JSX语法,会把JSX转成js执行
??? React的View层语法
??? React的Api
- 使用<组件 数据=‘值‘ >的形式传递
- 组件里使用this.props获取值
- 如果组件只有render函数,还可以用函数的形式写组件
- JSX本质就是js,所以直接数组.map渲染列表,【注意列表项必需有唯一key】
- Constructor构造函数设置组件初始状态,记得执行super(props)
- State就是一个不可变的对象,使用this.state获取
- 通过this.setState修改,不能直接修改
- JSX里,onClick={this.函数名}来绑定事件
- this引用的问题,需要在构造函数里用bind绑定this,或者箭头函数直接绑定
- this.setState修改state,记得返回新的state,而不是修改
??? React生命周期
?? ?独立团Demo
? ? ? 
import React from ‘react‘;
class App extends React.Component{
render(){
let boss = ‘李云龙‘
return (
<div>
<h2>独立团,团长{boss}</h2>
<FirstYin leader=‘张大喵‘></FirstYin>
<Squadron leader=‘孙德盛‘></Squadron>
</div>
)
}
}
function Squadron(props){
return <h2>骑兵连连长{props.leader},冲啊!</h2>
}
class FirstYin extends React.Component{
constructor(props) {
super(props)
this.state = {
solders: [‘虎子‘,‘柱子‘,‘王根生‘]
}
// this.addSolder = this.addSolder.bind(this)
}
componentWillMount(){
console.log(‘组件马上就要加载了‘)
}
componentDidMount(){
console.log(‘组件加载完成了‘)
}
addSolder = () => {
console.log(‘hello add solder‘)
this.setState({
solders: [...this.state.solders,‘新兵蛋子编号:‘+Math.random()]
})
}
render(){
console.log(‘组件正在加载‘)
return (
<div>
<h2>一营营长,{this.props.leader}</h2>
<button onClick={this.addSolder}>新兵入伍</button>
<ul>
{this.state.solders.map(solder => {
return <li key={solder}>{solder}</li>
})}
</ul>
</div>
)
}
}
export default App;
?
二、Redux基础知识
?? ?Redux核心概念
-
Store:保存数据的容器,一个应用只能有一个Store。Redux提供createStore函数,创建Store
import {createStore} from ‘redux‘;
const store = createStore(fun); //createStore的参数为reducer函数
-
State:数据状态。Store在某一时刻的状态,可以通过store.getState()获取到。
const state = store.getState();
-
Action:Redux改变state必需通过Action,实际上是一个JSON对象,该对象必须包含type属性,表示Action的名称。
//该函数不需要主动去调用,事实上我们在store.dispatch的时候,会自动触发。
const action = {
type: ‘ADD‘,//action名称
val: 5 //携带数据
};
-
Action Creator:Action生成函数,用于创建Action,类似于工厂模式。若不使用,需要写很多Action。
function createAdd(number) {
return {
type: ‘ADD‘,val: number
}
}
const action = createAdd(5);
-
store.dispatch(action):View用于触发数据变化的唯一方式
import {createStore} from ‘redux‘;
const store = createStore(fun);
store.dispatch({ //state+5
type: ‘ADD‘,val: 5
});
?? ?Redux单独使用?
? ? ? ? 
- src->index.js中:所有状态归redux管理(组件只负责view显示)
-
reducer新建store,随时通过store.getState获取状态
import {createStore} from ‘redux‘
//通过reducer
//根据老的 state和 action 生成新的state
function counter(state=0,action){
switch(action.type){
case ‘Add_GUN‘:
return state+1
case ‘REMOVE_GUN‘:
return state-1
default:
return 10
}
}
//1、新建store
const store = createStore(counter)
const init = store.getState()
console.log(init) //10
-
需求状态变更,store.dispatch(action)来修改状态
//2、派发事件 传递action
store.dispatch({type: ‘Add_GUN‘})
store.dispatch({type: ‘REMOVE_GUN‘})
-
reducer函数接收state和action,返回新的state,可以用store.subscribe监听每次修改
//定义事件方法
function listener(){
const current = store.getState();
console.log(`现在有机枪${current}把`)
}
//3、监听事件
store.subscribe(listener)
?? ?Redux和React一起用(手动连接)
? ? ??
-
Redux相关内容,移到单独的文件index.redux.js单独管理:reducer+action
//action type
const Add_GUN = ‘加机关枪‘
const REMOVE_GUN = ‘减机关枪‘
//reducer
export function counter(state=0,action){
switch(action.type){
case Add_GUN:
return state+1
case REMOVE_GUN:
return state-1
default:
return 10
}
}
//action creator
export function addGUN(){
return {type: Add_GUN}
}
export function removeGUN(){
return {type: REMOVE_GUN}
}
-
App.js中:把store.dispatch方法传递给组件,内部可以调用修改状态
import React from ‘react‘;
class App extends React.Component{
render(){
const store = this.props.store
const num = store.getState()
const addGUN = this.props.addGUN
const removeGUN = this.props.removeGUN
return (
<div>
<h3>现在有机枪{num}把</h3>
</div>
)
}
}
export default App;
-
index.js中:Subscribe订阅render函数,每次修改都重新渲染
import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import {createStore} from ‘redux‘
import {counter,addGUN,removeGUN} from ‘./index.redux‘
const store = createStore(counter)
function render(){
ReactDOM.render(<App store={store} addGUN={addGUN} removeGUN={removeGUN}/>,document.getElementById(‘root‘));
}
render()
store.subscribe(render)
?? ?Redux处理异步
? ? ??
- Redux默认只处理同步,异步任务需要react-thunk中间件
-
安装插件
npm install redux-thunk --save
-
index.js中:使用applyMiddleware开启thunk中间件
import {createStore,applyMiddleware} from ‘redux‘
import thunk from ‘redux-thunk‘
import {addGunAsync} from ‘./index.redux‘
const store = createStore(counter,applyMiddleware(thunk))
-
index.redux.js中:Action可以返回函数,使用dispatch提交action
//(模拟)异步函数提交dispatch
export function addGunAsync(){
return dispatch => {
setTimeout(() => {
dispatch(addGUN())
},2000)
}
}
-
App.js中:把store.dispatch方法传递给组件,内部可以调用修改状态
import React from ‘react‘;
class App extends React.Component{
render(){
const store = this.props.store
const num = store.getState()
const addGunAsync = this.props.addGunAsync
return (
<div>
<h3>现在有机枪{num}把</h3>
<button onClick={() => store.dispatch(addGunAsync())}>拖两天再给</button>
</div>
)
}
}
??? Redux调试工具
? ? ??
-
项目本地安装
npm install redux-devtools-extension --save
- 新建store的时候判断window.decToolsExtension
-
使用compose组合函数结合thunk和window.devToolsExtension
import {createStore,applyMiddleware,compose} from ‘redux‘
const store = createStore(counter,compose(
applyMiddleware(thunk),window.devToolsExtension ? window.devToolsExtension() : f => f
))
- 调试窗的redux选项卡,实时看到state
??? 使用React-redux优雅的链接react和redux
? ? ??
-
index.js中:Provider组件在应用最外层,传入store即可,只用一次
import {Provider} from ‘react-redux‘
import {counter} from ‘./index.redux‘
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,document.getElementById(‘root‘)
);?
-
Connect负责从外部获取组件需要的参数(mapStateToProps,actionCreators)
import React from ‘react‘;
import {connect} from ‘react-redux‘
import {addGUN,removeGUN,addGunAsync } from ‘./index.redux‘
class App extends React.Component{
render(){
return (
<div>
<h3>现在有机枪{this.props.num}把</h3>
<button onClick={this.props.addGUN}>申请武器</button>
<button onClick={this.props.removeGUN}>上交武器</button>
<button onClick={this.props.addGunAsync}>拖两天再给</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
num: state
}
}
const actionCreators = {addGUN,addGunAsync}
App = connect(mapStateToProps,actionCreators)(App)
export default App;
-
弹出个性化配置
-
安转专门支持装饰器的插件
npm install babel-plugin-transform-decorators-legacy --save-dev
-
Package.json里babel加上plugins配置
"plugins": [
["@babel/plugin-proposal-decorators",{ "legacy": true }],]
?
-
优化connect
import React from ‘react‘;
import {connect} from ‘react-redux‘
import {addGUN,addGunAsync } from ‘./index.redux‘
@connect(
state => ({num: state})
{addGUN,addGunAsync}
) //使用装饰器方法优化connect
class App extends React.Component{
render(){
return (
<div>
<h3>现在有机枪{this.props.num}把</h3>
<button onClick={this.props.addGUN}>申请武器</button>
<button onClick={this.props.removeGUN}>上交武器</button>
<button onClick={this.props.addGunAsync}>拖两天再给</button>
</div>
)
}
}
export default App;
?
三、React-router4基础知识?
?? ?React-router4
- React官方推荐路由库,4是最新版本,和之前版本不兼容,浏览器和RN均兼容
-
核心概念:动态路由、Route、Link、Switch
-
Web中应用React-router:安装react-router-dom作为前端路由
npm install react-router-dom --save
-
入门组件
-
BrowserRouter包裹整个应用
-
Router路由对应渲染的组件,可嵌套
-
Link跳转专用 
import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import {BrowserRouter,Route,Link} from ‘react-router-dom‘
function Yiying(){
return <h2>一营</h2>
}
function Erying(){
return <h2>二营</h2>
}
function Qibinglian(){
return <h2>骑兵连</h2>
}
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<div>
<ul>
<li>
<Link to=‘/‘>一营</Link> //点击跳到指定路由
</li>
</ul>
<ul>
<li>
<Link to=‘/erying‘>二营</Link>
</li>
</ul>
<ul>
<li>
<Link to=‘/qibinglian‘>骑兵连</Link>
</li>
</ul>
<Route path=‘/‘ exact component={Yiying}></Route> //exact表明路由完全匹配
<Route path=‘/erying‘ component={Erying}></Route>
<Route path=‘/qibinglian‘ component={Qibinglian}></Route> //路由对应渲染模板
</div>
</BrowserRouter>
</Provider>,document.getElementById(‘root‘)
);
-
url参数,Route组件参数可用冒号标识参数
<Route path=‘/:location‘ component={Test}></Route>
-
Redirect组件? 跳转
<Redirect to=‘/qibinglian‘></Redirect>
-
Switch只渲染命中的第一个子Route组件
<Switch>
<Route path=‘/‘ exact component={Yiying}></Route>
<Route path=‘/erying‘ component={Erying}></Route>
<Route path=‘/qibinglian‘ component={Qibinglian}></Route>
</Switch>
?? ?和Redux配合
- 复杂redux应用,多个reducer,用combineReducers合并
-
index.js中:引入合并后的reducer,并注入createStore中
import reducers from ‘./reducer‘ //合并后的reducer
const store = createStore(reducers,window.devToolsExtension ? window.devToolsExtension() : f => f
))
-
reducers.js中:合并所有reducer,并返回
/**
* 合并所有reducer 并且返回
*/
import {combineReducers} from ‘redux‘
import {counter} from ‘./index.redux‘
import {auth} from ‘./Auth.redux‘
export default combineReducers({counter,auth})
-
Redirect组件 跳转
return this.props.isAuth ? app : <Redirect to=‘/login‘></Redirect>
-
Switch只渲染一个子Route组件
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route path=‘/login‘ component={Auth}></Route>
<Route path=‘/dashboard‘ component={Dashboard}></Route>
<Redirect to=‘/dashboard‘></Redirect>
</Switch>
</BrowserRouter>
</Provider>,document.getElementById(‘root‘)
);

注:转载请注明出处
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|