-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
react源码分析 #26
Comments
Effect 依赖项怎么发生变化
重点避免不必要渲染,针对数组、对象,使用useMemo得到memorize。再放进useEffect依赖项内; |
Fiber
function performWork(deadlineInfo) {
deadline = performance.now() + (deadlineInfo.timeRemaining() || 50); // 模拟每个时间片为 50ms
while (taskQueue.length > 0 && !shouldYield()) {
const task = taskQueue.shift();
task.callback();
}
if (taskQueue.length > 0) {
requestIdleCallback(performWork); // 继续下一帧任务
}
} react 18较16有哪些 最新功能点
|
Hooks HOC对比用来解决逻辑复用的问题 为什么顶层hooks本质是用数组管理状态的
常用
HOOK编写useHover() 题目描述 编写useHover(),并且符合以下调用: const [ref, hovering] = useHover(); // 使用函数
function useHover() {
const [hovering, setHovering] = usestate();
const ref = useRef();
useEffect(() => {
dom.addevt("mousemove", () => {setHovering(true)});
dom.addevt("mouseend", () => {setHovering(false)});
return () => {
dom.rvmevt("mousemove", () => {});
dom.rvmevt("mouseend", () => {});
};
}, [ref.current]);
return [ref, hovering];
}
//调用
const [ref, hovering] = useHover();
<div ref={hoverRef} > {isHovering ? '鼠标悬停中' : '鼠标未悬停'}</div> HOC 增强编写基于yup的高阶组件 题目描述
已知yup是一个流行的schema的校验库,其基本用法如下:
const schema = yup.object({ name: yup.string().required(), age: yup.numer() });
const validDataOrError = schema.validateSync({ name: 'Koa' });
验证通过返回校验修正后的数据,验证失败则返回包含错误原因的Error对象。
请根据上述信息,编写高阶组件withYupValidator(WrappedComponent, schema),对传入的组件进行增强,实现可以对props进行校验。如果组件未校验通过,显示错误信息(<div>error message here</div>)。
// 方案一:外层函数返回函数组件(使用hooks,`增加函数组件组件`嵌套原始组件):()=>{return (props)=>{ return <com {...props}>}}
withYupValidator(WrappedComponent,schema){
// 1. 高阶返回一个函数(props)
return (props)=>{
useEffect(()=>{
const validateProps = async () => {
try {
await schema.validate(props);
setError(null);
} catch (err) {
setError(err.message);
}
};
validateProps(); },[props])
if(err){return <div>error message here</div>}
// 2.返回 组件
return <WrappedComponent {...props} />
}
}
方案二:外层函数返回Cls组件(使用Lifecyclce,`增加Cls组件组件`嵌套原始组件)
const withYupValidator = (WrappedComponent, schema) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
};
}
componentDidMount() {
this.validateProps(this.props);
}
componentDidUpdate(prevProps) {
if (prevProps !== this.props) {
this.validateProps(this.props);
}
}
validateProps(props) {
try {
schema.validateSync(props);
this.setState({ error: null });
} catch (err) {
this.setState({ error: err.message });
}
}
render() {
const { error } = this.state;
if (error) {
return <div>{error}</div>;
}
return <WrappedComponent {...this.props} />;
}
};
};
// 调用
const schema = yup.object({ name: yup.string().required(), age: yup.numer() });
const MyComponent = ({ name, age }) => (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
const EnhancedComponent = withYupValidator(MyComponent, schema); |
双缓冲
协调diff时本身时jsx 和current对比,得到wip |
Scheduler的优先级lane模型
scheduler 优先级 expiretime-> lane模型(更好批次管理)scheduler 5种优先级
react 有4种优先级 |
react vs vue
|
diff algorithm
react diff
单节点
多节点
一轮
二轮
vue2diffchildren diff children伪代码
// 参数父节点dom
diffchildren(parentEle,old,new){
// 首 新老start index ++ end index--
while(old start<end && new start < end){
if else
1 2 // 首首 //尾尾 issame 直接 patch(旧、新) 索引start + ,end -
3 首尾 issame 移动位置 (旧前 移动到 旧后 ele) ,用silbing表示后
旧 a b c d
新 d c b a
过程 首首a d 、尾尾d a不同 ,首尾a a比较,相同,看第3种情况
看新a在尾,针对新 旧a 新a,目的让a显示页面上列表兄弟最后方,
这里却用老的vdom去找parent ele, parentinsertbefor(old.start.ele,old.end.sibling.ele) 旧前 移动到 旧后
索引start + ,end -
4 尾首相同, 移动位置 (旧后 移动到 旧前)
旧 a b c d
新 d c b e
过程 首首a d 、尾尾d a不同 首尾a e不同,尾首d d相同 看第4种情况
看新d首, 针对新 旧d 新d,目的让d显示页面上最前方,
这里却用老的vdom去找parent ele, parentinsertbefor(old.end.ele,old.start.ele) 旧后 移动到 旧前
索引start + ,end -
5 首首 尾尾 交叉 都不同 创建map{} 存旧节点,判断newstart 是否有 有移动,没有旧新增
例子 新增
旧 a b c d e
新 m b e a d
1.a m ,ed ,ad em都不同
2第五种创建 map ={a:1,b:2,c:3,d:4,e:5}
判断新节点m 在map里面有same的节点
new start m 没有的话,新增 在旧start新增一个 parentinsertbefor(new一个,old.start.ele)
有的话,新增 在旧start新增一个 parentinsertbefor(这个c,old.start.ele)
如:
例子 移动
旧 a b c d e
新 c b e a d
1.a c ,ed ,ad ec都不同
2第五种创建 map ={a:1,b:2,c:3,d:4,e:5}
判断新节点c 在map里面有same的节点
new start c 有的话,可以`移动复用`:c 置为undfined,parentinsertbefor(这个c,old.start.ele)
新start++
}
// 新老个数不配,要么新增,要么删除
// 跳出循环外,需要创建 删除动作 旧新列表对比,如果 多一个或者少一个 需要创建 删除动作
要么 old start >end 新增
for(old start end){
before=new end+1
parent.insertbefie(createnode ,before)
}
要么 new start >end 删除
for(old start end){
parent.remove(node)
}
} insertBefore方法insertBefore方法是DOM操作中的一个经典方法,其作用是将一个节点插入到另一个节点之前。这个方法接受两个参数:第一个参数是要插入的新节点,第二个参数是参考节点(即新节点将要插入到这个节点前面)。 patch
issame
|
1 |
2 similar comments
1 |
1 |
实现一个调度器 并发执行任务数限制 优先级控制class TaskScheduler {
constructor({ concurrency }) {
this.concurrency = concurrency;
this.runningTasks = 0;
this.taskQueue = [];
}
addTask(task, { priority = 0 } = {}) {
return new Promise((resolve, reject) => {
this.taskQueue.push({ task, priority, resolve, reject });
this.taskQueue.sort((a, b) => b.priority - a.priority);
this.runNext();
});
}
runNext() {
if (this.runningTasks >= this.concurrency || this.taskQueue.length === 0) {
return;
}
const { task, resolve, reject } = this.taskQueue.shift();
this.runningTasks++;
task()
.then(resolve)
.catch(reject)
.finally(() => {
this.runningTasks--;
this.runNext();
});
}
}
// Example usage:
const scheduler = new TaskScheduler({ concurrency: 3 });
function fetchData(url) {
return new Promise((resolve) => {
setTimeout(() => resolve(`Data from ${url}`), 1000);
});
}
scheduler.addTask(() => fetchData('url1'), { priority: 1 }).then(res => console.log('Task1 Success:', res)).catch(console.error);
scheduler.addTask(() => fetchData('url2'), { priority: 2 }).then(res => console.log('Task2 Success:', res)).catch(console.error);
scheduler.addTask(() => fetchData('url3'), { priority: 1 }).then(res => console.log('Task3 Success:', res)).catch(console.error);
scheduler.addTask(() => fetchData('url4'), { priority: 1 }).then(res => console.log('Task4 Success:', res)).catch(console.error);
scheduler.addTask(() => fetchData('url5'), { priority: 3 }).then(res => console.log('Task5 Success:', res)).catch(console.error);
scheduler.addTask(() => fetchData('url6'), { priority: 1 }).then(res => console.log('Task6 Success:', res)).catch(console.error); |
实现简单实现 React Fiber 和 调度器(Scheduler) 的例子,用来帮助理解 React Fiber 的核心原理。完整的 Fiber 实现非常复杂,这里只实现了一个基础版本,支持以下功能: schduler和协调渲染 实现调度和FIber
以下是 Fiber 和调度器的核心代码:
|
setState 同步&异步
1.获取优先级
2.创建更新
3.schedule
原因:自动批处理
参考
The text was updated successfully, but these errors were encountered: