前奏
最近在做考试系统,需要实现:
标题栏点击对应的菜单,底部主区域动态加载对应的界面
红色区域就是要动态替换的
界面通过访问 uri 进行加载
想要结果的,可以直接滑到最后~
挫折之路
首先想到的就是 iframe,但是它有很大的缺点:不能高度自适应!!!
- 虽然滚动条及边框可以去掉,但是去掉滚动条之后,就不能滚动了,即使内容还没有展示完!!!
- 如果写死 iframe 的高度,或者只在一开始获取 iframe 的内容高度并更新 iframe 的高度,就会出现:当子页面的高度变化后,iframe 没有动态更新高度,出现一大片空白
于是我尝试了各种动态修改 iframe 的方法,包括用定时器去轮询获取高度,监听器插件等
因为我要嵌入的子页面是用了 vue.js,所以我还考虑了 vue 的嵌套路由,但是我不是前端开发,这种临时学习的知识,我实践不了啊,呜呜
然后我还尝试了用 <link>
、<object>
等其他可以嵌套的方法,均不行
因为我的框架是 thymeleaf,所以父页面是 html,就没有尝试 jsp 的 include
愿景
我想要那种虽然是嵌套的页面,但是子页面要和父页面完美融合,类似这种:
尝试
最终我决定回归原生,使用 document.innerHTML 方法,将子页面嵌套
<div id="insertIframe">
</div>
//导入子页面
$.get("www.baidu.com", function (data) {
$("#insertIframe").html(data);
});
然后,我惊奇发现,竟然真的可以了哎
但是新的问题随之而来:
加载了子页面之后,再次点击菜单,重新加载子页面时,报错:
Uncaught SyntaxError: Identifier 'xxxxx' has already been declared
刚燃起的希望,再次破灭
我以为是 Vue 没办法再次渲染,然后就开始胡乱搜:
- innerHTML 两次加载包含 Vue.js 的子页面出错
- Vue 强制渲染页面
- ……
结果肯定是搜不到想要的啊
折腾了一天,心态爆炸,最后我才想起来:
为什么不仔细看一下报错信息呢?
然后发现是因为变量重复定义,我就开始搜:
JavaScript 删除变量,认为在加载子页面的时候,把子页面的变量先删除一遍
结果,还是报错!!!
最后机缘巧合下,发现了一句话:
let 声明的变量不能重复定义,但是 var 声明的变量可以
我急忙去看了一下子页面的变量,果然是 let 声明的:
然后改成 var,就完美运行了!!!
总结
父页面导入子页面,可以通过 innerHTML 的方式(jQuery 是 html)进行导入
$.get("子页面的访问地址", function (data) {
$("#父页面嵌套子页面的 div 的 id").html(data);
});
子页面中所有变量均需使用 var 声明!!!