在处理AngularJS,Angular和React之类的JS框架时,我发现不鼓励直接与DOM进行交互,如果您忽略警告,通常会导致错误。当我说“与DOM交互”时,是指使用document.getElementById('myElement')
和类似方法进行一些操作或从文档中读取值。
我的问题本质上是为什么?。这是一个虚拟DOM问题吗,例如React无法跟踪实际的DOM,因此如果您在没有通知React并随后更新虚拟DOM的情况下“自行”进行更改,就会措手不及?在这种情况下,Angular会有同样的问题吗?
如果某人只了解特定的框架,那么即使我的问题没有被普遍化,我也会非常有兴趣阅读该问题的答案。显然,我将继续在Google上进行搜索,但是我在这里还没有看到类似的问题,因此我认为我会为后代发帖。预先感谢您的任何见解!
答案 0 :(得分:6)
@HDJEMAI链接到此文章,我会重复,因为它是一个很好的建议:https://www.reddit.com/r/javascript/comments/6btma7/whats_so_wrong_with_direct_dom_manipulation/
我将基于以下一些原因进行扩展:
有很多原因想要抽象DOM,并且链接到Reddit的页面主要关注“状态管理”,因为您的框架(Angular,React等)可能会假设DOM是状态,如果您直接操作DOM将被破坏,例如:
function this_is_your_code() {
tell_angular_to_make_my_sidebar_500px_wide();
document.getElementById('mysidebar').style.width = 700px;
var sidebar_width = ask_angular_for_sidebar_width();
console.log( sidebar_width ); // will print "500px"
}
提取DOM的另一个原因是,除了典型的Web浏览器document
/ window
DOM环境(例如“ {{3 }}“是一种事情,其中一些Angular代码在服务器上运行,以预渲染HTML以发送给客户端,以最大程度地减少应用程序启动延迟或允许没有JavaScript的网络浏览器访问您的网页,在这种情况下, W3C DOM不再可用,但是“伪” DOM是可用的,但是它是Angular提供的,并且只能通过Angular的抽象来工作-如果直接操作document
,它将不起作用,例如:>
function this_is_your_code_that_runs_in_nodejs() {
tell_angular_to_make_my_sidebar_500px_wide(); // this works and Angular's built-in abstraction of the DOM makes the appropriate change to the rendered server-side HTML
document.getElementById('mysidebar').style.width = 500px; // fails because `document` is not available
}
答案 1 :(得分:2)
上面@Dai的答案非常好,我想补充一点。在大多数情况下,您不应直接操作dom。在某些情况下,您必须这样做,这是正确的事情。
例如,React和Vue具有引用的概念。虽然可以像id一样,但可以访问dom节点。假设您正在构建一个聊天应用程序,当用户滚动到顶部时,您需要在其中获取旧的聊天记录,并且需要使最后一次可见的聊天记录保持焦点。
存在这种情况,我们需要访问dom。优良作法是保持此类代码的封装状态,并使用访问某些内容的框架方式,而不是向文档/域寻求帮助。