[ React02 | 青训营笔记]

53 阅读3分钟

2.1

通过 React 的 Diff 算法比较旧虚拟 DOM 树和新虚拟 DOM 树之间的 Change ,然后批处理这些改变

通过一个例子了解Fiber,可以看到点击切换后先呈现内容后展示切换动画,说明先把优先级高的内容呈现出来,不要让用户等待时间过长(loading界面)。

import { createSignal, Suspense, Switch, Match, useTransition } from "solid-js";
import { render } from "solid-js/web";
import Child from "./child";
​
import "./styles.css";
​
const App = () => {
  const [tab, setTab] = createSignal(0);
  const [pending, start] = useTransition();
  const updateTab = (index) => () => start(() => setTab(index));
​
  return (
    <>
      <ul class="inline">
        <li classList={{ selected: tab() === 0 }} onClick={updateTab(0)}>
          Uno
        </li>
        <li classList={{ selected: tab() === 1 }} onClick={updateTab(1)}>
          Dos
        </li>
        <li classList={{ selected: tab() === 2 }} onClick={updateTab(2)}>
          Tres
        </li>
      </ul>
      <div class="tab" classList={{ pending: pending() }}>
        <Suspense fallback={<div class="loader">Loading...</div>}>
          <Switch>
            <Match when={tab() === 0}>
              <Child page="Uno" />
            </Match>
            <Match when={tab() === 1}>
              <Child page="Dos" />
            </Match>
            <Match when={tab() === 2}>
              <Child page="Tres" />
            </Match>
          </Switch>
        </Suspense>
      </div>
    </>
  );
};
​
render(App, document.getElementById("app"));

1.Fiber干了啥?

react在render第一次渲染时,会通过React.createElement创建一颗Element树Virtual DOM Tree,同时基于Virtual DOM Tree创建一个结构相同的FiberTree

Virtual DOM Tree 虚拟 DOM 树 虚拟 DOM 树的存在就是为了解决 js 直接操作真实 DOM 而引起的计算机计算能力的浪费。 因为通过 js 直接修改 DOM ,会引起整颗 DOM 树计算和改变,而虚拟 DOM 树的存在可以让真实 DOM 只改变必要改变的部分。

FiberTree是由FiberNode构成的,更像是一个单链表构成的树,便于向上、向下、向兄弟节点转换

组件树和fiber树结构对应,一个组件实例有一个对应的fiber实例、

Fiber负责整个应用层面的调和,fiber实例负责组件的调和。

2.规定调度顺序:expirationTime到期时间

每个FiberNode都会有一个ExpirationTime到期时间来确定当前时间片是否执行该节点的更新任务。

到期时间越短,优先级越高。

为了防止某个Update因为优先级的原因一直被打断而未能执行。React会设置一个ExpirationTime,如果到了这个时间某个Update还未执行的话,React将会强制执行该update,这就是ExpirationTime的作用。

每一次update之前检查

WillMount任务优先级比较低(找哪些节点挂载到界面中),有可能会被高优先级(render、

DidMount )任务打断,打断之后会重新再执行一次,执行次数多了就失去了唯一性,不够安全

componentDidMount:

成功render并渲染完成真实DOM之后触发,可以修改DOM

用来放一些请求,订阅函数调用,setInterval,基于创建完的dom进行初始化

render:只能访问this.props和this.state,不允许修改状态和DOM输出

2.2 事件、state与setState

把要更新的值都放在state里,更新数值用setState

仅仅更改数值并不能在界面上直接显示出来,所以需要state

import React from 'react'export default function App2() {
    state={
        num:1
    }
  return (
      <div>
          <h2>数字为:{this.state.num}</h2>
          <button onClick={()=>this.setState({num:this.state.num+1})}></button>
      </div>
  )
}

对类的复习

若A类继承了B类 且A中写了构造器 那么A类构造器中的super是必须要调用的

类中所定义的方法  都是放在原型对象中的 供实例对象去使用

setState的三种写法

useState

第一个参数,第二个放用来修改参数的方法

函数式组件

函数式组件没有生命周期

函数式组件没有this

函数式组件没有state状态

2.3受控组件与不受控组件

不受控组件:

和组件本身state数据没有关系,所以不受组件管理

受控组件:

表单元素的value值受组件state数据控制,表单中有onChange事件,可以在事件中对表单做实时验证,验证是否合法然后做相应操作

2.4 传值、父传子、子传父

无论是父传子还是子传父,真正在做事的都是父组件,即使是子传父,也是父组件给子组件提供了一个方法来实现的。

父传子

以属性的形式传给组件即可

let msg = "你好世界"export default function App(){
    return <Sub msg={msg} />
}
​
// 子组件
export default function Sub(props) {
  return <h2>{props.msg}</h2>
}

子传父

export default function App(){
    const fn = function(arg){
        console.log(arg)    // 123
    }
    return <Sub msg={msg} fn={fn} />
}
​
// 子组件
export default function Sub(props) {
  return (
      <>
        <h2>{props.msg}</h2>
        <button onClick={()=>props.fn(123)}>将123传递给父组件</button>
      </>
  )
}

this.state

先在state里面定义 之后再使用

// 定义状态数据:
constructor(props){
  super(props)
​
  this.state = {
    num: 20
  }
}
​
// 使用状态数据:
return (
  <div>
    <p>{this.state.num}</p>
  </div>
)

this.props