操作浏览器
Window对象
BOM(浏览器对象模型)
- 浏览器对象模型,是浏览器内置中的全局对象
- 包含了
navigator、location、document、history、screen5个属性,即所谓的BOM(浏览器对象模型)
定时器-延时函数
定义
JavaScript 内置的一个用来让代码延迟执行的函数
语法
setTimeout (回调函数, 等待的毫秒数)
特点
setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略 window
清除延时函数
-
设置句柄
let timer = setTimeout(回调函数, 等待的毫秒数) -
清除
clearTimeout(timer)
拓展
-
通过递归
setTime可以实现setIntervalfunction test() { div.innerText = new Date().toLocaleString() // :一个函数调用自身,就形成 函数递归 setTimeout(test, 1000) } test() -
通过自清除
setInterval可实现setTimeoutfunction time() { let tid = setInterval(() => { console.log(1); clearInterval(tid) }, 1000); } time() -
两种定时器对比
-
setInterval- 重复执行,首次执行会延时
- 自清除可模拟
setTimeout
-
setTimeout- 延时执行,只执行 1 次
- 结合递归函数,能模拟
setInterval重复执行 - clearTimeout 清除由 setTimeout 创建的定时任务
-
JS执行机制
同步和异步
-
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
-
异步
在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。
-
本质区别
这条流水线上各个流程的执行顺序不同。
执行过程
-
同步任务
同步任务都在主线程上执行,形成一个执行栈。
-
异步任务
js的异步是通过回调函数实现的,都放在任务队列中。 -
类型
- 普通事件,如
click、resize等 - 资源加载,如
load、error等 - 定时器,包括
setInterval、setTimeout等
- 普通事件,如
执行机制
- 先执行执行栈中的同步任务,异步任务(回调函数)放入任务队列中(任务队列也称为消息队列)
- 一旦执行栈中所有同步任务执行完毕,系统会按次序读取任务队列中的异步任务,开始执行
- 由于主线不断地重复获取任务、执行任务、再获取任务、再执行任务,这种机制被称为事件循环
图解
location 对象
定义
数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
常用属性和方法
-
href属性获取完整的URL地址,对其赋值时用于地址的跳转loacltionhref = 'http://www.baidu.com' -
search属性获取地址中携带的参数,符号 ?后面部分 -
hash属性获取地址中的啥希值,符号 # 后面部分 -
reload方法用来刷新当前页面,传入参数true时表示强制刷新
navigator 对象
定义
数据类型是对象,该对象下记录了浏览器自身的相关信息
常用属性和方法
通过 userAgent 检测浏览器的版本及平台
histroy 对象
-
数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
-
常用属性和方法
- 前进:
history.foward() - 后退:
history.back() - 前进或后退:
history.go(参数)——前进1步history.go(1);后退一步history.go(-1)
- 前进:
swiper 插件
- 插件定义:别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
- 官网 www.swiper.com.cn/
APi文档 www.swiper.com.cn/api/index.h…
本地存储
特性
- 数据存储在浏览器内
- 设置、读取方便、刷新不丢失数据
- 容量大
- 只能存储字符串
分类
-
loaclStorage-
特点
- 存储在浏览器物理空间中
- 除非手动删除,理论上可以永久存在
- 可以跨页面使用,但是要保证是同一个浏览器
- 可以存储5MB左右
- 以键值对的形式存储使用
-
语法
- 存储数据
loaclStorage.setItem('名字key',值value); - 获取数据
loaclStorage.getItem('名字key'); - 删除数据
loaclStorage.clear();
- 存储数据
注意事项 只能存储字符串,如果存储的不是字符串形式,会自动进行
toString()将数据转换为字符串 -
存储复杂类型
- 本地只能存储字符串,无法存储复杂数据类型,要把复杂数据类型转换为
JSON字符串再存储到本地 - 将复杂数据转换成JSON字符串,存储 本地存储中
JSON.stringify(复杂数据类型) - 将
JSON字符串转换成对象,取出 时候使用JSON.parse(JSON字符串)
-
sessionStorage(了解)- 特点
api和localStorag一样- 它是存储在浏览器的缓存空间中
- 只是关闭当前会话,就会消失
- 不同会话不能混用,那个会话存储就只能这个会话使用
- 以键值对的形式存储使用
- 特点
自定义属性
固有属性
标签天生自带的属性 比如 class id title等,又叫做内置属性,可以直接使用点语法操作
自定义属性
由程序员自己添加的属性,在 DOM 对象中找不到,无法使用点语法操作,必须使用专门的 API
随便自定义属性
- 获取自定义属性
getAttribute('属性名') - 设置自定义属性
setAttribute('属性名', '属性值') - 删除自定义属性
removeAttribute('属性名')
data-自定义属性
- 定义:在标签上一律以
data-开头 - 获取:以
dataset对象方式获取
总结
综合案例
数据编辑
整体效果如下所示。
点击编辑按钮会跳出模态框,同步当行的数据,修改数据后点击保存按钮后会保存数据重新渲染页面,并且刷新后也不会复原。
页面结构布局:
该页面并没有用到自己写,而是使用 bootstarp 框架,bootstarp官网点击 javastrapt 组件,找到模态框,复制以下代码即可。
然后修改一下里面的内容。
<!-- 编辑模态框 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">编辑</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">分类名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="name" placeholder="请输入分类名称" />
</div>
</div>
<div class="form-group">
<label for="slug" class="col-sm-2 control-label">分类别名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="slug" placeholder="请输入分类别名" />
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
取消
</button>
<button type="button" class="btn btn-primary btnsave">保存</button>
</div>
</div>
</div>
</div>
最后引入 css 样式与 js 、 jquery 包即可。
js 步骤解析:
-
获取事件源,由于这几个数据都是未来事件类型,因此要用到事件委托,获取他们的父类
tbody。再获取名称和别称表单与保存按钮。let tbody = document.querySelector('tbody') let name = document.querySelector('#name') let slug = document.querySelector('#slug') let btnsave = document.querySelector('.btnsave') -
声明一个数组模拟假数据,在封装一个页面渲染函数方便后续重复渲染,避免代码冗余。渲染页面步骤如下:
- 设置一个新变量
htmlStr,赋值空字符串。 - 对数组进行遍历,用拼接字符串以及模板字符串的方式添加结构。
- 为
tbody赋值。
// 1.模拟数据 let list = [ { id: 1, name: '爱代码', slug: 'love code' }, { id: 2, name: '爱调试', slug: 'love debug' }, { id: 3, name: '爱作业', slug: 'love homework' } ] // 2.实现动态渲染:遍历+拼接 function init() { let htmlStr = '' list.forEach(function(v, i) { htmlStr += `<tr> <td>${v.name}</td> <td>${v.slug}</td> <td class="text-center" width="100"> <button type="button" class="btn btn-primary btn_edit" data-id='${v.id}' data-name='${v.name}' data-slug='${v.slug}'>编辑</button> </td> </tr>` }) tbody.innerHTML = htmlStr } init()- 使用自定义
data-把id号、名称和别名属性存储起来。
- 设置一个新变量
-
事件委托的方式绑定事件。由于每项数据都不是固定写死的,会未来生成或删除,因此用事件委托来实现。为父类
tbody绑定点击事件:e.target可以获取被点击是那个元素,类名是内置属性,因此可以直接e.target.classList.contains()进行类名判断被点击的是否是编辑按钮,如果是编辑按钮,则弹出模态框。- 获取之前存储的自定义属性
e.target.dataset,让模态框的名称表单与别名表单的值等于这两个属性。 - 设置一个全局变量
id,再在这里获取前面存储的id值,用于后面保存操作的id识别。如果这里没有设置成全局变量,而是直接用let声明,则会因为作用域问题报错,提示变量id未声明。
tbody.addEventListener('click', function(e) { if (e.target.classList.contains('btn_edit')) { // 填充默认数据 // 1.先获取你要填充的数据 let data = e.target.dataset console.log(data); id = data.id // 2.填充数据 name.value = data.name slug.value = data.slug $('#myModal').modal('show') } }) -
点击保存按钮后,对数组进行循环遍历,判断:
- 如果某一项
list[i].id值等于当前被点击的编辑按钮的id则把表单内的值赋值给这一项的数据。 - 渲染页面
- 做本地存储,由于是复杂数据,因此要先转为
Json格式,代码语法为:loaclStorage.setItem('book', JSON.stringify(list)),前面渲染页面函数内也要做这项操作,在发生改动之后渲染完页面也要再一次做本地存储。光存储不调用也不行,此时数组list无需使用固定死的数组数据,直接调用本地存储的数据,代码语法为:let list = JSON.parse(localStorage.getItem('book')) || []。 - 点击保存按钮后关闭模态框,这项去看
bootstarp官网文档即可。
function init() { let htmlStr = '' list.forEach(function(v, i) { htmlStr += `<tr> <td>${v.name}</td> <td>${v.slug}</td> <td class="text-center" width="100"> <button type="button" class="btn btn-primary btn_edit" data-name='${v.name}' data-id='${v.id}' data-slug='${v.slug}'>编辑</button> </td> </tr>` }) tbody.innerHTML = htmlStr localStorage.setItem('book', JSON.stringify(list)) }btnsave.addEventListener('click', function() { // 循环数组,进行判断 for (let i = 0; i < list.length; i++) { // 如果数组里的id值等于当前被点击的id,则更改它的值为表单的值 if (list[i].id == id) { list[i].name = name.value list[i].slug = slug.value } init(); localStorage.setItem('book', JSON.stringify(list)); // 渲染页面,关闭编辑页面 $('#myModal').modal('hide') } }) - 如果某一项
注意:
数组引用本地存储使用到或运算
||,如果本地没有数据,则前半部分为假,或运算会把后半部分的空数组赋给list,如果本地有数据,则短路运算,直接把数据给list。这一步的目的是为了防止本地没数据list为null,空没有forEach属性而报错。