我已使用socket-io
和nodejs
实施了聊天应用程序。该应用程序运行正常,但有时我会遇到问题以处理HTML
内容,因为当我尝试$('#id').hide()
或$('#id').show()
时没有任何反应,因为元素 id < / em>不可用。
如果我尝试刷新页面按 F5 ,有时它会起作用,因为在我尝试隐藏或显示它之前会渲染该元素。我在使用Google Developer工具进行调试时遇到了这种情况,但我不确定它是否真的是为什么&#34;。
我试图在互联网上找到DOM元素的生命周期,但我找不到能够澄清我想法的东西。
我试图在开发环境中重现这个问题,但我很快就遇到了问题:
<script>
console.log('Creating socket');
var socket = io();
console.log('Socket created');
socket.on('connected', function (data) {
console.log('connected to server');
});
function timeout() {
setTimeout(function() {console.log('sleeping')}, 5000);
}
$(document).ready(function(){
timeout(); // is possible to stuck process on this point?
console.log('Ready');
});
</script>
无论我把socket.on('connected'..
放在哪里,因为它总是在console.log('Ready')
之后调用。基于此,我的 F5 刷新理论不正确,我觉得我在圈子里跑。
任何人都知道为什么HTML
元素有时不存在?
而且,如果我在socket.on('anyevent, {})
内使用$(document).ready(function(){}
,我是否可以保证只在页面完整呈现后处理该事件?
在现实世界中,我们所有的套接字事件都在$(document).ready(function(){}
内,但仍然没有隐藏或显示某些html元素,因为它们不存在。
答案 0 :(得分:1)
我不确定您的HTML和代码结构,但这听起来像是将事件侦听器绑定到动态添加的元素,但绑定时此元素不存在。
如果我的理解是正确的,你需要在一个元素上添加绑定,但是将操作基于新添加的元素,类似于:
// Add event listener, bound to the dynamically added element
$("button").on('click', $("#newElemId"), function(){
// if element exists, toggle it
if($("#newElemId").length){
$("#newElemId").toggle();
}else{
console.log('element not present yet');
}
});
请参阅以下演示:
$(function(){
// define function to add an element to the DOM
var addElement = function(){
var newElementAsObj = $(document.createElement('div'));
// add an id for querying later
newElementAsObj.attr('id', 'newElemId');
// add some text (so it's visible)
newElementAsObj.text('New Element');
$("#container").append(newElementAsObj);
console.log('new element added!');
}
// add a new element after a few secs
setTimeout( addElement, 5 * 1000); // time is in ms so 5*1000 = 5secs
// Add event listener, bound to the dynamically added element
$("button").on('click', $("#newElemId"), function(){
if($("#newElemId").length){
// if element exists, toggle it
$("#newElemId").toggle();
}else{
console.log('element not present yet');
}
});
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<button>Toggle</button>
</div>
&#13;
答案 1 :(得分:0)
首先,关于这个:
$(document).ready(function(){
timeout(); // is possible to stuck process on this point?
console.log('Ready');
});
不,这是不可能的。但你不需要在那里等待。您可以完全删除timeout
功能。
您应该将socket.on('connected', function ...
移到$(document).ready(...
,因为在文档准备好之前您不想响应任何套接字事件。
<script>
console.log('Creating socket');
var socket = io(); // It's fine to do this before the document loads
console.log('Socket created');
$(document).ready(function(){
socket.on('connected', function (data) {
console.log('connected to server');
});
console.log('waiting for connection...');
});
</script>
答案 2 :(得分:0)
JQuery文档描述了在整个页面(而不仅仅是DOM)准备就绪后,您可以使用$(window).on('load', function() {})
来运行代码。你可能会尝试,如果仅仅你的DOM已经准备就绪,但你需要等待整个页面被加载。
https://learn.jquery.com/using-jquery-core/document-ready/
如果我尝试按F5刷新页面,有时它会起作用,因为在我尝试隐藏或显示它之前会渲染该元素。我在使用Google Developer工具进行调试时遇到了这种情况,但我不确定这是“真正的原因”。
您是否使用$().append()
或类似动态创建该元素?如果是这样,请确保在尝试与其进行交互之前实际创建该元素。如果元素不是动态创建的,请确保与元素交互的代码位于$(document).ready
或$(window).on('load')
回调中。
无论我在哪里放置socket.on('connected'..因为它总是在console.log('Ready')之后调用。基于此,我的F5刷新理论不正确我觉得我是在圈子里跑。
这是因为建立套接字连接比渲染DOM需要更多时间。通常最好尽快附加事件监听器,以免错过任何事件。如果仅在加载DOM后附加事件侦听器,则可能错过某些事件。但请注意,如果您在事件侦听器回调中操作DOM,那么您无法确定是否已加载DOM并且您的目标元素在那里,除非您在加载DOM后附加事件侦听器。所以我建议在加载DOM之后附加事件监听器。至少那些包含一些代码来修改DOM。
任何人都知道为什么有时候HTML元素不存在?
这可能的原因并不多。您的元素尚未加载或您的代码由于某种原因删除了它们。我建议将断点放在你创建元素的地方或以某种方式操纵它们,看看执行顺序是什么。
而且,如果我在$(document).ready(function(){}中使用socket.on('anyevent,{}),我是否可以保证只在页面完全呈现后处理该事件?< / p>
您可以保证在anyevent
发生时以及DOM准备就绪时执行回调函数,也就是说,所有静态html元素都在那里。