一、
1.当组件的state或者props发生改变的时候,render函数就会重新执行;当父组件的render函数被运行时,他的子组件的render都将被重新运行
2.react视图更新原理:
image.pngimage.png
优点:1.提升性能2.跨端应用的实现reactNative
虚拟dom:1.同层比对
3.生命周期:
image.png4.prevState的使用
1.组件中只能通过setState改变state的值,其他直接赋值等改变state的方式都将不被允许
2.setState接收第二个回调函数
3.prevState接收的是变化钱的值
4.className
this.setState((prevState) =>({
list:[...prevState.list,prevState.inputValue],
inputValue: ''
}), () => { console.log(this.ul.querySelectorAll('div').length) })
二、使用Charles进行接口数据模拟
1.下载工具
2.配置
image.png
image.png
三.父组件
1.react中操作dom使用ref={(input) => {this.input = input}}
2.通过bind(this)来绑定this的指向
3.UI组件的使用
4.生命周期方法的使用
import React, { Component } from 'react'
//按需引入antd组件
import 'antd/dist/antd.css'
import { Input,Button,List} from 'antd'
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue:'',
list:[]
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleBtnClick= this.handleBtnClick.bind(this)
this.handleItemDelete= this.handleItemDelete.bind(this)
}
//在组件即将被挂在到页面的时候自动执行
componentWillMount(){}
render(){
return(
<Fragment>
<div>
<label htmlFor="insertArea">输入内容</label>
<input id="insertArea" className='input' value={this.state.inputValue} onChange= {this.handleInputChange} ref={(input) => {this.input = input}}/>
<button onClick={this.handleBtnClick}>提交</button>
</div>
<ul> { this.getTodoItem() }</ul>
<Fragment>
)
}
}
//组件被挂载到页面之后,自动被执行
componentDidMount() {}
//组件被更新之前,他会自动被执行
shouldComponentUpdate(){}
//如果被更新之前,它会自动执行,但是她在shouldComponentUpdate之后,
//如果shouldComponentUpdate返回false,这个函数不会被执行
componentWillUpdate() {}
//将代码做部分分离
getTodoItem() {
return this.state.list.map( (item,index) => {
return (
<TodoItem key={item} content={item} index={index} deleteItem={this.handleItemDelete}/>
)
} )
}
handleInputChange(){
const value = this.input.value;
this.setState( () => { inputValue:value } )
}
handleBtnClick() {
this.setState((prevState) =>({
list:[...prevState.list,prevState.inputValue],
inputValue: ''
}), () => { console.log(this.ul.querySelectorAll('div').length) })
}
handleItemDelete(index) {}
四.子组件
import React, { Component } from 'react';
import PropTypes from 'props-types';//参数约束
class TodoItem extends Component {
constructor() {
super(props);
this.handleClick = this.handleClick.bind(this);
}
//代码优化
//由于父组件的更新就会引发子组件的更新,但是这样损耗了性能
//通过shouldComponentUpdate来判断,只有该组件相关的参数发生更新再更新
shouldComponentUpdate(nextProps,nextState){
if(nextProps.content !== this.props.content) {
return true;
}else{
return true
}
}
render(){
const { content,test } = this.props; //代码优化
// return <div onClick={ this.handleClick }>{ this.props.content }</div>
return (<div onClick={ this.handleClick }>{ test } - { content }</div>)
}
handleClick(){
const { deleteItem, index } = this.props;
deleteItem(index);
}
//一个组件要从父组件接收参数
//只要父组件的render函数被执行了,子组件的这个生命周期函数就会被执行
//如果这个组件第一次存在于父组件中,不会执行
//如果这个组件之前已经存在于父组件中,才会执行
componentWillReceiveProps() {}
}
TodoItem.propTypes = {
test:PropTypes.string.isRequired,//PropTypes.oneOfType(PropTypes.number,PropTypes.func)
}
TodoItem.defaultProps = {
test:'hello world'
}
export default TodoItem
五、App.js
important React, { Component, Fragment } from 'react';
important { CSSTransition, TransitionGroup } from 'react-transition-group'
important './style.css'
class App extends Component {
constructor((props){
super(props);
this.state = {
list: []
}
this.handleAddItem = this.handleAddItem.bind(this);
}
render() {
return (
<Fragment>
<TransitionGroup>
this.state.list.map((item,index) => {
return (
<CSSTransition timeout = {1000} classNames='fade' unmountOnExit
onEntered={(el) => {el.style.color='blue'} appear={true} key={index}}>
<div>{item}</div>
</CSSTransition>
)
})
<TransitionGroup>
<Fragment>
)
}
}
react中的css动画
1.原生
image.png
image.png
2.通过组件 react-transition
image.png
image.png
image.png
六、Redux
1.redux的工作流程
image.png
2.引入
image.png
引入redux调试工具到代码需要做以下配置
image.png
3.引入redux后的TodoList
1.引入store,删除了本文件的state
import React, { Component } from 'react'
//按需引入antd组件
import 'antd/dist/antd.css'
import { Input,Button,List} from 'antd';
import store from './store';//
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this)
this.handleBtnClick= this.handleBtnClick.bind(this)
this.handleItemDelete= this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange);
}
//在组件即将被挂在到页面的时候自动执行
componentWillMount(){}
render(){
return(
<Fragment>
<div>
<Input placeholder='todo info' className='input' value={this.state.inputValue} onChange= {this.handleInputChange} ref={(input) => {this.input = input}}/>
<Button type='primary' onClick={this.handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop:'10px',width:"300px"}}
bordered
dataSource={this.state.list}
renderItem={ item => (<List.Item>{item}</List.Item>) }
/>
// <ul> { this.getTodoItem() }</ul>
<Fragment>
)
}
}
//组件被挂载到页面之后,自动被执行
componentDidMount() {}
//组件被更新之前,他会自动被执行
shouldComponentUpdate(){}
//如果被更新之前,它会自动执行,但是她在shouldComponentUpdate之后,
//如果shouldComponentUpdate返回false,这个函数不会被执行
componentWillUpdate() {}
handleInputChange(e){
//1.
// const value = this.input.value;
// this.setState( () => { inputValue:value } )
//2.
// const action = { type:'change_input_value',value:e.target.value }
//store.dispatch(action);
//3.使用actionCreator.js统一创建action
const action = getInputChangeAction(e.target.value);
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleBtnClick() {
// this.setState((prevState) =>({
// list:[...prevState.list,prevState.inputValue],
// inputValue: ''
// }), () => { console.log(this.ul.querySelectorAll('div').length) })
//ActionTypes的拆分
const action = { type:ADD_TODO_ITEM };
store.dispatch(action);
}
handleItemDelete(index) {}
export default TodoList;
4.actionTypes.js的使用
image.png
5.reducer.js的使用
image.png
6.使用actionCreator.js统一创建action
image.png
7.store的几个方法
image.png
七、容器组件和UI组件(傻瓜组件)
容器组件
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this)
this.handleBtnClick= this.handleBtnClick.bind(this)
this.handleItemDelete= this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange);
}
render(){
return(
<TodoListUI inputValue={this.state.inputValue} list={this.state.list}
handleInputChange = { this.handleInputChange} handleBtnClick =
{this.handleBtnClick} />
)
}
}
handleInputChange(e){
const action = getInputChangeAction(e.target.value);
store.dispatch(action);
}
UI组件
class TodoListUI extends Component {
render () {
const { inputValue,handleInputChange,handleBtnClick,list } = this.props;
rerurn (
<div>
<div>
<Input placeholder='todo info' className='input' value=
{inputValue} onChange= {handleInputChange} ref={(input) =>
{this.input = input}}/>
<Button type='primary' onClick={handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop:'10px',width:"300px"}}
bordered
dataSource={list}
renderItem={ item => (<List.Item>{item}</List.Item>) }
/>
</div>
)
}
}
傻瓜组件也可以改写成函数形式,加快性能
image.png
八、使用Redux-thunk中间件进行ajax请求
1.引入和配置
image.png
windows配置
image.png
2.ajax异步请求
image.png image.png
3.中间件的工作原理(作用在action和store之间)
image.png
4.扩展(redux-saga对大型项目而言更合适)
image.png
image.png
九、react-redux的使用
1.Provider
image.png
2.connect
import React, { Component } from 'react'
import store from './store';
import connect from 'react-redux';
class TodoList extends Component {
render() {}
}
const mapStateToProps = (state) => {
return {
inputValue:state.inputValue;
}
}
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue(e){
const action = {
type:'change',
value:e.target.value
}
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(TodoList)
十、样式
1.styled-components的使用(npm i styled-components)
全局样式
image.png
组件样式
image.png
image.png
写法
image.png
image.png
image.png
image.png
2.iconfont使用
image.pngimage.png
十一、优化以及工具的使用
1.combineReducer的使用,便于组件中数据的管理
image.png
2.actionCreators和constants的拆分
3.immutable.js,阻止随意更改state
image.png
image.png
image.png
image.png
image.png
image.png
十二、路由(npm i react-router-dom)
1.App.js
import React, { Component } from 'react'
import store from './store';
import { Provider } from 'react-redux';
import Header from './common/header'
important Home from './pages/home'
import { BrowserRouter, Route } from 'react-router-dom'
class App extends Component{
render() {
return (
<Provider store={store}>
<div>
<Header/>
<BrowserRouter>
<Route path='/' exact render={ ()=><div>home</div>}></Route>
<Route path='/detail' exact component={Home}}></Route>
<Route path='/detail/:id' exact component={Home}}></Route>
</BrowserRouter>
<div>
</Provider>
)
}
}
2.detail/index.js
1.获取路由参数
componentDidMount() {
this.props.getDetail(this.props.match.params.id);
}
3.路由参数获取
image.png
4.路由跳转
image.png
十三、服务器
1、安装
image.png
2.使用
image.png
网友评论