React学习整理

  • React 的核心特征是“数据驱动视图”,UI = render (data) 或者 UI = f (data)。
  • jsx 是 JavaScript 的一种语法扩展,它和模板语言很接近,但是它充分具备 JavaScript 的能力。jsx 的本质是 React.createElement 这个 JavaScript 调用的语法糖,jsx 与 html 相似有更高的可读性。

 

  • createElement 对传入参数进行格式化,并在处理之后 return ReactElement方法的调用。

 

  • ReactDOM.render 将虚拟DOM转换为真实DOM。
ReactDOM.render(
    // 需要渲染的元素(ReactElement)
    element, 
    // 元素挂载的目标容器(一个真实DOM)
    container,
    // 回调函数,可选参数,可以用来处理渲染结束后的逻辑
    [callback]
)

 

  • React 15 的生命周期:
import React from "react";
import ReactDOM from "react-dom";
// 定义子组件
class LifeCycle extends React.Component {
  constructor(props) {
    console.log("进入constructor");
    super(props);
    // state 可以在 constructor 里初始化
    this.state = { text: "子组件的文本" };
  }
  // 初始化渲染时调用
  componentWillMount() {
    console.log("componentWillMount方法执行");
  }
  // 初始化渲染时调用
  componentDidMount() {
    console.log("componentDidMount方法执行");
  }
  // 父组件修改组件的props时会调用
  componentWillReceiveProps(nextProps) {
    console.log("componentWillReceiveProps方法执行");
  }
  // 组件更新时调用
  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate方法执行");
    return true;
  }

  // 组件更新时调用
  componentWillUpdate(nextProps, nextState) {
    console.log("componentWillUpdate方法执行");
  }
  // 组件更新后调用
  componentDidUpdate(nextProps, nextState) {
    console.log("componentDidUpdate方法执行");
  }
  // 组件卸载时调用
  componentWillUnmount() {
    console.log("子组件的componentWillUnmount方法执行");
  }
  // 点击按钮,修改子组件文本内容的方法
  changeText = () => {
    this.setState({
      text: "修改后的子组件文本"
    });
  };
  render() {
    console.log("render方法执行");
    return (
      <div className="container">
        <button onClick={this.changeText} className="changeText">
          修改子组件文本内容
        </button>
        <p className="textContent">{this.state.text}</p>
        <p className="fatherContent">{this.props.text}</p>
      </div>
    );
  }
}

 

  • React 16 的生命周期:
import React from "react";
import ReactDOM from "react-dom";
// 定义子组件
class LifeCycle extends React.Component {
  constructor(props) {
    console.log("进入constructor");
    super(props);
    // state 可以在 constructor 里初始化
    this.state = { text: "子组件的文本" };
  }
  // 初始化/更新时调用
  static getDerivedStateFromProps(props, state) {
    console.log("getDerivedStateFromProps方法执行");
    return {
      fatherText: props.text
    }
  }
  // 初始化渲染时调用
  componentDidMount() {
    console.log("componentDidMount方法执行");
  }
  // 组件更新时调用
  shouldComponentUpdate(prevProps, nextState) {
    console.log("shouldComponentUpdate方法执行");
    return true;
  }

  // 组件更新时调用
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate方法执行");
    return "haha";
  }
  // 组件更新后调用
  componentDidUpdate(preProps, preState, valueFromSnapshot) {
    console.log("componentDidUpdate方法执行");
    console.log("从 getSnapshotBeforeUpdate 获取到的值是", valueFromSnapshot);
  }
  // 组件卸载时调用
  componentWillUnmount() {
    console.log("子组件的componentWillUnmount方法执行");
  }
  // 点击按钮,修改子组件文本内容的方法
  changeText = () => {
    this.setState({
      text: "修改后的子组件文本"
    });
  };
  render() {
    console.log("render方法执行");
    return (
      <div className="container">
        <button onClick={this.changeText} className="changeText">
          修改子组件文本内容
        </button>
        <p className="textContent">{this.state.text}</p>
        <p className="fatherContent">{this.props.text}</p>
      </div>
    );
  }
}

