为什么我的 iframe 的 contentEditable 会被重置?

Why does my iframe's contentEditable get reset?

我有一个网页,里面有一个空的 iframe,我想用 javascript 为它分配一个源,并使其内容可编辑。 问题是 - 虽然我可以看到框架的内容在短时间内变得可编辑(浏览器开始在未通过拼写检查的单词下划线) - 某些东西会重置该状态,我只剩下一个 iframe,它有正确的内容,但框架的 contentWindow.document.body.contentEditable 已重置为默认值 'inherit'。

在控制台中设置 contentEditable 属性 有效。创建一个在 1000 毫秒后更改 contentEditable 属性 的等待函数也是如此。我确定的解决方案是为我希望 iframe 包含的 URL 创建 XMLHttpRequest,将响应分配给中间 html 元素,更改该元素正文的 contentEditable 属性,然后将其 InnerHTML 分配给 iframe 的 srcdoc。

所以,我有变通办法,但我想了解是什么阻碍了我最初的、更简单的方法。

完成html:

<!DOCTYPE html>
<html>
<head>
<script>
function setedit(){
    var editableFrame = document.getElementById("editableFrame");
    editableFrame.src = '/b.html'
    editableFrame.contentWindow.document.body.contentEditable = true;
}
</script>
</head>
<body onload="setedit()">
<iframe id="editableFrame"></iframe>
</body>
</html>

b.html:

<!DOCTYPE html>
<html>
<body>
<p>Lorem ipsum yadda yadda</p>
</body>
</html>

编辑: 虽然公认的带箭头函数的解决方案有效,但现在我不明白为什么我写的时候没有

function setsrc(){
        var theFrame = document.getElementById('the_frame');
        theFrame.src = '/b.html';
        theFrame.onload = setedit();
}
function setedit(){
        var theFrame = document.getElementById('the_frame');
        theFrame.contentWindow.document.body.contentEditable='true';
}

编辑 2: 好的,我明白了。

theFrame.onload = setedit();

在加载 iframe 之前立即计算 'setedit()' 并将其 return 值分配给 'onload' 属性,这不是一个有效的函数。

这样写也是不行的

theFrame.onload = "setedit()";

大概是因为它试图将文字字符串值分配给 属性,这也不是一个有效的函数。

令人沮丧的是,我无法弄清楚 so log 的原因是,这些方法都不会导致将错误记录到控制台,并且它们都与分配 onload 处理程序的方式不一致你在标签内分配它们,即

<iframe id="the_frame" onload=setedit()></iframe>
<iframe id="the_frame" onload="setedit()"></iframe>

两者都将 'setedit()' 函数指定为 onload 事件的处理程序,除了 - 当以这种方式定义时 - 它们最终在父 window onload 之前和之后被调用并且无法更改contentEditable 属性 也出于某种原因第二次出现。 你必须在 window 的 onload 中构建函数,就像 Kaiido 对箭头函数所做的那样,或者在 ES5 中像这样:

onload = function(){
    var myFrame = document.getElementById('the_frame');
    myFrame.srcdoc = "<html><body><p>This should be editable</p></body></html>";
    myFrame.onload = function(){
        myFrame.contentDocument.body.contentEditable=true;
    };
}

这是因为加载 iframe(顺便说一句,就像任何资源一样)是一项异步任务。
因此,您访问的 editableFrame.contentWindow(及其 document.body)与文档加载后的内容不同。

你调用的时候是一个空文档;例如,可以通过记录本文档的 textContent 来检查。

我必须外包 live example to jsfiddle 因为 null 来源的 StackSnippets 框架不允许访问内部框架内容。

window.onload = e => {
  the_frame.src = URL.createObjectURL(
    new Blob([`<html><body>An other doc</body></html>`])
  );
  console.log(
    the_frame.contentWindow.document.documentElement.textContent
  ); // ""

  // while in the iframe's onload event
  the_frame.onload = e =>
    console.log(
      the_frame.contentWindow.document.documentElement.textContent
    ); // "An other doc"
};
<iframe id="the_frame"></iframe>

正如您可能已经理解的那样,解决方案是在您更改其 src.

后等待 iframe 的 onload 事件触发

https://jsfiddle.net/zwxrpdf8/1/