React学习笔记

802 阅读9分钟

1.关于setState什么时候是同步什么时候是异步的问题

  • setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
  • setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果
  • setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和 setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState ,setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。
  • libin1991.github.io/2017/09/21/…

2.展开运算符...

直接复制数组复制的是指向数组的指针,改变list时,this.state.list也会改变
使用展开运算符可以实现数组复制,且复制后两者不受影响。

3.用React展示html代码——dangerousSetInnerHTML

dangerouslySetInnerHTMl 是React标签的一个属性;有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;既可以插入DOM,又可以插入字符串;不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击的原因之一。

4.扩展光标聚焦——label

属性for为避免与循环for冲突,在React中改为htmlFor

5.父组件--子组件

【单向数据流】父组件可以向自组件传值,但子组件不能改变父组件的值

父组件向子组件传递数据,在父组件页面的子组件后面添加属性,在子组件页面通过{this.props.属性名}调用。

子组件中调用父组件的方法改变父组件的数据,注意this的指向做绑定

6.直接在构造函数里绑定this指针的指向

7.ES6函数中直接返回对象

8.???异步 变量外层保存

9.propTypes和defaultProps

propTypes:校验外部传入的属性的类型,可以是多种类型(如content),或规定其是否必须(如test)
defaultProps:设置传入属性的默认值
(使用前记得导入import PropTypes from 'prop-types';)

10.当组件的state或props发生变化时,render()函数就会重新执行;

当父组件的render()函数被运行时,子组件的render()函数都会被重新运行。 如果子组件在页面上直接使用父组件的属性,会获得同步更新。但如果子组件的state依赖于父组件,需要在componentWillReciveProps中手动setState进行子组件的state更新

11.虚拟DOM底层实现

  • state数据
  • JSX模版
  • 数据+模版 生成虚拟DOM(虚拟DOM就是一个js对象,用它来描述真实DOM)(损耗性能)
    eg:['div', {id: 'abc'},['span', {}, 'hello world']]
  • 用虚拟DOM的结构生成真实的DOM来显示
    eg:<div><span>hello world</span></div>
  • state发生变化
  • 数据+模版 生成新的虚拟DOM (极大提升来性能)
    eg:['div', {id: 'abc'},['span', {}, 'bye bye']]
  • 比较原始虚拟DOM和新的虚拟DOM的区别,找去不同不分的内容
  • 直接操作DOM,改变发生变化的内容

eg:return <div></span>item</span></div>
底层= JSX => createElement => 虚拟DOM(js对象)=> 真实DOM
return React.createElement('div', {}, React.create('span', {}, 'item'))

优点:

  • 极大提升来性能
  • 使得跨端应用得以实现。React Native

12.关于Diff算法

  • 短间隔的多次setState可以结合成一次,减少虚拟DOM比对次数,优化性能
  • 虚拟DOM比对时采用【同层比对】,从上至下,逐层比对。当发现有不同时,不再向下比对,直接废弃掉下层的虚拟DOM,直接用新的替换真实DOM
  • 列表循环时引入key值,提高虚拟DOM比对的性能 。key值要保持稳定,尽量不要用index 做key值

13.

  • arrayOf()表示输入的要求是数组,数组内容可以为number或者string
  • oneOfType()表示输入的内容是number或者string,参数以数组的形式给出 \

14.ref——操作DOM,获取DOM元素

构建一个ref引用,函数形式。该函数自动接受参数input(input标签对应的DOM元素),下面即可直接使用this.input代替e.target

  • e.target的结果是input对应的DOM元素节点\
  • 不推荐使用ref,尽量不要直接操作DOM元素

15.生命周期函数

生命周期函数指某一时刻组件会自动调用执行的函数(如render()函数)

  • Initialization
    • constructor():设置props, state
  • Mounting
    • componentWillMount():组件即将被挂载(组件第一次在页面上展示)到页面之前被自动执行
    • render():必须存在且自定义
    • componentDidMount():组件被挂载到页面之后被自动执行
  • Upnation (props, state)
    • componentWillReceiveProps: (只针对props)一个组件要从父组件接收参数。只要父组件的render函数被重新执行了,子组件的这个生命周期函数就会被执行(该组件之前存在于父组件中,才会执行)。
    • shouldComponentUpdate():组件被更新之前,被自动执行。该函数返回一个bool值,若返回false,组件不会更新;一般返回true,执行下面的更新流程。
    • componentWillUpdate():组件被更新之前,它会自动执行。但是在shouldComponentUpdate()之后执行。若shouldComponentUpdate()返回false,它不会执行。
    • render()
    • componentDidUpdate:组件被更新之后,它会执行
  • Unmounting
    • componentWillUnmount():组件即将被从页面中移除时自动执行

