关于react@5.x 学习顺序及重点总结

关于react@5.x 学习顺序及重点总结

1.开发环境搭建

npx create-react-app myapp

2.react中的组件

import React,{Component} from 'react'
import ReactDom from 'react-dom'
    
 
    class App extends Component{
        constructor(props) {
            super(props)
        }
        render() {
           return (<div>hello world</div>) 
        }
    }
​
ReactDom.render(
<App/>,document.getElementById('root')
)

3.jsx语法

React.createElement('div',className:'title','hello world')
​
createElement方法有三个参数,第一个是要创建的标签,第二个参数是标签的属性,第三个参数是标签的内容
​
​
只是原生的写法,使用脚手架构建项目的话,可以简化第二个参数
使用ReactDOM中的render方法将元素渲染到根节点上
​
ReactDOM.render(a,document.querySelector('#root'))

4.react中的占位符

import React,{Component,Fragment} from 'react'
<Fragment></Fragment>可以代替render函数最外层包裹的标签,这样结构中就不会有多余的元素

5.响应式设计思想和事件绑定

constructor(props) {
    super(props)
    this.state = {
        inputValue:'hello',
        list:[]
    }
}
​
<input value={this.state.inputValue} onChange={this.handleInputChange.bind(this)} </input>
    <button onClick={this.handleClick.bind(this)}>提交</button>
    
 handleInputChange(e) {
        this.setState({
            inputValue:e.target.value
        })
}
    
handleClick() {
    this.setState({
         list:[...this.state.list,this.state.inputValue]
        })
 }

6.循环渲染

<ul>
    {
    this.state.list.map((item,index)=>(<li key={index}>{item}</li>)
    )
​
    }
</ul>

7.想要渲染出html标签的时候

{
    this.state.list.map((item,index)=>(<li key={index} dangersousSetInnerHtml={{__html:item}}></li>)
    )
​
}

8.组件之间的传值

父组件向子组件传值通过属性的形式传递
​
父组件传递
<TodoItem content={item}/>
    
子组件接收
class TodoItem extends Component {
    render() {
        return <div>{this.props.content}</div>
    }
​
}
 

9.setState优化

this.setState(()=>({
    list:[...this.state.list,this.state.inputValue],
    inputValue:''
}))

10.PropTypes和DefaultProps

import  PropTypes from 'prop-types'

TodoItem.propTypes = {
    content:PropTypes.String,//父组件传递过来的content必须是字符串类型
    deleteItem:PropTypes.func,
    test:PropTypes.String.isRequired
}

更多用法,查看react文档的 Typechecking with propTypes

TodoItem.defaultTypes = {   //给接收的属性设置默认值
    test:'hello world' 
}

11.props,State与render函数之间的关系

1.当组件的props或者State发生改变的时候,组件的render函数就会重新执行

2.当父组件的render函数被运行时,他的子组件的render都将被重新执行一遍

12.react中的虚拟dom以及虚拟dom中的diff算法

13.react中ref的使用

<input ref={(input)=>this.input=input}></input>    this.input指向当前的dom节点

使用的时候只要使用this.input就能获取到当前元素

14.react中的生命周期函数

分为四个阶段

1.Initialization
setup props and state

2.Mounting

componentWillMount---->render----->componentDidMount

3.Updation
这里有两种情况,一种是props更新,一种是states更新
 
	3.1 props更新                                           true向下执行
    	componentWillReceiveProps---->shouldComponentUpdate--->componentWillUpdate--->render---->componentDidUpdate
        													false不会在向下执行
        
        state更新
        shouldComponentUpdate---->componentWillUpdate---->render---->componentDidUpdate
        
        
        组件被更新之前,shouldComponentUpdate会自动执行,他需要返回一个布尔值
        shouldComponent(){
            return true   
		}
        
		componentDidUpdate() {  //组件更新完成之后会被执行
		}

		componentWillReceiveProps() {
            //当一个组件要从父组件接收参数
            //只要父组件的render函数被(重新)执行了,子组件的这个生命周期函数会执行
            //如果这个组件第一次存在父组件中不会执行
            //如果这个组件之前已经存在于父组件中才会执行
        }
		
 4.Unmounting
 compoentWillUnmount () {
	//当这个组件即将从页面中删除的时候,会被执行
 }

15.生命周期函数的使用场景

shouldComponentUpdate(nextProps,nextState) { //两个默认参数,nextProps和nextState,假设子组件中接受一个content的prop
    if(nextProps.content!==this.props.content) {
        return true
	}else {
		return false
    }
}


componentDidMount() {
	//ajax请求放在这里面
}

16.react中使用css动画效果

github中react-transtion-group项目
import {CSSTranstion} from 'react-transition-group'

