跨iframe使用jQuery实例时如何修改查询上下文
问题描述
在现有Web应用1中,iframe间复用jQuery实例时遇到查询范围问题:
- jQuery已在包含侧边栏iframe的父文档中加载并别名为
$jq - iframe文档通过
$jq = window.parent.$jq复用父文档的jQuery - 核心问题:iframe内执行
$jq("body").attr("id")默认返回父文档body的id,必须手动添加上下文参数$jq("body", document)才能获取当前iframe文档的对应值 - 需求:能否通过全局设置,无需为每个查询添加上下文,直接将查询范围限定在当前iframe文档?
父文档代码
<!DOCTYPE html> <html> <head> <title>Parent</title> <style>body{ margin: 0; padding: 0; font-family: sans-serif;} #page{ display: flex; } #main { padding: 10px; flex: 1 0 auto; } #sidebar{ width: 360px; background-color: #fafafa; border: 0; padding: 10px; height: calc(100vh - 20px); } </style> <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script> <script> $jq = jQuery; </script> </head> <body id="Parent"> <div id="page"> <iframe id="sidebar" src="sidebar.html"></iframe> <div id="main"> <h2>I am the parent</h2> <code class="result"></code> </div> </div> <script> $('.result').html('$jq("body").attr("id"): <b>' + $jq("body").attr("id") + '</b>'); </script> </body> </html>
iframe文档代码(sidebar.html)
<!DOCTYPE html> <html> <head> <title>Sidebar</title> <style>body{font-family: sans-serif;}</style> </head> <body id="Sidebar"> <h2>I am the sidebar iFrame</h2> <code class="result"></code> <script> var $jq = window.parent.$jq; var theId = $jq("body").attr("id"); var theIdithContext = $jq("body", document).attr("id"); var el = document.querySelector('code'); el.innerHTML +=('$jq("body").attr("id"): <b>' + theId + '</b><br><br>'); el.innerHTML +=('$jq("body", document).attr("id"): <b>' + theIdithContext + '</b>'); </script> </body> </html>
解决方案
可以通过两种方式实现全局默认上下文的切换,无需每次查询手动指定:
方法1:创建绑定当前文档的jQuery局部实例
放弃直接复用父级$jq,基于父级jQuery创建一个绑定当前iframe文档的专属实例:
// 替换原有的var $jq = window.parent.$jq; var $jq = window.parent.jQuery.noConflict(true)(window, document);
此后所有$jq()查询都会默认以当前iframe的document为上下文,直接获取当前文档内的元素。
方法2:重写jQuery选择器逻辑
如果必须保留复用父级$jq变量的方式,可重写其选择器逻辑,强制默认上下文为当前文档:
var $jq = window.parent.$jq; // 保存原始jQuery构造函数 var originalJQ = $jq; // 重写为自动添加上下文的函数 $jq = function(selector, context) { // 未指定上下文时,默认使用当前iframe的document return originalJQ(selector, context || document); }; // 复制原jQuery的静态方法与属性,保证功能完整 Object.assign($jq, originalJQ); // 修复原型链,确保链式调用正常 $jq.fn = originalJQ.fn;
验证效果
修改iframe脚本后,执行$jq("body").attr("id")会直接返回当前iframe的Sidebar,与手动添加上下文的结果完全一致。
1 该应用已使用jQuery,暂时无法替换
内容的提问来源于stack exchange,提问作者zıəs uɐɟəʇs
相关产品推荐
相关产品推荐

