如何在iFrame body标签上设置jQuery data()并从iFrame中检索它?

时间:2013-05-22 10:20:08

标签: javascript jquery iframe parameters jquery-data

我一直试图在我创建的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"));

但是当我尝试使用configdata()来管理data("config")时,就像这样:

  console.log(newElement.contents().find("body").data("config"));

它始终返回undefined

问题
为什么无法在iFrame上设置jQuery data()?或者我做错了什么?

感谢您的帮助!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

jQuery不会将数据与元素本身一起存储,而是存储在jQuery.cache

在jQuery代码中你有这个部分:

jQuery.expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" )

正如您所看到的,每个jQuery加载都会创建一个唯一的expando。

expando用作存储DOM元素的标识符的属性。

当您使用.data(key,value)将数据存储在元素中时,jQuery会执行以下步骤:

  1. 检查id中是否存有element[jQuery.expando]元素,如果没有,则会创建唯一的id
  2. 检查是否有jQuery.cache[id]的条目,如果没有创建一个空对象来存储该元素的数据。
  3. 因此,如果您调用.data(key,value)数据存储在窗口中,则您使用的jQuery实例将被定义。

    如果parent中有一个jQuery对象,iframe中有一个jQuery对象,则由于随机数而有两个不同的expandos。如果从iframe的元素上的父jQuery对象调用.data(),则使用父项的expando,并将数据存储在父项中。如果你然后使用iframes jQuery,然后在iframe的jQuery之前就找不到任何数据的同一元素上调用.data,因为它一方面有另一个expando,另一方面有数据存储在父窗口中。

    因此,如果要在iframe中设置数据,则应使用iframes jQuery对象。 $('iframe')[0].contentWindow.jQuery("body").data( ... )设置数据,然后可以再次从iframe内部检索该数据,因为这样您就可以使用相同的jQuery对象来设置和读取数据。

    修改 一个额外的重要说明。因为数据与使用过的jQuery实例一起存储,所以不应该使用jQuery在另一个上下文中存储数据。当你用jQuery删除元素时,JQuery有一个清理方法,它删除了事件监听器并从jQuery.cache中删除了数据。但是,如果您使用jQuery存储另一个上下文中的元素的数据,则此清理方法将失败(例如,如果您在iframe中加载另一个页面)。因此,只有在重新加载父数据时才会释放数据。