16.性能优化

父组件的render函数执行时,子组件的render会被重新执行。损耗性能。 使用shouldComponentUpdate函数,比较当前状态和下一个状态的需要改变的内容是否相同,不相同时才执行子组件的render函数
(其他性能优化方法:在constructor里进行函数的指针绑定;diff算法同层比较;setState函数异步,可以把多次数据更新合并成一次)

17.发送ajax请求

使用axios扩展工具,写在componentDidMount函数里

18.CSS实现

  • 过渡效果

  • 动画效果

forwards 表示保留变化后最后一帧的CSS样式

19.react-transition-group

在需要添加样式的标签外层嵌套<CSSTransiton></CSSTransition>

  • in: 绑定参数,根据还参数的变换判断是出场(false)还是入场(true)
  • timeout: 完成需要的时间
  • classNames: css样式前缀
  • unmountOnExit: 出场时删除对应DOM元素
  • appear: 第一次载入页面时的样式(默认false。为true时,可以为其设置样式)

  • <TransitionGroup>组件管理列表中的一组<Transition>组件。<TransitionGroup>是一种状态机,用于管理组件随时间的安装和卸载。
  • 可以在<TransitionGroup>中使用任何<Transition>组件,而不仅仅是css。
  • 要把所有需要管理的列表项都写在<TransitionGroup> 中,其次,<CSSTranstion> 组件的in属性此时由<TransitionGroup> 管理了
  • 当点击按钮后,将会把此项添加到列表中,此时in属性为true,同时默认设置了首次动画,所以会触发一次进场动画。

20.Redux工作流

21.流程实现

  • 创建store
  • 创建reducer

  • 组件连接store,通过this.state = store.getState();获得store中的数据

  • 定义action,然后使用store.dispatch(action);传递给store。store接受到后,自动将当前数据和接收到的action转发给reducer
  • reducer对数据进行处理,返回新数据给store (reducer可以接收state,但绝不能修改state。const newState = JSON.parse(JSON.stringify(state));深拷贝后对数据进行操作)
  • 组件更新。store.subscribe(this.handleStoreChange);store内容发生改变时,自动调用作为参数的该函数
    在该函数中,再次获取store的值即可
  • 可用过定义action中的type值方便调试
  • 可以创建一个actionCreate.js文件,存放所有action,在组件里直接调用即可

22.关于Redux

  • store是唯一的
  • 只有store能改变自己的内容
  • Reducer必须是纯函数(纯函数:给定固定输入,一定有固定输出,并且不会有任何副作用)

23.组件

  • 普通组件
  • 容器组件:一般负责逻辑部分
  • UI组件:一般负责页面渲染
  • 无状态组件:如果一个组件只有render函数,可以将其写成无状态组件。无状态组件是一个函数,性能比普通组件高。

24.redux-thunk 中间件

中间件指的是action和store的中间。它使得dispatch接收的action不仅可以是一个对象,还可以是一个函数。这样就可以将异步请求的代码写在action对应的函数里。当action是一个函数时,执行store.dispatch(action);时会自动调用action的函数,该函数可以接收一个dispatch的参数,在函数体里直接dispatch(action)即可。

25.同时使用redux开发工具和redux-thunk中间件


import thunk from 'redux-thunk';
import reducer from './reducer.js'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
	applyMiddleware(thunk),
	);
const store = createStore(reducer, enhancer);

export default store;

26.redux-saga 中间件

  • 在index.js中配置saga
import createSagaMiddleware from 'redux-saga';

import reducer from './reducer.js';
import todoSagas from './sagas.js';

const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));
const store = createStore(reducer, enhancer);
sagaMiddleware.run(todoSagas);

export default store;
  • 将异步请求代码写在sagas.js文件中

该文件中需要一个mySaga函数并导出。这样当派发action时,不仅reducer可以收到,sagas也可以收到。takeEvery第一个参数为接收到的action的type,第二个参数表示当type等于参数一时需要执行的函数。在该函数里可以编写异步请求代码。用yield put(action);代替store.dispatch(action);

27.react-redux

Provide是一个组件,传递store后,Provide里的每一个子组件都可以使用store。

mapStateToProps()将store中的state挂载到组件的props上,然后就可以通过this.props代替this.state mapDispatchToProps()将dispatch()方法挂载到组件的props上。里面编写action,直接调用dispatch方法