0

我被困data()在我创建的 iFrame 上。

这就是我正在做的事情:

  // 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 和它的 body 标签时,它attr("foo")已正确设置,我也可以像这样对其进行控制台:

  console.log(newElement.contents().find("body").attr("foo"));

但是当我尝试使用or来控制config使用时,就像这样:data()data("config")

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

它总是返回undefined

问题
为什么不能data()在 iFrame 上设置 jQuery?还是我做错了什么?

感谢您的帮助!

4

2 回答 2

2

jQuery does not store the data with the element itself but in jQuery.cache.

In jQuery code you have this part:

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

As you can see for each jQuery load a unique expando is created.

The expando is used as property to store an identifier with the DOM element.

When you store data with .data(key,value) in an element jQuery does the following steps:

  1. check if there is an id stored with the element in element[jQuery.expando] if not it creates an unique id.
  2. check if there is an entry with jQuery.cache[id] if not create an empty object for storing the data for the element there.

So if you call .data(key,value) the data is stored in the window the jQuery instance you use is defined in.

If you have a jQuery object in the parent and one in the iframe these have two different expandos because of the random number. And if you call .data() from the parents jQuery object on an element of the iframe, the expando of the parent is used and the data is stored within the parent. If you then use the iframes jQuery and then call .dataon the same element as before the iframe's jQuery would not find any data because it has on the one hand a different expando and on the other hand the data is stored in the parent window.

So if you want to set data in the iframe you should use the iframes jQuery object. $('iframe')[0].contentWindow.jQuery("body").data( ... ) to set the data, then it is possible to retrive that data from inside of the iframe again, because then you use the same jQuery object for setting and reading the data.

EDIT One additional and important note. Because the data is stored with the used jQuery instance, you should not use jQuery to store data in another context. JQuery has a cleanup methode that is called when you remove elements with jQuery which removes event listeners and removes the data from jQuery.cache. But if you use jQuery to store data for an element that is in another context this cleanup method will fail ( e.g. if you load another page in the iframe). So the data then will only be freed if you reload the parent.

于 2013-05-22T11:45:39.793 回答
2

通过向$(selector, scope).

$(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

于 2013-05-22T10:57:45.813 回答