正如 Mattias Buelens 解释的那样,document.write
调用open
清除 DOM 的方法只是因为 - 在加载后 - 该document.close
方法是自动调用的。当然,您可以使用许多替代方案。例如,使用元素
的innerHTML
属性。
使用and也是一种选择body
document.createElement
document.body.appendChild
但也许值得考虑的是,这两种方法都有其缺点:使用innerHTML
允许您将格式错误的标记注入 DOM,并且可能使您容易受到 XSS 攻击。
使用document.createElement
速度较慢(通常)并且通常需要更多代码,这反过来会降低您的脚本的可维护性。
你可以使用这样的东西:
var flip = (function(tempDiv)
{//create a div once
var page = 0,
targetDiv = document.getElementById('contentgoeshere');//closure variables
//page is now no longer an evil global, and the target element into which
//we will inject new data is referenced, so we don't have to scan the DOM
//on each function call
return function(overridePage)//optional argument, just in case
{//actual flip function is returned here
overridePage = overridePage || page++;//new content
tempDiv.innerHTML = overridePage;//render in div that isn't part of the DOM
//any number of checks can go here, like:
if (tempDiv.getElementsByTagName('script').length > 0)
{
alert('Naughty client, trying to inject your own scripts to my site');
return;
}
targetDiv.innerHTML = tempDiv.innerHTML;
//or, depending on your needs:
targetDiv.innerHTML = tempDiv.innerText;//or the other way 'round
};
}(document.createElement('div')));
一些旁注:就目前而言,这个函数将不起作用,因为必须完全加载 DOM 才能使闭包工作。一个快速的解决方法是:
var flip;//undefined
window.onload = function()
{
flip = (function(tempDiv)
{
var page = 0,
targetDiv = document.getElementById('contentgoeshere');
return function(e)
{
tempDiv.innerHTML = e instanceof Event ? page++ : (e || page++);//ternary + logical or
//your [optional] checks here
targetDiv.innerHTML = tempDiv.innerHTML;
if (e instanceof Event)
{//this part is optional, but look it up if you want to: it's good stuff
e.returnValue = false;
e.cancelBubble = true;
if (e.preventDefault)
{
e.preventDefault();
e.stopPropagation();
}
}
return e;
};
}(document.createElement('div')));
//instead of using the HTML onclick attribute:
document.getElementById('buttonID').onclick = flip;//use as event handler
};
请注意,这window.onload
会导致 IE<9 上的内存泄漏,请查看此链接以获取此问题的解决方案