React as a UI Runtime(三、协调)

news/2025/2/12 18:07:45

1.协调

如果我们在同一个容器中使用两次ReactDOM.render()会发生什么?

ReactDOM.render(<button className="blue" />,document.getElementById('container')
);// ... later ...//  应该替换掉 button 宿主实例吗?
// 还是在已有的 button 上更新属性?
ReactDOM.render(<button className="red" />,document.getElementById('container')
);

再次说明,React的工作是使宿主树和提供的React元素的树一致。确定宿主树怎么样来响应新的信息的这个过程被称为协调。
协调有两种方法。React的简单的版本是抛弃已经存在的树,重新建立新的树:

let domContainer = document.getElementById('container');
// 清除树
domContainer.innerHTML = '';
// 创建新的宿主树
let domNode = document.createElement('button');
domNode.className = 'red';
domContainer.appendChild(domNode);

但是在DOM中,这是低效的,并且会丢失一些重要的信息像聚焦状态,选中状态,滚动状态等等。所以我们希望React像下面一样工作:

let domNode = domContainer.firstChild;
// Update existing host instance
domNode.className = 'red';

换句话说,React需要决定那时候需要更新一个已经存在的宿主实例来响应新的React元素,那时候需要新建一个宿主实例。
这就提出了关于分别的问题,React的元素可能一直在变化,那理论上那时候引用同一个宿主实例呢?
在我们的例子上是很简单的。我们已经创建了一个<button>作为第一个(也是唯一一个)子元素,并且我们希望在同一个地方再次渲染一个<button>。我们已经有一个<button>的宿主实例,我们就不需要再创建新的,再次使用它就好了。

这个已经与React的思想非常接近了。
如果元素的种类在树的同一个地方之前一次的渲染和接下来的渲染是相同的,React会再次使用已经存在的宿主实例。
下面是React带有备注的大致实现过程:

// let domNode = document.createElement('button');
// domNode.className = 'blue';
// domContainer.appendChild(domNode);
ReactDOM.render(<button className="blue" />,document.getElementById('container')
);// 可以再次使用吗? Yes! (button → button)
// domNode.className = 'red';
ReactDOM.render(<button className="red" />,document.getElementById('container')
);// 可以再次使用吗? No! (button → p)
// domContainer.removeChild(domNode);
// domNode = document.createElement('p');
// domNode.textContent = 'Hello';
// domContainer.appendChild(domNode);
ReactDOM.render(<p>Hello</p>,document.getElementById('container')
);// 可以再次使用吗? Yes! (p → p)
// domNode.textContent = 'Goodbye';
ReactDOM.render(<p>Goodbye</p>,document.getElementById('container')
);

这套规则对子树也同样适用。例如,当我们在更新有两个<button>子组件时的<dialog>,React首先决定是否重用<dialog>
然后再对每一个子组件进行相同的过程。


https://dhexx.cn/news/show-2960711.html

相关文章

调用微信的接口报错errcode: 40164 invalid ip

调用微信的接口报错errcode: 40164 调用微信的接口报错 { errcode: 40164, errmsg: invalid ip 117.100.47.169 ipv6 ::ffff:117.100.47.169, not in whitelist hint: [39lrcA01394100] } 报这个错是说&#xff0c;调用微信的接口的ip地址不在白名单内。 解决办法&#xff1…

使用Nginx的必备软件以及Linux内核参数的优化

Linux操作系统&#xff1a;需要内核为Linux2.6及以上版本的操作系统。使用uname -a命令来查询Linux内核版本。 操作系统上面至少安装了如下软件&#xff1a;1、GCC编译器&#xff08;可用来编译C语言程序&#xff09;yum install -y gcc2、PCRE库&#xff08;perl兼容正则表达式…

Python图像处理(14):神经网络分类器

快乐虾http://blog.csdn.net/lights_joy/欢迎转载&#xff0c;但请保留作者信息在opencv中支持神经网络分类器。本文尝试在python中调用它。和前面的贝叶斯分类器一样。神经网络也遵循先训练再使用的方式&#xff0c;我们直接在贝叶斯分类器的測试代码上做简单改动&#xff0c;…

微信小程序在界面中传递URL时,传递的url里有‘?’的处理办法

微信小程序在界面中传递URL时&#xff0c;传递的url里有‘&#xff1f;’的处理办法 我有一个obejct&#xff0c;需要在微信小程序的页面之间传递&#xff0c;object中有?&#xff0c;description: "青山隐隐泛中流&#xff0c;洞天云霄何处生?"&#xff0c;如下&…

pandas 修改 DataFrame 列名

本文参考自:pandas 修改 DataFrame 列名 原博客针对每个DataFrame.columns中的元素做相同的修改操作而拙作是对每个元素做不同操作的生搬硬套, 请大家不吝赐教 提出问题 存在一个名为dataset的DataFrame >>> dataset.columns Index([age, job, marital, education, de…

vue + 高德地图路径规划的demo

vue 高德地图路径规划的demo 官方文档说明 位置经纬度 驾车路线规划 高德地图官方参考链接 demo: <template><div id"demo"><el-amap vid"amapDemo" :amap-manager"amapManager" :events"mapEvents" class"am…

JDK的安装[Centos]

##JDK 下载JDK给所有用户添加可执行权限 chmod x jdk-****.rpm或者直接放掉所有权限 chmod 777 jdk-****.rpm开始安装程序 rpm -ivh jdk-8u45-linux-x64.rpm配置环境变量 vi /etc/profile export JAVA_HOME/usr/java/jdk1.*.*_** export JRE_HOME$JAVA_HOME/jre export CLASSP…

vue + canvas 截取视频的预览图

在页面中加载太多的视频&#xff0c;会造成页面加载慢&#xff0c;所以在显示视频的地方显示视频的预览图。用vue 和 canvas 截取视频的预览图。 示例图&#xff1a; demo: <template> <div id"demo"><div class"video-wrapper" :stylevi…

webstorm使用技巧

在Webstorm中使用正则进行查找或替换 使用正则来查找http://stackoverflow.com/ques... 想该行数据替换为下行数据。include border-radius($big-radius); border-radius: $big-radius;Search for: 在搜素框中日填写下行。 include(.*)\((.*)\); Replace with: 在替换框中填写下…

如何在元素内容前后加图标

大家最常用作图标的元素是i标签&#xff0c;为什么呢&#xff1f; 用 <i> 元素做图标在语义上是不正确的&#xff08;虽然看起来像 icon 的缩写&#xff09;&#xff1b;<i> 比 <span> 短&#xff0c;但 gzip 后差异很小&#xff0c;不过打字可以少按三个键&…