没有 React 的类似 React 的编程
React-like programming without React
我是使用 JQuery 长大的,并且一直遵循一种编程模式,可以说是“React-like ",但不使用 React。尽管如此,我还是想知道我的图形性能如何如此出色。
例如,在我的前端,我有一个 table 显示一些 "state"(在 React 术语中)。然而,这个 "state" 对我来说只是保存在全局变量中。我有一个 update_table()
函数,它是对 table 进行更新的中心位置。它接受 "state" 并用它渲染 table 。它做的第一件事是调用 $("#table").empty()
来获得一个干净的开始,然后用 "state" 信息填充行。
我在服务器端每 2-3 秒有一些动态变化的数据("state"),我使用 Ajax 进行轮询,一旦我获得数据/"state",我就叫update_table()
。
这是用 React 解决的完美问题,我知道。然而,在使用 JQuery 实现这个简单的解决方案后,我发现它工作得很好(我没有在这里填充巨大的 table;我最多有 20 行和 5 列)。
我预计会看到闪烁,因为 $("#table").empty()
调用随后在 update_table()
函数中逐行添加行。但是,浏览器 (chrome/safari) 似乎在仅更新实际更改的元素方面做得很好(几乎就像浏览器实现了 Virtual DOM/diffing,例如 反应!)
我猜你的问题是为什么不用React也能有这么好的图形性能
您所看到的 "good graphics performance" 确实是一个定义问题,或者更糟的是,意见问题。
经典的 Netscape 处理周期(所有现代浏览器都继承了它)基本上有四个主要阶段。 Here is the full-blown Gecko engine description.
只要您操纵 DOM,您就处于 "DOM update" 阶段并且根本不会执行任何渲染。只有当您的代码产生时,下一阶段才会开始。由于 DOM 的变化,某些元素的大小或位置也可能发生了变化。所以这个阶段重新计算布局。在这个阶段之后,接下来是渲染,重新绘制像素。
这意味着如果您的代码更改了 DOM 中的大量元素,它们仍然会一起呈现,而不是以增量方式呈现。因此,如果您在之后立即重新填充 table,则 empty() 调用不会呈现。
现在,当您看到像“13872”这样的元素的像素时,渲染阶段可能会以完全相同的颜色在完全相同的位置渲染这些像素。像素颜色没有任何变化,因此您看不到闪烁。
也就是说,您的图形性能非常出色 -- 是的。但是你是怎么测量的呢?你只是看着它,并认为它是完美的。现在,从视觉上看,它真的可能非常非常好。因为您所需要的只是避免 sizing/positioning 不同的布局阶段。
但实际性能不是用我们人类懒惰的眼睛来衡量的(在那个领域有很多可用性研究,假设 60 Hz 的一帧需要 16.6 毫秒,所以渲染时间不到这个就足够了).它是用实际指标(每秒更新或其他)来衡量的。考虑到在具有较旧浏览器和较慢显卡的旧机器上,您的 "excellent" 性能可能看起来很可耻。你怎么知道它在具有 64 MB 显存的旧东芝 tablet 上仍然很好?
那么缩放呢?如果您现在拥有 100 倍的元素,您确定它会很好地扩展吗?如果一些数据占用更多(或更少)space 并改变整个布局怎么办?您的简单方法可能无法涵盖所有这些边缘条件。
像 React 这样的库会考虑到您可能还没有遇到过的情况,并提供统一的模式来处理它们。
因此,如果您对自己的解决方案感到满意,则不需要 React。我经常避免使用 jQuery,因为现在 ES5/ES6 已经很不错了,我可以使用 document.getElementById() 等记下 3-4 行代码。但我意识到在较大的项目或复杂的情况下 jQuery 是完美的工具。
像这样看 React:一个当你意识到你需要它时有用的工具,而当你认为你可以不用它时它又很麻烦。一切由你决定:)
当你遇到这样的事情时:
$("#table").empty()
.html("... new content of the table ... ");
然后会发生以下情况:
.empty()
删除内容并将渲染树/布局标记为无效。
.html()
添加新内容并将渲染树/布局标记为无效。
除其他事项外,标记为无效会在将来某个时间点调用 InvalidateRect() (on Windows) that causes the window to receive WM_PAINT 事件。
通过处理 WM_PAINT,浏览器将计算布局并呈现所有结果。
因此,多个更改请求将合并为单个 window 绘画操作。
我是使用 JQuery 长大的,并且一直遵循一种编程模式,可以说是“React-like ",但不使用 React。尽管如此,我还是想知道我的图形性能如何如此出色。
例如,在我的前端,我有一个 table 显示一些 "state"(在 React 术语中)。然而,这个 "state" 对我来说只是保存在全局变量中。我有一个 update_table()
函数,它是对 table 进行更新的中心位置。它接受 "state" 并用它渲染 table 。它做的第一件事是调用 $("#table").empty()
来获得一个干净的开始,然后用 "state" 信息填充行。
我在服务器端每 2-3 秒有一些动态变化的数据("state"),我使用 Ajax 进行轮询,一旦我获得数据/"state",我就叫update_table()
。
这是用 React 解决的完美问题,我知道。然而,在使用 JQuery 实现这个简单的解决方案后,我发现它工作得很好(我没有在这里填充巨大的 table;我最多有 20 行和 5 列)。
我预计会看到闪烁,因为 $("#table").empty()
调用随后在 update_table()
函数中逐行添加行。但是,浏览器 (chrome/safari) 似乎在仅更新实际更改的元素方面做得很好(几乎就像浏览器实现了 Virtual DOM/diffing,例如 反应!)
我猜你的问题是为什么不用React也能有这么好的图形性能
您所看到的 "good graphics performance" 确实是一个定义问题,或者更糟的是,意见问题。
经典的 Netscape 处理周期(所有现代浏览器都继承了它)基本上有四个主要阶段。 Here is the full-blown Gecko engine description.
只要您操纵 DOM,您就处于 "DOM update" 阶段并且根本不会执行任何渲染。只有当您的代码产生时,下一阶段才会开始。由于 DOM 的变化,某些元素的大小或位置也可能发生了变化。所以这个阶段重新计算布局。在这个阶段之后,接下来是渲染,重新绘制像素。
这意味着如果您的代码更改了 DOM 中的大量元素,它们仍然会一起呈现,而不是以增量方式呈现。因此,如果您在之后立即重新填充 table,则 empty() 调用不会呈现。
现在,当您看到像“13872”这样的元素的像素时,渲染阶段可能会以完全相同的颜色在完全相同的位置渲染这些像素。像素颜色没有任何变化,因此您看不到闪烁。
也就是说,您的图形性能非常出色 -- 是的。但是你是怎么测量的呢?你只是看着它,并认为它是完美的。现在,从视觉上看,它真的可能非常非常好。因为您所需要的只是避免 sizing/positioning 不同的布局阶段。
但实际性能不是用我们人类懒惰的眼睛来衡量的(在那个领域有很多可用性研究,假设 60 Hz 的一帧需要 16.6 毫秒,所以渲染时间不到这个就足够了).它是用实际指标(每秒更新或其他)来衡量的。考虑到在具有较旧浏览器和较慢显卡的旧机器上,您的 "excellent" 性能可能看起来很可耻。你怎么知道它在具有 64 MB 显存的旧东芝 tablet 上仍然很好?
那么缩放呢?如果您现在拥有 100 倍的元素,您确定它会很好地扩展吗?如果一些数据占用更多(或更少)space 并改变整个布局怎么办?您的简单方法可能无法涵盖所有这些边缘条件。
像 React 这样的库会考虑到您可能还没有遇到过的情况,并提供统一的模式来处理它们。
因此,如果您对自己的解决方案感到满意,则不需要 React。我经常避免使用 jQuery,因为现在 ES5/ES6 已经很不错了,我可以使用 document.getElementById() 等记下 3-4 行代码。但我意识到在较大的项目或复杂的情况下 jQuery 是完美的工具。
像这样看 React:一个当你意识到你需要它时有用的工具,而当你认为你可以不用它时它又很麻烦。一切由你决定:)
当你遇到这样的事情时:
$("#table").empty()
.html("... new content of the table ... ");
然后会发生以下情况:
.empty()
删除内容并将渲染树/布局标记为无效。.html()
添加新内容并将渲染树/布局标记为无效。
除其他事项外,标记为无效会在将来某个时间点调用 InvalidateRect() (on Windows) that causes the window to receive WM_PAINT 事件。
通过处理 WM_PAINT,浏览器将计算布局并呈现所有结果。
因此,多个更改请求将合并为单个 window 绘画操作。