render 阶段:纯净且没有副作用,可能会被 React 暂停、终止或重新启动。

pre-commit 阶段:可以读取 DOM。

commit 阶段:可以使用 DOM,运行副作用,安排更新。

render 阶段在执行过程中允许被打断,而 commit 阶段则总是同步执行的。

 

  • React 15 和 16 生命周期的区别

Mounting 阶段:组件的初始化渲染(挂载)

Updating 阶段:组件的更新

 

  • React 16 废弃的是哪些生命周期:componentWillMount、componentWillUpdate、componentWillReceiveProps。

(1)完全可以转移到其他生命周期(尤其是 componentDidxxx)里去做。

(2)在 Fiber 带来的异步渲染机制下,可能会导致非常严重的 Bug。

(3)即使你没有开启异步,React 15 下也有不少人能把自己“玩死”。

 

  • 数据是如何在 React 组件之间流动的?

(1)父 → 子;

(2)子 → 父;

(3)子A → 父 → 子B;

(4)利用“发布-订阅”模式驱动数据流:

(5)Context:

(6)Redux:在 Redux 的整个工作过程中,数据流是严格单向的。

1. 使用 createStore 来完成 store 对象的创建

// 引入 redux
import { createStore } from 'redux'
// 创建 store
const store = createStore(
    reducer,
    initial_state,
    applyMiddleware(middleware1, middleware2, ...)
);

2. reducer 的作用是将新的 state 返回给 store

const reducer = (state, action) => {
    // 此处是各种样的 state处理逻辑
    return new_state
}

3. action 的作用是通知 reducer “让改变发生”

const action = {
  type: "ADD_ITEM",
  payload: '<li>text</li>'
}

4. 派发 action,靠的是 dispatch 

import { createStore } from 'redux'
// 创建 reducer
const reducer = (state, action) => {
    // 此处是各种样的 state处理逻辑
    return new_state
}
// 基于 reducer 创建 state
const store = createStore(reducer)
// 创建一个 action,这个 action 用 “ADD_ITEM” 来标识 
const action = {
  type: "ADD_ITEM",
  payload: '<li>text</li>'
}
// 使用 dispatch 派发 action,action 会进入到 reducer 里触发对应的更新
store.dispatch(action)

发布-订阅

class myEventEmitter {
  constructor() {
    // eventMap 用来存储事件和监听函数之间的关系
    this.eventMap = {};
  }
  // type 这里就代表事件的名称
  on(type, handler) {
    // hanlder 必须是一个函数,如果不是直接报错
    if (!(handler instanceof Function)) {
      throw new Error("哥 你错了 请传一个函数");
    }
    // 判断 type 事件对应的队列是否存在
    if (!this.eventMap[type]) {
      // 若不存在,新建该队列
      this.eventMap[type] = [];
    }
    // 若存在,直接往队列里推入 handler
    this.eventMap[type].push(handler);
  }
  // 别忘了我们前面说过触发时是可以携带数据的,params 就是数据的载体
  emit(type, params) {
    // 假设该事件是有订阅的(对应的事件队列存在)
    if (this.eventMap[type]) {
      // 将事件队列里的 handler 依次执行出队
      this.eventMap[type].forEach((handler, index) => {
        // 注意别忘了读取 params
        handler(params);
      });
    }
  }
  off(type, handler) {
    if (this.eventMap[type]) {
      this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1);
    }
  }
}

// 实例化 myEventEmitter
const myEvent = new myEventEmitter();
// 编写一个简单的 handler
const testHandler = function (params) {
  console.log(`test事件被触发了,testHandler 接收到的入参是${params}`);
};
// 监听 test 事件
myEvent.on("test", testHandler);
// 在触发 test 事件的同时,传入希望 testHandler 感知的参数
myEvent.emit("test", "newState");

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值