关于React的入门知识

2019-07-16  本文已影响0人  吴一晏
  1. 受控组件 V.S. 非受控组件

     <FInput value={x} onChange={fn}/> 受控组件:渲染表单的React组件 还控制着 用户输入表单时变化的操作,每次状态变化都调用onChange,这种组件叫受控组件。表单数据是由 React 组件来管理的。
     <FInput defaultValue={x} ref={input}/> 非受控组件:React赋予组件一个初始值,但是不去控制后续的更新。表单数据将交由 DOM 节点来处理。
    
    
  1. React 有哪些生命周期函数?分别有什么用?(Ajax请求放在哪个阶段?)
    初始化阶段:
    componentWillMount()组件即将被渲染到页面之前触发,此时可以进行开启定时器、向服务器发送请求等操作
    render()组件渲染
    componentDidMount()组件已经被渲染到页面中后触发:此时页面中有了真正的DOM的元素,可以进行DOM相关的操作
    运行中阶段:
    componentWillReceiveProps()组件接收到属性时触发
    shouldComponentUpdate()当组件接收到新属性,或者组件的状态发生改变时触发。组件首次渲染时并不会触发
    componentWillUpdate()组件即将被更新时触发
    render()
    componentDidUpdate()组件被更新完成后触发。页面中产生了新的DOM的元素,可以进行DOM操作
    销毁阶段
    componentWillUnmount() 组件被销毁时触发。
    1. componentDidMount()中请求数据。
  2. React 如何实现组件间通信?
    1. 父子靠props 传函数
    2. 爷孙可以穿两次props
    3. 任意组件用 Redux(也可以自己写一个 eventBus
  3. shouldComponentUpdate 有什么用?
    1. 用于在没有必要更新 UI 的时候返回 false,以提高渲染性能。
    2. 但是不要滥用,这是React提供的一个紧急出口,必要的时候再使用,因为它的维护成本比较高,比如你新加了一个props,但是又忘记在shouldComponentUpdate 写,就会引起bug。
    3. 如何优化?
  4. 虚拟 DOM 是什么?
    1. 要点:虚拟 DOM 就是用来模拟 DOM 的一个对象,这个对象拥有一些重要属性,并且更新 UI 主要就是通过对比(DIFF)旧的虚拟 DOM 树 和新的虚拟 DOM 树的区别完成的。
    2. 参考:http://foio.github.io/virtual-dom/
  5. 什么是高阶组件?
    1. 文档原话——高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。
    2. React-Redux 里 connect 就是一个高阶组件,比如 connect(mapState)(MyComponent) 接受组件 MyComponent,返回一个具有状态的新 MyComponent 组件。
  6. React diff 的原理是什么?
    首先,React diff遵循三个策略:1. Web UI 中,DOM节点跨层级的移动操作特别少,可以忽略不计。2.拥有相同类的两个组件将生成相似的树形结构,拥有不同类的两个组件将生成不同的树形结构。3. 对于同一层级的一组子节点,可以通过唯一id来区分它们。基于以上三个策略,React分别对tree diff、component diff、element diff进行了算法优化。
  1. Redux 是什么?
    1. ReduxJavaScript 状态管理工具,提供可预测化的状态管理。
    2. Action:是把数据从应用传到 Store 的有效载荷。它是 Store 数据的唯一来源。改变 State 的唯一办法,就是使用 Action。
import { ADD_TODO } from "../actionTypes";

export const addTodo = (payload:any) => {
    return {
        type: ADD_TODO,
        payload
    }
}

Reducers: 指定了应用状态的变化如何响应 actions并发送到store 的,记住 actions只是描述了有事情发生了这一事实,并没有描述应用如何更新 state
Reducer 是一个函数,它接受 Action 和当前State 作为参数,返回一个新的 State
我们还可以将拆分后的Reducer 放到不同的文件中, 以保持其独立性并用于专门处理不同的数据域。然后使用combineReducers将多个Reducer合并成一个,输出成一个大的对象。

import { ADD_TODO } from "../actionTypes";

export default function (state = [],action:any) {
    switch (action.type){
        case ADD_TODO:
            return [...state,action.payload]
        default:
            return state
    }
}

import { ADD_TOMATO } from "../actionTypes";

export default function (state = [], action: any) {
    switch(action.type) {
        case ADD_TOMATO:
            return [...state, action.payload]
        default:
            return state
    }
}
//使用combineReducers
import { combineReducers } from "redux";
import todos from './todos'
import tomatoes from './tomatoes'

export default combineReducers({ todos, tomatoes });

Store: 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 StoreRedux提供createStore这个函数,接受reducers,用来生成 Store

import { createStore } from "redux";
import rootReducer from "./reducers"; 

const store = createStore(rootReducer)

export default store

Store有以下职责:

connect:该API连接React组件与 Redux store,连接操作不会改变原来的组件类。反而返回一个新的已与 Redux store 连接的组件类。connect可以接受参数,将参数注入到组件当中

const mapStateToProps = (state: { todos: any; }, ownProps: any) => ({//注入props
    ...ownProps
})

const mapDispatchToProps = {//注入属性
    editTodo, 
    updateTodo
}

export default connect(mapStateToProps, mapDispatchToProps)(todoItem)

<Provider store> 使组件层级中的 connect()方法都能够获得 Redux store。正常情况下,你的根组件应该嵌套在 <Provider> 中才能使用 connect() 方法。

ReactDOM.render(
  <Provider store={store}>
    <MyRootComponent />
  </Provider>,
  rootEl
)
  1. connect 的原理是什么?
    react-redux 库提供的一个 API,connect的作用是让你把组件和store连接起来,产生一个新的组件(connect 是高阶组件)。

1.首先connect之所以会成功,是因为Provider组件:
- 在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
- 接收Reduxstore作为props,通过context对象传递给子孙组件上的connect

2.connect做了什么:它真正连接ReduxReact,它包在我们的容器组件的外一层,它接收上面Provider 提供的store里面的statedispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。

3.主逻辑源码

export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
  return function wrapWithConnect(WrappedComponent) {
    class Connect extends Component {
      constructor(props, context) {
        // 从祖先Component处获得store
        this.store = props.store || context.store
        this.stateProps = computeStateProps(this.store, props)
        this.dispatchProps = computeDispatchProps(this.store, props)
        this.state = { storeState: null }
        // 对stateProps、dispatchProps、parentProps进行合并
        this.updateState()
      }
      shouldComponentUpdate(nextProps, nextState) {
        // 进行判断,当数据发生改变时,Component重新渲染
        if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
          this.updateState(nextProps)
            return true
          }
        }
        componentDidMount() {
          // 改变Component的state
          this.store.subscribe(() = {
            this.setState({
              storeState: this.store.getState()
            })
          })
        }
        render() {
          // 生成包裹组件Connect
          return (
            <WrappedComponent {...this.nextState} />
          )
        }
      }
      Connect.contextTypes = {
        store: storeShape
      }
      return Connect;
    }
  }

connect是一个高阶函数,首先传入mapStateToPropsmapDispatchToProps等参数,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件,该组件具有如下特点:

上一篇下一篇

猜你喜欢

热点阅读