<CSSTranstion
	in={this.state.show}
	timeout={1000}
	classNames='fade'
	unmountOnExit   //当动画执行完成之后动画被移除
    onEntered={(el)=>el.style.color='blue'}  //当入场动画结束之后会自动执行的钩子
    appear={true}   //第一次展示hello时候也要动画效果   增加的类名是  .fade-active  .fade-appear-active
> 
    <div>hello</div>
</CSSTranstion>

更多细节查看文档...

17.多个元素之间的动画效果

import {TransitionGroup} from 'react-transition-group'
<TransitionGroup>
	{
		this.list.map((item,index)=>{
            return (
            
                
                <CSSTranstion
					in={this.state.show}
					timeout={1000}
					classNames='fade'
					unmountOnExit   //当动画执行完成之后动画被移除
                    onEntered={(el)=>el.style.color='blue'}  //当入场动画结束之后会自动执行的钩子
    				appear={true}   //第一次展示hello时候也要动画效果   增加的类名是  .fade-active  .fade-appear-active
				> 
    				<div key={index}>{item}</div>
				</CSSTranstion>
            
            
            )	
        })
    }


</TransitionGroup>

18.redux工作流程

 

19.创建redux中的store

1.store文件夹下的store.js
	import {createStore} from 'redux'
	import reducer from './reducer.js'
	const strore = createStore(reducer)
	export store
2.reducer.js
	const defaultState = {
        inputValue:'',
        list:[]
    }
	export default = (state,action)=>{
        if(action.type==='change_input_value') {
		const newState = JSON.parse(JSON.stringify(state))
    	newState.inputValue = action.value
        return newState
	}
        return state
}
    
3.组件中取值
constructor(props) {
	super(props)
    this.state = store.getState()
    store.subscribe(this.handleStoreChange)
}

4.重新渲染页面
handleStoreChange() {
    this.setState(store.getState())
}

20.将变量统一放到constants.js文件中,这样有这方面的错误可以直接报错

21.所有的action都是用actionCreator来创建,方便测试和管理

22.UI组件又叫傻瓜组件,他只负责页面的展示,没有逻辑代码

23.无状态组件

//当我们的组件中只有一个render函数的时候,我们就可以使用无状态组件来定义这个组件

const TodoList = (props)=>{
    return (
    <div>hello world</div>
    )
}
无状态组件的性能比较高,他就是一个函数,无状态组件要执行的函数只有render函数

24.redux中常用的两个中间件

中间件指的是redux的中间件,而不是react的


