- 什么是iframe?
当我们在查阅手册或使用文档时,左侧通常会有一个列表,右侧则是对应的具体内容。要实现这种效果,我们可以使用iframe(内嵌网页)来实现。
示例图中:红色区域为列表,黄色区域为网页,类似于这种布局,我们可以通过iframe来实现。
- 实现思路
为了实现这种布局,我们可以通过以下三个div元素来实现。首先,在最外层套上一个div元素(container),将其作为包裹整个区域的容器。接着,第二个div元素使用左侧浮动来作为目录(列表),其中包含所需的链接。最后,第三个div元素则浮动在右侧,并在其中添加一个iframe元素,以填充我们所需链接的网页。
这里需要提醒的是,当我们只使用iframe但不对其设置长宽时,默认长宽为300*150,并且自带的边框并不美观(内凹的)。
所以我们可以让iframe充满他的父容器(黄色区域),此处需要对iframe的name属性进行设置,我们一般使用它的name属性来捕获它。
- 实例演示:
这里我们需要a.html/b.html/c.html/d.html
先附上a.html代码,其他代码以此类推。
[qzdypre]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>a.html</h1>
</body>
</html>
[/qzdypre]
iframe网页代码
[qzdypre]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iframeDemo</title>
<style type="text/css">
#container {
width: 100%;
height: 800px;
}
#list {
width: 20%;
height: inherit;
float: left;
box-sizing: border-box;
padding: 10px 20px;
background: grey;
}
#wrapper {
width: 80%;
height: inherit;
float: right;
box-sizing: border-box;
}
#wrapper > iframe[name="page"] {
width: 100%;
height: 100%;
border: none;
}
#list span{
cursor: pointer;
}
</style>
</head>
<body>
<div id="container">
<div id="list">
<p><span data-address="a.html">a.html</span></p>
<p><span data-address="b.html">b.html</span></p>
<p><span data-address="c.html">c.html</span></p>
<p><span data-address="d.html">d.html</span></p>
</div>
<div id="wrapper">
<!--iframe的默认尺寸为300x150-->
<iframe name="page" src="a.html"></iframe>
</div>
</div>
</body>
</html>
[/qzdypre]
通过开发者工具可以看出,iframe的内置样式并不美观。所以我们需要对它进行美化
所以在上述代码中,我们将其的border设置为none
最终页面演示:
学习到这里,我们仅设置了iframe的默认属性为a.html,当单击其它的html标签,iframe并不会跳转。所以我们现在需要通过js脚本来实现案例。
- 脚本再现
思路:当单击对应的html标签,我们会触发click事件,并且实现网页跳转,所以我们需要对click事件监听并阻止它的默认行为发生(即打开对应网页),并将它的href值指定为iframe的src值。
- 实现功能
在iframe.html页面添加以下脚本:
[qzdypre]
<script>
window.addEventListener("load", (event) => {
let iframe = document.querySelector("iframe[name=page]");
let links = document.querySelectorAll("#list span");
links.forEach((link) => {
link.addEventListener("click", (event) => {
iframe.src = event.target.dataset.address;
})
})
})
</script>
[/qzdypre]
这段JavaScript代码是在网页加载完成后(load)执行的,主要功能是修改一个名为"page"的iframe的src属性。以下是对这段代码的逐句解释:
- addEventListener("load", (event) => {...}):在网页加载完成后执行括号内的函数。
- let iframe = document.querySelector("iframe[name=page]"):选择名为"page"的iframe元素。
- let links = document.querySelectorAll("#list span"):选择id为"list"的元素下的所有span元素。
- forEach((link) => {...}):遍历所有选择的span元素。(这里用到了回调函数,具体可自行查找forEach的参数及用法)
- addEventListener("click", (event) => {...}):为每个span元素添加点击事件监听器
- src = event.target.dataset.address:当点击span元素时,将iframe的src属性设置为该span元素的dataset中的address属性值。
总结:这段代码的目的是在网页加载完成后,为id为"list"的元素下的所有span元素添加点击事件监听器。当点击这些元素时,会修改名为"page"的iframe的src属性,使其指向这些span元素的dataset中的address属性值所指定的地址。
- 提出疑问
为什么要将代码放在“load”事件后执行?这样做有什么好处?
答:将其放在load事件下是因为在网页加载完成后才可能执行相关的JavaScript代码。如果这些代码依赖于页面的某些元素(如iframe),那么只有在这些元素都加载完成后,代码才能正确执行。
这样做的好处包括:
确保相关元素已加载:在load事件中执行JavaScript代码可以确保所需的DOM元素已经加载完成,避免因元素尚未加载而导致的错误。
提高性能:将JavaScript代码放在load事件中可以延迟脚本的执行,直到页面完成加载,这有助于提高页面加载速度和性能。
避免阻塞页面渲染:通过将JavaScript代码放在load事件中,可以避免在页面渲染过程中阻塞,从而提高用户体验。
统一管理:将JavaScript代码放在load事件中可以使代码结构更加清晰和统一,方便管理和维护。
所以在日常网页编写中,我们需要考虑一些细节问题。
学以致用:利用iframe做一个简易的发信界面
在一般的发信界面,我们可以看到如下图所示的一些元素
这里我们主要模拟:收信人和抄送的文本框,以及添加附件和发送按钮,最重要的是利用iframe来实现正文部分的填写。
附代码和界面截图:
页面1:email.html
[qzdypre]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>发信页面</title>
<style>
iframe{
width: 600px;
height: 400px;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h1>发信页面</h1>
<form>
<label for="recipient">收信人:</label>
<input type="text" id="recipient" name="recipient" required><br><br>
<label for="cc">抄送:</label>
<input type="text" id="cc" name="cc" required><br><br>
<label for="attachment">添加附件:</label>
<input type="file" id="attachment" name="attachment"><br><br>
<iframe name="test" src="blank.html"></iframe>
</form>
<input type="submit" value="发送">
<script>
window.addEventListener('load', function () {
let frame = frames["test"];
frame.document.designMode="on";
});
</script>
</body>
</html>
[/qzdypre]
页面2名称为blank.html,在此次仅供iframe来引用作为文本输入框,并无任何代码!
这段代码的主要功能是:
通过iframe来引入blank界面,然后利用js脚本将iframe中的文档设计模式设置为开启,这样用户可以编辑iframe中的内容。
总的来说,这段代码创建了一个简单的电子邮件发信页面,包括收信人、抄送、附件上传以及一个提交按钮的功能。同时,它还包含一个iframe元素,当页面加载完成后,将iframe中的文档设计模式设置为开启。但由于这段代码并没有实现真正的邮件发送功能,所以它只是一个模拟页面。
- 本课第二块内容:利用js脚本对表格内容进行修改
本块内容主要内容:利用js脚本创建表格,并对表格内容进行修改。
我们首先新建一个页面:table.html
对其设置一个id为container的div,并引入js脚本,创建表格内容数组。代码如下:
[qzdypre]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
table, tr, td ,th{
border: 1px solid black;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
// 定义一个对象数组,每个对象包含表格单元格的值
let heads=["name","gender","age","tall"];
let students=[
{name:"Alice",gender:"female",age:20,tall:160},
{name:"Bob",gender:"male",age:21,tall:176},
{name:"Mark",gender:"male",age:21,tall:173},
{name:"Jack",gender:"male",age:20,tall:180}
]
</script>
</body>
</html>
[/qzdypre]
那么我们如何通过js在html页面中创建table表格元素呢?
为了提高性能,我们按照上面提到的,在load事件后编写脚本。
我们首先通过
[qzdypre]
let table = document.createElement("table");
[/qzdypre]
这行代码使用document.createElement方法创建一个新的HTML元素。
之后通过id捕获div,并在其中添加table元素
[qzdypre]
document.querySelector("#container").appendChild(table);
[/qzdypre]
以此类推,创建td、tr、th元素,附完整脚本:
[qzdypre]
window.addEventListener("load",function () {
let table = document.createElement("table");
document.querySelector("#container").appendChild(table);
let tr = document.createElement("tr");
table.appendChild(tr);
for(const head of heads){
let th = document.createElement("th");
tr.appendChild(th);
th.innerText = head;
}
});
[/qzdypre]
这里的难点在于第六行的for of循环,用于遍历heads数组,并赋给head,然后将它填充为th的文本内容(表头)。
类似的,我们一样可以通过上述方法来填充表格的文字内容。附代码:
[qzdypre]
for(let i=0;i<students.length;i++){
let edit_pat = /age|tall/ ;
let stu = students[i];
let tr = document.createElement("tr");
table.appendChild(tr);
for(const head of heads){
let td = document.createElement("td");
tr.appendChild(td);
td.innerText = stu[head];
if(edit_pat.test(head)){
td.contentEditable = "true";
td.onblur=td.onkeypress=(event)=>{
stu[head] = td.innerText;
}
}
}
}
[/qzdypre]
这里我们通过一个正则表达式内容来确定对表格的内容决定能否修改,用JavaScript为网页动态创建表格,并且在特定的列(年龄或身高)上使单元格可编辑。当用户编辑这些单元格时,你更新了对应的学生数据。
这里定义了一个正则表达式,用于匹配包含“age”或“tall”的字符串。
td.contentEditable = "true";这一行使表格单元格可编辑
td.onblur=td.onkeypress=(event)=>{ stu[head] = td.innerText; }这一行设置了一个事件处理器,当单元格失去焦点或按键被按下时,会触发这个处理器。处理器将单元格的内容更新为对应学生的数据。
至此,这样一个能够动态表格就实现了,实际运用中,我们可以通过在脚本中引入fetch,来实现客户端到服务器端实现表格数据的实时修改!
- 本课第三块内容:同源网页的数据传输
首先我们需要理解“同源”,在网页开发中,"同源"通常指的是两个或多个网页具有相同的协议(例如HTTP或HTTPS),相同的域名和相同的端口号。这种一致性可以确保浏览器能够安全地访问和操作这些网页中的数据。
当网页中的脚本尝试从一个不同源的源(即:具有不同的协议、域名或端口)获取数据时,浏览器会阻止这种行为,以防止潜在的安全风险。这种限制被称为"同源策略"。
方法①:超链接传输同源数据
此处我们需要两个页面a.html和b.html
在a中通过<a href>将数据传输到b,并在b中取出。
这里我们附上a.html的代码
[qzdypre]
这里我们附上a.html的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="b.html?id=1&name=Bob">b.html</a>
</body>
</html>
[/qzdypre]
在这段代码中,我们假设传输给页面b的数据有两个,分别为id和name。id为1,name为Bob
这里我们需要引出一个新的概念:
基于BOM((Browser Object Model)浏览器对象模型)的API,提供了独立于脚本语言和浏览器的方法,允许程序和脚本独立地与浏览器窗口交互。
这里我们主要用到的是location,location对象的作用主要包含以下几个方面:
- 保存当前文档的信息:Location对象包含了关于当前网页的URL信息,并且可以对URL进行拆分、读写等各种操作。
- 解析URL片段:Location对象将URL解析为独立的片段,让开发人员可以通过不同的属性访问这些片段,例如协议、主机名、端口、路径、查询参数、锚等。
- 实现页面导航:通过Location对象提供的方法,可以进行页面的导航操作,例如assign()方法可以使页面跳转到新的URL。
从图中可知,location.search(查询字符串)中包含我们所需要的参数id和name。但是此参数是从“?"开始的,我们需要通过编写JavaScript代码来分离参数和值。
- 思路
- 因为"?"与我们所需要提取的值并不相关,所以我们需要去掉这里的"?",这里我们可以用substr方法。
substr的方法如下:
[qzdypre]
str.substr(start, length);
[/qzdypre]
- start:必需参数,子字符串的起始位置。第一个字符的索引为0,第二个字符的索引为1,依此类推。
- length:可选参数,提取的子字符串的长度。
这里我们可以用let search = location.search.substr(1);来删掉"?"
之后,我们可以通过”&“来切割,再对每个元素用"="来切割。
之后通过引入URLSearchParams来处理。
最后,通过"..."展开运算符,来对数组进行展开,即提取参数。
至此,利用超链接来传输数据的大体思路完成了,我们可以通过这个思路来编写js代码来提取数据。
- 编写具体的脚本
首先在b页面中添加按钮,用来获取a页面的数据
[qzdypre]
<input type="button" value="jump to a.html">
[/qzdypre]
编写函数addParam为a页面加入被传参数
[qzdypre]
function addParam(url, name, value){
if(url.indexOf("?") === -1){
return url + "?" + name + "=" + value;
}else{
return url + "&" + name + "=" + value;
}
}
[/qzdypre]
函数的逻辑如下:
- 首先,函数使用indexOf方法检查URL中是否已经存在一个问号(?)。这个问号是URL参数的分隔符。如果URL中不存在问号,说明URL中还没有参数。
- 如果URL中不存在问号,那么函数将在URL的末尾添加一个问号,然后紧接着添加参数名和参数值,参数名和参数值之间用等号(=)连接。例如,如果输入的URL是"example.com",参数名是"key",参数值是"value",那么函数将返回"example.com?key=value"。
- 如果URL中已经存在一个问号,那么函数将在URL的末尾添加一个&字符,然后紧接着添加参数名和参数值,参数名和参数值之间用等号(=)连接。例如,如果输入的URL是"example.com?existing=parameter",参数名是"key",参数值是"value",那么函数将返回"example.com?existing=parameter&key=value"。
之后我们可以通过按钮来捕获它,并为其添加想传入的参数
[qzdypre]
document.querySelector("input").addEventListener("click", event => {
let url = "a.html"
alert(addParam(addParam(url, "id"," 1"),"name","Alice"));
})
[/qzdypre]
这里我们使用addParam来参加被传参数,并且每需要一组参数就需要引入一次addParam
下节课还会介绍其它方法,课后学有余力的同学可以尝试其它方法(如本地储存(localStorage)和json转换)
文章评论