至此我们介绍了react的理念,如果解决cpu和io的瓶颈,关键是实现异步可中断的更新
我们介绍了react源码架构(ui=fn(state)),从scheduler开始调度(根据过期事件判断优先级),经过render阶段的深度优先遍历形成effectList(中间会执行reconcile|diff),交给commit处理真实节点(中间穿插生命周期和部分hooks),而这些调度的过程都离不开Fiber的支撑,Fiber是工作单元,也是节点优先级、更新UpdateQueue、节点信息的载体,Fiber双缓存则提供了对比前后节点更新的基础。我们还介绍了jsx是React.createElement的语法糖。Lane模型则提供了更细粒度的优先级对比和计算,这一切都为concurrent mode提供了基础,在这之上变可以实现Suspense和batchedUpdate(16、17版本实现的逻辑不一样),18章context的valueStack和valueCursor在整个架构中运行机制,19章介绍了新版事件系统,包括事件生产、监听和触发,
答:mount时通过jsx对象(调用createElement的结果)调用createFiberFromElement生成Fiber
update时通过reconcileChildFibers或reconcileChildrenArray对比新jsx和老的Fiber(current Fiber)生成新的wip Fiber树
答:jsx经过编译之后编程React.createElement,不引入React就会报错,react17改变了编译方式,变成了jsx.createElement
function App() {
return <h1>Hello World</h1>;
}
//转换后
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
答:Fiber是一个js对象,能承载节点信息、优先级、updateQueue,同时它还是一个工作单元。
hooks
答:hook会按顺序存储在链表中,如果写在条件判断中,就没法保持链表的顺序
状态/生命周期
答:legacy模式下:命中batchedUpdates时是异步 未命中batchedUpdates时是同步的
concurrent模式下:都是异步的
答:新的Fiber架构能在scheduler的调度下实现暂停继续,排列优先级,Lane模型能使Fiber节点具有优先级,在高优先级的任务打断低优先级的任务时,低优先级的更新可能会被跳过,所有以上生命周期可能会被执行多次,和之前版本的行为不一致。
组件
答:用来表示元素的类型,是一个symbol类型
答:Class组件prototype上有isReactComponent属性
答:相同点:都可以接收props返回react元素
不同点:
编程思想:类组件需要创建实例,面向对象,函数组件不需要创建实例,接收输入,返回输出,函数式编程
内存占用:类组建需要创建并保存实例,占用一定的内存
值捕获特性:函数组件具有值捕获的特性 下面的函数组件换成类组件打印的num一样吗
export default function App() {
const [num, setNum] = useState(0);
const click = () => {
setTimeout(() => {
console.log(num);
}, 3000);
setNum(num + 1);
};
return <div onClick={click}>click {num}</div>;
}
export default class App extends React.Component {
state = {
num: 0
};
click = () => {
setTimeout(() => {
console.log(this.state.num);
}, 3000);
this.setState({ num: this.state.num + 1 });
};
render() {
return <div onClick={this.click}>click {this.state.num}</div>;
}
}
可测试性:函数组件方便测试
状态:类组件有自己的状态,函数组件没有只能通过useState
生命周期:类组件有完整生命周期,函数组件没有可以使用useEffect实现类似的生命周期
逻辑复用:类组件继承 Hoc(逻辑混乱 嵌套),组合优于继承,函数组件hook逻辑复用
跳过更新:shouldComponentUpdate PureComponent,React.memo
发展未来:函数组件将成为主流,屏蔽this、规范、复用,适合时间分片和渲染
开放性问题
类型 | 原生事件 | 合成事件 |
---|---|---|
命名方式 | 全小写 | 小驼峰 |
事件处理函数 | 字符串 | 函数对象 |
阻止默认行为 | 返回false | event.preventDefault() |
理解:
相关参考视频讲解:进入学习
优势:
dom
上么,如果不是绑定在哪里?
答:v16绑定在document上,v17绑定在container上this
(不是箭头函数的情况)
答:合成事件监听函数在执行的时候会丢失上下文return false
来阻止事件的默认行为?
答:说到底还是合成事件和原生事件触发时机不一样react
怎么通过dom
元素,找到与之对应的 fiber
对象的?
答:通过internalInstanceKey对应 解释结果和现象
function Child() {
console.log('Child');
return <div>Child</div>;
}
function Father(props) {
const [num, setNum] = React.useState(0);
return (
<div onClick={() => {setNum(num + 1)}}>
{num}
{props.children}
</div>
);
}
function App() {
return (
<Father>
<Child/>
</Father>
);
}
const rootEl = document.querySelector("#root");
ReactDOM.render(<App/>, rootEl);
答: 不会,源码中是否命中bailoutOnAlreadyFinishedWork
function Child() {
useEffect(() => {
console.log('Child');
}, [])
return <h1>child</h1>;
}
function Father() {
useEffect(() => {
console.log('Father');
}, [])
return <Child/>;
}
function App() {
useEffect(() => {
console.log('App');
}, [])
return <Father/>;
}
答:Child ,Father ,App ,render阶段mount时深度优先遍历,commit阶段useEffect执行时机
class App extends React.Component {
componentDidMount() {
console.log('mount');
}
}
useEffect(() => {
console.log('useEffect');
}, [])
答:他们在commit阶段不同时机执行,useEffect在commit阶段结尾异步调用,useLayout/componentDidMount同步调用
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。