1.redux-thunk
在github中搜索redux-thunk项目
//关键代码:
import {createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
const store = createStore(reducer,applyMiddleware(thunk))

如果需要使用调试工具的话,需要查看调试工具的文档,进行配置

使用了redux-thunk之后,可以使actionCreators中创建的action是一个函数,也就是里面的函数的返回值可以是一个函数
export const getTodoList = ()=>{
	return (dispatch)=>{
        axios.get('/api/getlist.json').then((res)=>{
            const data = res.data
            const action = initListAction(data)
            dispatch(action)
	})
	}
}
2.redux-saga中间件
在github中搜索redux-saga项目
//关键代码:
import {createStore,applyMiddleware} from 'redux'
import mySaga from './sagas.js'  //自己创建的saga文件
import createSageMiddleware from 'redux-saga'
const store = createStore(reducer,applyMiddleware(createSageMiddleware))

sagaMiddleware.run(mySaga)

//配置过之后,saga.js文件中也能接受到action

//saga.js文件中的内容
import {takeEvery} from 'redux-saga/effects'
import {GET_INIT_LIST} from './actionTypes'
import  {initListAction} from './actionCreators'

function* getInitList() {
   const res = yield axios.get('/api/getlist.json')
	const action = 	initListAction(res.data)
    yield put(action)   //使用put方法将action传递给reducer  
}


function * mySage() {
    yield takeEvery(GET_INIT_LIST,getInitList)   //第一个参数是action的类型 ,一旦执行到这个action,就执行后面的方法
}
export default mySage


在做大型项目的时候,redux-saga是优于redux-thunk的

25.第三方模块react-redux的使用

import {Provider} from 'react-redux'
import store from './store'
const App = (
	<Provider store={store}>
        <TodoList/>
	</Provider>
)
ReactDOM.render(App,document.getElementById('root'))   //Provider会将store提供给内部的所有组件



在组件的文件中
import {connect} from 'react-redux'

const mapState = (state)=>({
    inputValue:state.inputValue
})

const mapDispatch = (dispatch)=>({
	changeInputValue() {

    }
})


export default connect(mapState,mapDispatch)(TodoList)

26.styled-components使用

//在gitub上搜索styled-components项目

使用reset.css对项目的css样式进行初始化   官网:https://meyerweb.com/eric/tools/css/reset/


代码示范:
组件文件中:
import {HeaderWrapper} from './style.js'
class Header extends Component {
	render() {
	return (<HeaderWrapper>hello</HeaderWrapper>)
   }
}

style.js文件中
export const HeaderWrapper = styled.div`
width:100px;
height:200px;
`

27.使用combineReducers完成对数据的拆分管理

全局的store文件夹下 import {combineReducers} from 'redux' import {reducer as headerReducer} from '../common/header/store' const reducer = ()=>({ header:headerReducer }) export default reducer

28.使用immutable统一数据格式

reducer.js文件中
import {fromJS} from 'immutable'
const defaultState = fromJS({
    focused:true
})

将import {combineReducers} from 'redux'改为 import {combineReducers} from 'redux-immutable'

const mapState = (state)=>({
    focused:state.get('header').get('focused')
   //也可以写成下面这种
    focused:state.getIn(['header','focused'])
})

29.reducer文件中的if语句可以改写成switch语句来提升性能

import * as constants from './constants.js'
export default(state=defaultState,action)=>{
    switch(action.type) {
        case constants.SEARCH_FOCUS :
            return state.set('focused',true);
        case constants.CHANGE_LIST :
            return state.merge({     //merge的性能更高,连续调用set会生成多个immutable对象
                list:action.data,
                totalPage:action.totalPage
            })
        default:
            return state
    }
}

30.react@5.0.0下的路由的使用方法

import {BrowserHistory,Route} from 'react-router-dom'

class App extends Component {
	render() {
        <BrowserHistory>
            <Route path='/' exact component={<Home/>}></Route>
            <Route path='/detail' exact component={<detail/>}></Route>
        </BrowserHistory>
    }
}

31.性能优化

将import React,{Component} from  'react' 改为import React,{PureComponent} from 'react'
PureComponent在底层实现了一个shouldComponentUpdate,只有当当前组件的props或者state改变时他才会重新执行render函数,当只有他的父组件改变时,不执行当前子组件的render函数

不过使用PureComponent就使用immutable来管理数据,不然可能会有坑

32.页面跳转

import {Link} from 'react-router-dom'
{
    list.map((item,index)=>{
        return(
        <Link key={index} to={'detail' + item.get('id')}>
            <ListItem>
                <img src={item.get(imgUrl)}/>
                <ListInfo>
                    <h3 className='title'>{item.get('title')}</h3>
                    <p>{item.get('desc')}</p>
                </ListInfo>
             </ListItem> 
        </Link>
            
        )
    })
}

<Route path='/detail/:id' exact component={<detail/>}></Route>
这个参数获取的方式是: const id = this.props.match.params.id

 <Route path='/detail' exact component={<detail/>}></Route>
这个参数获取的方式是: const res = this.props.location.search  //  '?id=2'

33.react中的异步组件

需要使用一个react-loadable的包
yarn add react-loadable

在store文件夹下创建loadable.js
import React,{Component} from 'react'
import {Loadable} from 'react-loadable'
const LoadableComponent  = Loadable({
    loader:()=>import('./reducer.js'),
    loading() {   //在加载伟完成时页面显示的临时内容
        return (
            <div>正在加载...</div>
        )
    }
})

导出一个组件,有下面两种写法

export default class App extends Component {
   render() {
        return (<LoadableComponent/>)
   }
}

也可以象下面这样,导出一个无状态组件
export default ()=><LoadableComponent/>

34.如果要设置元素上的属性的时候

export const NavSearch = styled.input.attrs({
    placeHolder:'搜索'
})`
width:200px;
height:30px;
`

35.如果reducer的内容较多时,可以对其进行拆分,方便管理

const changeHomeData=(state,action)=> {
  return state.merge({
    topicList: fromJS(action.topicList),
    articleList: fromJS(action.articleList),
    recommandList: fromJS(action.recommandList)
  });
}

const addArticleData = (state,action) => {
  return state.merge({
    'articleList': state.get('articleList').concat(action.articleList),
    'page':action.nextPage
  })
}



export default (state = defaultState, action) => {
  switch (action.type) {
    case constants.CAHNGE_HOME_DATA:
      return changeHomeData(state,action)
    case constants.ADD_ARTICLE_DATA:
      return addArticleData(state,action)
    case constants.CAHNGE_SCROLL_TOP:
      return state.set('showScroll',action.show)
    default:
      return state
  }
 
}

36.登录鉴权

import {Redirect} from 'react-router-dom'


class Login extends PureComponent {
  render() {
    const { toLogin,loginStatus } = this.props
  
    {
      if (!loginStatus) { //控制登录状态的变量
        return (
             <LoginWrapper>
              <LoginBox>
                <Input placeholder='账号'  ref={(input)=>{this.account=input} }/>
                <Input placeholder='密码' type='password' ref={(input)=>{this.password=input} }/>
               <Button onClick={()=>{toLogin(this.account,this.password)}}>登录</Button>
            </LoginBox>
          </LoginWrapper>
        )
      } else {
        return (
          <Redirect to='/'/>
        )
      }
     }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值