https://note.youdao.com/ynote...all in js单向数据流Fragment:占位符,替换最外层DIV事件方法绑定//方法一 <input value={inputVal} onChange={this.handleInputChange.bind(this)} /> <input value={inputVal}//方法一-传递下标 onChange={this.handleInputChange.bind(this),index} />//方法2//this 的绑定放在构造函数里, 这样函数的this 永远指向这个组件constructor(){this.handleInputChange = this.handleInputChange.bind(this)}handleInputChange(){console.log(this);}改变状态值-setStatesetState 可以接受一个参数preState (和构造函数里state保持一致)preState: 上一次修改之前数据的状态//方法一this.setState({xxx:xxx})//方法二 —新版本推荐语法this.setState(()=>{return { xxx:xxx}})orthis.setState(()=>({ xxx:xxx }))注释{/xxxxxxxxxxxxxxxxxxxxx/}{/xxxxxxxxxxxxxxxxxxxxxxx/}className代替样式class<div className=‘test’>dangerouslySetInnerHTML//<h1>hello world </h1> 相当于 v-html<div dangerouslySetInnerHTML={{_html:item}}></div>子组件修改父组件内容子组件如何调用父组件方法,修改父组件的数据?只需要把父组件的方法传给子组件,子组件就可以通过这个方法间接的操作父组件的数据传递函数给子组件需要强制把作用域绑定在父组件的thisimport Child from “./Child"class Father extends React.Component{render(){ <div> <Child showFather={this.handleFather.bind(this)}></Child> </div>}handleFather(){ alert(’this is Father’)}}//子组件调用this.props.showFather()propTypes和defaultTypesimport React,{Component} from ‘react’import PropTypes from ‘prop-types’class Test extends Component{}Test.propTypes={content:PropTypes.string,deleteItem:PropTypes.func,index:PropTypes.number,test:PropTypes.string.isRequired,test2:onOfType([PropTypes.number,PropTypes.string])//两个类型都可以,这两个类型中的一个test3:arrayOf(PropTypes.number,PropTypes.string)//数组类型,数组的组成内容可以是数字或者字符}Test.defaultProps={test:“hello world”}Props,State和Render的关系当组件的Props或者state发生改变的时候Render函数就会重新执行父组件的render执行的时候子组件的render也会被执行虚拟dom虚拟dom是一个js对象,用来描述真实DOM在js里面比较js对象不怎么耗性能,但是比较真实的dom会很耗费性能用数组来描述第一个参数是标签名称,第二个参数是属性,第三个方法是子元素[‘div’,{id:“test”},[‘span’,{},‘hello’]]state 数据JSX模板数据+模板结合生成虚拟dom –原始虚拟DOM用虚拟dom的结构,来生成真实DOM,在页面显示"“state发生变化数据+模板结生成新的虚拟dom –新的虚拟dom比较原始虚拟dom和新生成的虚拟dom的区别,区别出有差异的dom直接操作dom 改变内容refref 接受一个箭头函数 (数据驱动,尽量不要用ref) ref使用放在setState的第二个函数里面执行, 确保正确<div ref={(testref)=>{this.testref = testref}}></div>声明周期某一时刻 组件会自动调用执行的函数 生命周期render:渲染页面getDerivedStateFromProps:接受两个参数(props,state)构造函数执行后执行state和props更新也会被执行componentWillMount:组件即将被挂载到页面之前的时候执行(还没有被挂载)componentDidMount:组件被挂载之后制动执行shouldComponentUpdate:组件是否更新,返回布尔值类型,组件更新之前执行componentWillUpdate:组件被更新之前自动,shouldComponentUpdate之后执行,如果shouldComponentUpdate返回true才执行,否则不会被执行componentDidUpdate:组件完成更新之后会被执行componentWillReceiveProps:执行需要满足一下条件当组件从父组件接受了参数如果这个组件第一次存在于父组件中,不会执行如果之前已经存在于父组件中,才会执行componentWillUnmount:这个组件即将从页面中剔除的时候执行生命周期使用场景shouldComponentUpdate(nextProps,nextState):接受两个参数nextProps:接下来我的属性要变成什么样子,nextState 同理;避免组件重复渲染componentDidMount:函数里来执行ajax请求性能提升shouldComponentUpdate:避免渲染函数作用域绑定放在constroctor函数里做,函数作用域绑定只会执行一次,减少子组件的无谓渲染,setState:异步函数, 可以把多次性能的改变结合成一次。降低虚拟DOM的比对频率虚拟dom,同层比对 KEY值比对,提高比对速度React动画效果css过渡动画.show{opacity:1transinition:all 1s ease-in;}.hide{opacity:0; transinition:all 1s ease-in;}css动画效果@keyframes hide-iten{0%{ opacity:1; color:red;}50%{ opacity:0.5; color:green;}100%{ opacity:0; color:blue;}}//forwards:当动画完成后,保持最后一个属性值(在最后一个关键帧中定义)animation: hide-item 2s ease-in forwards;React-transition-groupCSSTransition<CSSTransition in={showValidationMessage} timeout={300} classNames=“message” unmountOnExit onExited={() => {this.setState({ showValidationButton: true,});}} /> // in={showValidationMessage} timeout:动画执行时间 classNames:类名前缀(fade) unmountOnExit:隐藏之后dom被移除.fade-enter{ opacity:0;} .fade-enter-active{ opacity:1; transition:opacity 1s easy-in;} .fade-enter-done{ opacity:1;} .fade-exit{ opacity:1} .fade-exit-active{opacity:0; transition:opacity 1s easy-in;} .fade-done{ opacity:0}CSSTransition会自动的给dom添加一些样式,什么时候添加这个样式由“in”来控制动画执行会在dom元素挂载css类:.fade-enter,.fade-enter-active,.fade-active.done,.fade-exit, .fade-exit-active, .fade-exit-done.fade-enter:当动画执行入场动画时,也就是showValidationMessage由flase变成true的时候,在入场动画执行的第一个时刻,组件会给div挂载.fade-enter,刚要入场还没有入场的时候的状态.fade-enter-active:入场动画执行的第二个时刻,到入场动画执行完成之前。dom上一直会有这个fade-enter-active.fade-active.done:当整个入场动画执行完成之后,.fade-active.done会被添加到dom元素React-transition-groupJS实现动画classNames={{ appear: ‘my-appear’, appearActive: ‘my-active-appear’, enter: ‘my-enter’, enterActive: ‘my-active-enter’, enterDone: ‘my-done-enter, exit: ‘my-exit’, exitActive: ‘my-active-exit’, exitDone: ‘my-done-exit,}}<CSSTransition onExited={() => {this.setState({ showValidationButton: true,});}} //钩子函数(和生命周期函数一样,在某一个时刻自动执行的函数) onEntered={(el)=>{el.style.color = “red”}}onEntered:入场动画执行完成之后执行,该钩子执行,接受一个参数el(CSSTransition内部包裹的元素) el.style.color = “red"onEnter:入场动画执行第一帧的时候执行onEntering:入场动画第二帧,到结束之前执行第一次进入页面加动画第一次展示也要动画效果 appear=true<CSSTransition appear={true} />改功能会在动画执行的第一帧 添加==.fade-appear==<div class=“fade-active fade-appear”>动画第二帧,已经整个动画执行的过程中 添加.fade-appear-activeTransitionGroup多个动画UI组件和容器组件的拆分UI组件负责容器的渲染-傻瓜组件容器组件负责页面的逻辑-容器组件无状态组件一个组件如果只有render函数的时候,可以改写成无状态组件性能会更高,因为它就是一个函数,而不是一个类,所以没有生命周期函数定义UI组件,或者没有逻辑操作 只需要渲染的时候可以定义为无状态组件const test=(props)=>{render(){ return ( <div>{props.test}</div> )}}Redux实例图: 类似于一个图书馆借书流程React Components:用户Action Creators:借书的动作(告诉管理员要借什么书)Store:图书馆管理员负责所有图书的管理(store是唯一的,只有store能改变自己的内容,store拿到reduce返回的数据,再对数据进行更新,reduce只是对数据做处理)Reducers:记录本,记录所有的数据(必须是一个纯函数–给定固定的输入,就一定会有固定的输出,而且不会有任何副作用)React ComponentsAction CreatorsStoreReducers(1)(2) dispatch(action)(3)(previousState,action)(4) (newState)(5)(state)React ComponentsAction CreatorsStoreReducersreduce创建流程1.创建数据管理仓库yarn add redux创建store 文件夹, 创建index.js(store 代码存放位置) index.jsimport {createStore} from ‘redux’;//第二步创建reducer.js后 引入reducerimport reducer from ‘./reducer.js’const store = createStore()export default store2.创建reducer.js(负责对全局数据的更改)根据用户派发的action和value来对state做操作,然后返回新的newstate(固定写法)reducer可以接受state但是绝对不能修改state,所以我们要定义一个新的newState//state:存储所有的数据//设置默认值const defaultState = {inputVal:’’,list:[],}export default (state=defaultState,action)=>{let newState = JSON.parse(JSON.stringify(state))switch (action.type) { case ‘change_input_value’: newState.inputVal = action.value; return newState; break; case ‘add_item’: newState.list.push(newState.inputVal); newState.inputVal = "” return newState; break; default: return state}return state}3.在文件中引入,获取数据store.getState():获取store数据store.dispatch(action):设置更改store数据;(action={type:’’,val})import React from ‘react’import store from ‘store/index.js’class text extends React.component{constructor(props){ super(props) this.state = store.getState() //订阅store状态,发生改变时回调函数自动执行 store.subscribe(()=>{ this.setState(store.getState()) )}submitSatate(val){ const action ={ type:‘change_input_value’, value:val }}}Redux-thunk中间件将异步请求或者复杂的逻辑放到action里来执行https://github.com/reduxjs/re…;如何引入import { createStore, applyMiddleware } from ‘redux’;import thunk from ‘redux-thunk’;import rootReducer from ‘./reducers/index’;// Note: this API requires redux@>=3.1.0const store = createStore( rootReducer, applyMiddleware(thunk));如何使用 普通的action creator返回的是一个对象export const getTodoList=(data)=>({ type:‘TODOLIST’, data})使用redux-thunk 可以在里面返回一个异步函数//返回actionexport const initListAction =(data)=({type:“INIT_LIST_ACTION”,data,})export const getTodoList =()=>{return (dispacth)=>{ axios.get(url).then((res)=>{ const data = res.data; const action = initListAction(data) dispatch(action) })}}在业务代码中使用componentDidMount(){const action = getTodoList();store.dispatch(action)}store.dispatch(action)调用的时候action会自动被执行(此时action是redux-thunk返回的一个函数) redux-thunk中间件是在 action–store中间做操作Redux-saga 中间件https://github.com/redux-saga… 后续补上React-Redux的使用第三方模块,可以帮助我们在React中更加方便的使用Redux核心APIProvider:连接Store,Provier内部的组件都有能力获取到Store里的内容了connect:让组件和sotre做连接安装–首配置npm install –save react-redux//更目录下的index 引入 react-redux,storeimport { Provider } from ‘react-redux’import store from ‘./store/index’//将要渲染在更目录下的组件用provider包裹起来(Provider其实就是一个组件)//将store作为属性值传递给provider,provider内部的组件都有能力获取storeconst App = (<Provider store={store}> <TodoList /></Provider>)//将App作为组件 传递给ReactDOM.render方法ReactDOM.render(<TodoList />, document.getElementById(‘root’));组件内使用,使用Props来获取状态或者派发dispatchimport {connect} from ‘react-redux’;class TodoList extends Component{render(){ return { <div> </div> }}}const mapStateToProps = (state) => { return { inputVal: state.inputVal, list: state.list}}//将Store的dispatch方法挂载到Props方法上//自动disPatch(方法可以直接返回{type:xxx,value:xxx})const mapDispatchToProps = (dispatch) => { return { changeInputValue(e) { let inputVal = e.target.value const action = { type: ‘change_input_value’, inputVal } dispatch(action) },}}export default connect(mapStateToProps, mapDispatchToProps)(TodoList)请求拦截//拦截请求axios.interceptors.request.use(config => {console.log(config)return config})//拦截响应axios.interceptors.response.use(response => { console.log(response)return response})