WEB第七天
一、 DOM事件监听
1.1 添加事件监听
<p>
<span>点我试试</span>
</p>
let p_e = document.getElementsByTagName('p')[0]
let span_e = p_e.firstElementChild // 第一个子标签元素
let click_span = (ev)=>console.warn('span 被点击');
span_e.addEventListener('click', click_span);
(ev)=>console.warn(‘span 被点击’) 是ES6中匿名函数的写法, 相当于:
function (ev) {
console.warn('span 被点击')
}
如果给span父标签也增加点击事件监听 ,则可以先捕获子标签的事件,然后再处理子标签的事件。默认情况下,是冒泡方式,即先处理子标签的事件,再处理父标签的事件。
p_e.addEventListener('click', function (ev) {
console.error('p标签被点击');
}, false);
addEventListener()第三个参数的boolean表示是否优先捕获事件。默认为false即冒泡。
1.2 删除事件监听
span_e.removeEventListener('click', click_span);
也可以在适当的事件中,去除事件监听。
p_e.addEventListener('click', function (ev) {
console.error('p标签被点击');
// 'click' 事件类型, click_span监听函数的对象
this.firstElementChild.removeEventListener('click', click_span);
});
注意:如果事件监听的对象是匿名函数,是无法的删除的。
1.3 自定义选项卡
html网页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>自定义选项卡</title>
<link rel="stylesheet" href="css/tab.css">
</head>
<body>
<div id="tab">
<ul id="tab-head">
<li class="active">主页</li>
<li >精品推荐</li>
<li>818活动</li>
</ul>
<ul id="tab-body">
<li>
<div style="height: 100%;background-color:red;color:white">
<h1>主页</h1>
</div>
</li>
<li class="hidden">
<h3>精品推荐</h3>
<span>> 123</span> <br>
<span>> 345</span><br>
<span>> 1111</span><br>
<span>> 12333</span><br>
</li>
<li class="hidden">818活动</li>
</ul>
</div>
<script src="js/tab.js"></script>
</body>
</html>
css样式文件:
ul,li{
list-style: none;
margin: 0;
padding: 0;
}
#tab-head li{
float: left;
}
ul:after{
content: "";
display: block;
height: 0;
clear: both;
overflow: hidden;
}
#tab{
width: 600px;
height: 400px;
background-color: skyblue;
padding: 0px;
}
#tab-head{
height: 40px;
background-color: yellowgreen;
}
#tab-head li{
padding: 10px;
}
#tab-head .active{
background-color: greenyellow;
}
#tab-body{
margin: 0px;
}
#tab-body h1{
margin: 0px;
}
#tab-body li{
width: 100%;
height: 360px;
}
#tab-body .hidden{
display: none;
}
js文件
function $(element_id) {
return document.getElementById(element_id)
}
window.onload = function () {
// 当文档加载就绪之后,执行的函数
let head_tabs = $('tab-head').children;
let body_tabs = $('tab-body').children;
let currentIndex = 0;
for(i in head_tabs){
// 获取头的每个选项卡的标题
let hTab = head_tabs[i];
hTab.index = i // 设置选项卡的索引
hTab.onclick = function (ev) {
// this 指向的是当前事件来源(点击的标签)
if(this.index !== currentIndex){
console.log(this.index)
head_tabs[currentIndex].removeAttribute('class');
this.setAttribute('class', 'active')
//显示对应的内容
body_tabs[currentIndex].setAttribute('class', 'hidden');
body_tabs[this.index].removeAttribute('class');
currentIndex = this.index
}
}
}
};
提示说明:
-
window.onload 是当空前窗口的监听函数,表示当前网页文档加载完成(文档就绪)后调用的函数。
-
获取一个父标签元素下的所有子元素节点: $(‘tab-head’). children 返回所有#tab-head的标签的所有子元素标签, 即所有li标签。
-
在标签的事件函数中,this表示事件发生在什么标签上,即事件源。this即表示点击某一标签的元素对象。
-
可以动态地添加元素对象的属性, 有两种方式添加:
- 对象.属性= 属性值
- 对象[属性] = 属性值
-
标签事件类型: mouseover(), click(), focus(), blur()
二、面向对象
2.1 创建对象
-
使用Object来创建
let stu = new Object(); stu.name = 'disen'; stu.age = 20;
-
使用 {} 创建
let stu2 = { name: 'jack', age: 20 } // 动态地添加属性 stu2.city = '西安'; stu2['phone'] = '110';
-
使用构造函数
function Student(id, name, city){ // 使用this关键字,初始化对象的属性 // this表示通过Student()构造函数创建的对象 this.id = id; this.name = name; this.city = city; } let s1 = new Student(1, 'dula', '北京'); // s1对象初始化时新增了id, name, city 三个属性 s1.id // 1 s1 // {id: 1, name: "dula", city: "北京"}
默认情况下,对象和对象之间不共享属性和方法。如果像Python类的定义,让多个对象共享相同的属性或方法时,需要使用对象的元型属性。
2.2 对象的元型prototype
prototype是任何对象都具有的属性,表示类的方法或属性,让多个相同类的对象共享属性或方法。
给上面的构造函数 Student类,增加元型属性:
Student.prototype.say = function(){
console.log(this.id, this.name, this.city)
}
接下来,创建两个对象,可以分别调用say()函数,显示 的结果是不一样的。
// 通过构造函数创建类的对象时,必须是使用new关键字
let s1 = new Student(1, 'disen', '西安');
let s2 = new Student(2, 'jack', '北海');
s1.say() // 1 disen 西安
s2.say() // 2 jack 北海
2.3 JSON对象与数组
JSON(JavaScript Object Notation - js对象的简述), 只描述对象的数据属性,即去除了对象的行为方法。json对象包含两种类型, 即是json对象 {}, json数组 [ ]。
2.3.1 JSON对象
普通json对象
let p1 = {
id: 1,
name: 'jack'
};
带有jsno数组的对象
let p2 = {
id: 2,
name: 'disen',
loves: ['音乐','程序', '电影']
}
带有其它对象的对象
let p3 = {
id: 3,
name: 'lucy',
father: {
name: 'disen',
age: 40,
address: {
name: '西安市高新六路',
city: '陕西省西安市'
}
}
}
2.3.2 json数组对象
let cates = [
{
title: '家电'
top: [
{
name: '热销',
url: '/rx',
icon: '/imgs/rx.png'
},
{
name: '818活动',
url: '/a818',
icon: '/imgs/a818.png'
},
]
},{
title: '手机'
top: [
{
name: '热销',
url: '/rx',
icon: '/imgs/rx.png'
},
{
name: '818活动',
url: '/a818',
icon: '/imgs/a818.png'
},
]
}
]
2.4 json对象的序列化与反序列化
json格式的数据,主要用于前后端接口交互的数据格式之一,如前端将json 对象的数据传给后端 ,则需要做以下几件事件:
-
序列化, 将json对象序列化json格式的字符串,即将属性和属性值转成key:value, key使用字符串表示的。
let p3_str = JSON.stringify(p3); typeof p3_str === 'string' //true
-
将请求头的Content-Type改为 application/json
如果后端请求成功后,响应的数据是json数据时(响应头中Content-Type参数值是 application/json),前端需要将json格式的字符串进行反序列化,之后以对象的属性方式来访问json数据。
let person = JSON.parse(p3_str);
person.id // 3
2.5 综合案例-加载分类
创建本地的json数据文件, cate.json
{
"total": 4,
"data": [
{
"name": "手机",
"url": "http://www.baidu.com/s?wd=手机"
},
{
"name": "平板",
"url": "http://www.baidu.com/s?wd=平板"
},
{
"name": "智能手表",
"url": "http://www.baidu.com/s?wd=智能手表"
},
{
"name": "AI音箱",
"url": "http://www.baidu.com/s?wd=AI音箱"
}
]
}
-
加载商品类型
fetch('cate.json') .then(response=>response.text()) .then(result=>{ // 解析 console.log(result) })
-
解析商品类型的数据,并生成DOM标签
声明创建li标签元素对象的函数
function createCategory(name, url, element_name='li') { let element = document.createElement(element_name) let a = document.createElement('a') a.setAttribute('href', url) a.innerText = name element.appendChild(a) return element }
html的内容, 显示分类的位置
<ul id="cate"> </ul>
解析js代码
fetch("cate.json") .then(respone=>respone.text()) .then(result=>{ // 将json格式的文本数据转成json对象 let respData = JSON.parse(result); let data = respData.data; // Array [] let ul_e = document.getElementById('cate') for(let i in data){ let category = data[i] // Object {} ul_e.appendChild(createCategory(category.name, category.url)) } });
三、正则的使用(Regular Expression)
3.1 正则的创建
-
// 创建, 语法: /正则表达式/img
img可以组合使用,分别使用也可以, i 忽略大小写,m多行, g 全局搜索
let phone_regexp = /1[3-57-9]\d{9}/ig
-
RegExp类创建
let name_min_len = RegExp('\\w{6,}', 'img') // 转成 /\w{6,}/gim
3.2 正则的使用
-
test()方法
test()方法的返回结果是true或false, 一般在if条件中使用
let phone = '1110' if(phone_regexp.test(phone)){ console.log('phone is ok!') }else{ console.log('phone is error!') }
如果正则表达式中,存在分组,可以通过 RegExp.$1…99 方式提取分组的内容。
let format = 'yyyy-mm-dd'; let year_regexp = /(y+)/ig if(year_regexp.test(format)){ // format字符串存在y字符 console.log(RegExp.$1) // 显示正则中第一个分组获取的字符串: yyyy }
-
exec()方法
exec()匹配正则中的数据, 分组中的匹配数据结果,通过RegExp.$1…99来提取。
-
String相关的方法
format.match(/\w+/)
format.search( /\w{6}/ig )
format.replace(regexp, ‘newstr’)
format.split(regexp)
四、日期时间与定时器
4.1 日期时间类-Date
-
创建Date类对象,Date对象中包含年、月(0-11)、日、周、时、分、秒、毫秒
<div id="currentDate"></div> <script> function showDate() { let date = new Date() let date_str = "yyyy-mm-dd HH:MM:SS" date_str = date_str.replace(/y+/, date.getFullYear()) //四位 年 .replace(/m+/, date.getMonth()+1) // 月 0-11 .replace(/d+/, date.getDate()) // 日 .replace(/H+/, date.getHours()) // 小时 .replace(/M+/, date.getMinutes()) // 分钟 .replace(/S+/, date.getSeconds()) // 秒 document.getElementById('currentDate').innerHTML=date_str } window.onload = function () { showDate() } </script>
另外,获取当前时间的方式:Date.now()
-
使用日期时间格式的字符串生成Date对象
new Date('2019-10-12') new Date('2019-10-12 17:24:30') new Date('2019/10/12 17:24:30') new Date('10 12 2019 17:24:30') // 月 日 年 new Date('12,10 2019 17:24:30') // 月,日 年 new Date('12/10 2019 17:24:30') // 月/日 年 new Date('12/10/2019 17:24:30') // 月/日/年
4.2 扩展-自定义格式化Date
可以使用Date.prototype原型的方式设置格式化日期的函数,如 format
Date.prototype.format = function (format_str) {
let o = {
"(y+)": this.getFullYear(),
'(m+)': this.getMonth() + 1,
'(d+)': this.getDate(),
'(H+)': this.getHours(),
'(M+)': this.getMinutes(),
'(S+)': this.getSeconds(),
'(s+)': this.getMilliseconds()
}
for (key in o) {
if (RegExp(key).test(format_str)) {
if (key === '(y+)')
format_str = format_str.replace(RegExp.$1,
String(o[key]).substr(4 - RegExp.$1.length))
else if(key == '(s+)')
format_str = format_str.replace(RegExp.$1,
String(o[key]).substr(0, RegExp.$1.length))
else {
let key_len = RegExp.$1.length;
let val_len = String(o[key]).length;
format_str = format_str.replace(RegExp.$1,
key_len == 1 ? o[key] : ("00" + o[key]).substr(val_len))
}
}
}
return format_str;
};
format函数必须返回格式之后的字符结果。
let date = new Date()
date_str = date.format('yyyy-mm-dd HH:MM:SS sss') // 2019-08-06 18:07:10 998
4.3 setInterval()定时器
let id = setInterval(function(){}, interval_ms)
clearInterval(id)
setInterval(function(){
let date = new Date()
date_str = date.format('yyyy-mm-dd HH:MM:SS sss')
document.getElementById('currentdate').innertHTML = date_str
}, 1000)
var interId = 0;
window.onload = function () {
interId = setInterval(function () {
let current_datetime = new Date()
document.getElementById('currentDate').innerHTML = current_datetime.format('yyyy-mm-dd HH:MM:SS')
}, 1000)
}
4.4 setTimeout()延迟器
五、Ajax异步请求
Ajax是JS异步请求的全称, 包含请求对象XMLHttpRequest、FormData及请求资源与数据解析等一系列操作。