如何在 iFrame 正文标签上设置 jQuery data() 并从 iFrame 内部检索它?
Posted
技术标签:
【中文标题】如何在 iFrame 正文标签上设置 jQuery data() 并从 iFrame 内部检索它?【英文标题】:How to set jQuery data() on an iFrame body tag and retrieve it from inside the iFrame? 【发布时间】:2013-05-17 08:35:36 【问题描述】:我无法在我创建的 iFrame 上设置 data()
。
这就是我正在做的:
// options > my configuration object
// options.src = eg "path/foo.html"
// options.id = uuid
// options.parent = $(elem)
// options.param = JSON object
newHTML = document.createElement("iframe");
newHTML.setAttribute("src", options.src);
newHTML.setAttribute("frameborder", 0);
newHTML.setAttribute("seamless", "seamless");
newHTML.setAttribute("data-id", options.id);
newParentElement = options.parent.parent()[0];
options.parent.replaceWith( newHTML );
// select
newRootElement = newParentElement.querySelectorAll(
'[data-id="'+options.id+'"]'
);
// add configuration
$( newRootElement[0] ).load(function ()
var newElement = $(this);
if (options.param)
newElement.contents().find("body").attr("foo","bar").data("config", options.param);
);
当我查看我的 iframe 和它的正文标签时,attr("foo")
已正确设置,我也可以像这样对其进行控制台:
console.log(newElement.contents().find("body").attr("foo"));
但是当我尝试使用data()
或data("config")
来控制config
时,就像这样:
console.log(newElement.contents().find("body").data("config"));
它总是返回undefined
问题:
为什么不能在 iFrame 上设置 jQuery data()
?还是我做错了什么?
感谢您的帮助!
【问题讨论】:
options.param 是一个有效的字符串吗?为什么不为所有脚本使用 jQuery 语法?会容易得多:) jQuery 不会将数据与元素本身一起存储。它只是将id
与元素一起存储。数据本身存储在jQuery.cache
中。如果您使用父级的 jQuery
对象从 iframe 外部设置数据,则设置的数据 存在于父级中,并且无法使用 .data
和 jQuery
对象检索框架。那是因为这两个 jQuery 对象不共享它们的 .cache
对象。
@t.niese:啊。谢谢。你能把它作为一个答案,以便我检查一下吗?
我已经在 FF、Safari 和 Chrome 中测试了您的代码,并且可以正常工作。这是一个小提琴jsbin.com/atezot/3/edit。确保在设置数据之前不要检索数据。
【参考方案1】:
jQuery 不将数据与元素本身一起存储,而是在jQuery.cache
中。
在 jQuery 代码中你有这部分:
jQuery.expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" )
正如您所见,每个 jQuery 加载都会创建一个独特的扩展。
expando 用作属性来存储带有 DOM 元素的标识符。
当您在元素中使用.data(key,value)
存储数据时,jQuery 会执行以下步骤:
-
检查是否存在与
element[jQuery.expando]
中的元素一起存储的id
,如果没有,它会创建一个唯一的id
。
检查是否存在带有jQuery.cache[id]
的条目,如果没有则创建一个空对象来存储该元素的数据。
因此,如果您调用 .data(key,value)
,数据将存储在您使用的 jQuery 实例定义的窗口中。
如果您在parent
中有一个jQuery 对象,在iframe
中有一个对象,则由于随机数,它们有两个不同的expandos
。如果您在 iframe 的元素上从父 jQuery 对象调用 .data()
,则会使用父级的 expando
并将数据存储在父级中。如果您随后使用 iframe jQuery,然后在与 iframe 的 jQuery 之前相同的元素上调用 .data
,则不会找到任何数据,因为它一方面具有不同的 expando
,另一方面数据存储在父窗口。
所以如果你想在 iframe 中设置数据,你应该使用 iframes jQuery 对象。
$('iframe')[0].contentWindow.jQuery("body").data( ... )
设置数据,然后可以再次从 iframe 内部检索该数据,因为您使用相同的 jQuery 对象来设置和读取数据。
编辑
一个额外的重要说明。因为数据是与使用的 jQuery 实例一起存储的,所以您不应该使用 jQuery 在另一个上下文中存储数据。 jQuery 有一个清理方法,当您使用 jQuery 删除元素时会调用该方法,该方法会删除事件侦听器并从 jQuery.cache
中删除数据。但是,如果您使用 jQuery 为另一个上下文中的元素存储数据,则此清理方法将失败(例如,如果您在 iframe 中加载另一个页面)。因此,只有在重新加载父级时,数据才会被释放。
【讨论】:
@frequent 我对这个问题的回答可能对你也有用:javascript: Can data be passed bi-directionally through an iframe? 酷。一旦 iframe 正常工作,我就会做这样的事情 :-) 再次感谢!【参考方案2】:通过向$(selector, scope)
提供第二个参数,确保您的 jQuery 选择器在相关范围内查找。
$(function()
var scope = $('iframe')[0].contentWindow.document; // <iframe>
$('body', scope).data('id', 'some id'); // set data on body of iframe
console.log($('body', scope).data('id')); // ==> 'some id'
);
这是一个小提琴,我成功地将数据设置到 iframe 的主体然后检索它:http://jsbin.com/ecenij/1/edit
【讨论】:
酷。scope
很方便。在上面尝试,是否可能是时间问题。
@Vadim 您不应该以这种方式设置数据或附加事件侦听器,因为如果您在 iframe 中加载另一个页面(然后在iframe 将在内存中,直到父窗口重新加载。)以上是关于如何在 iFrame 正文标签上设置 jQuery data() 并从 iFrame 内部检索它?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用正文中的 min-height 属性设置 iframe 的高度?