# 基础知识点
# web apis和js基础关联性
# js的组成
- JavaScript
- ECMAscript javascript语法 JavaScript基础
- DOM 页面 文档对象模型 web apis
- BOM 浏览器对象模型 web apis
# 获取元素
# 根据id名获取元素
document.getElementById('time');
- 参数 字符串id名
- 返回 对应dom节点
- get 获得 element 元素 by 通过 驼峰命名法
- 参数 id是大小写敏感的字符串
console.dir(timer)
- 打印我们返回的元素对象 更好的查看里面的属性和方法
# 根据标签名获取
document.getElementsByTagName('li');
- 参数 字符串标签名
- 返回 伪数组
// 1. 通过标签名获取节点 : 返回伪数组
// document.getElementsByTagName(字符串类型的标签名)
var inps = document.getElementsByTagName('input');
// console.log(inps);
# 获取父元素指定标签名
获取某个元素(父元素)内部所有指定标签名的子元素 注意:父元素必须是单个对象(必须指明是哪一个元素对象).获取的时候不包括父元素自己 获取ol里面的li
var ol=document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
# 通过html5新增的方法获取
ie9+支持
# 1.根据类名返回元素对象 box是对象
document.getElementsByClassName('box')
- 参数 字符串类名
- 返回 伪数组
// 2. 通过类名获取节点: 返回伪数组
// document.getElementsByClassName(字符串类名的类名)
var btns = document.getElementsByClassName("btn");
# 2. 直接写选择器 根据指定选择器返回第一个元素对象
切记 里面的选择器需要加符号 .box #nav
var firstbox=document.querySelector('.box')
返回一个节点,如果页面中有多个标签使用了这个选择器 只返回第一个 没有这个节点返回null
# 3.返回指定选择器的所有元素对象集合
//参数 字符串类型的css选择器, 多个选择器逗号隔开
var allBox = document.querySelectorAll('.box');
document.querySelectorAll('.box,.father')
返回伪数组 "参数1,参数2"
# 特殊元素获取
# 1.获取body 元素
var bodyEle = document.body;
# 2.获取html 元素
// var htmlEle = document.html;
var htmlEle = document.documentElement;
# dom节点属性
# 行内样式 style
# className
// className // 1. 如果是控制单个类名, 没有影响 // 2. 如果要是控制多个类名: 添加可以多次添加; 思考: 删除比较麻烦
# classList
伪数组: 有索引, 有数据, 可遍历 // add() : 添加类名 btn1.onclick = function() { box.classList.add("aa"); } // remove(): 移除类名 btn2.onclick = function() { box.classList.remove("dd"); } // toggle(): 切换 btn3.onclick = function() { box.classList.toggle("daqiu"); }
标准属性 与html属性写法一致 class除外
- src
- value
- checked true false
# 自定义属性
//如果保存自己业务方面需要的数据, 可以自定义HTML属性保存自己任何想要的数据 // 自定义HTML属性也要满足HTML标准属性的语法 k="v" , 工作中可以: data-xx="xx"; // **** js如何获取自定义属性值 dataset var inps = document.getElementsByTagName("input"); // console.log(inps[0].dataset.guanxi); // dataset属性返回一个对象 // ****** 需求: 按钮单击, 修改img的src , 对应的按钮的data-xx自定义HTML属性的值 var img = document.getElementById("img"); inps[0].onclick = function() { img.src = inps[0].dataset.guanxi; } inps[1].onclick = function() { img.src = inps[1].dataset.guanxi; }节点方法 设置不带格式的自定义HTML的获取和设置方法
//回顾 :自定义html k="v" data-guanxi=""js:dataset.guanxi var box = document.querySelector("#box"); // console.log(box.dataset.zhangsan); // 不带个格式的自定义html的属性获取方法 console.log(box.dataset.abc); //undefined // 1.获取 // box.getAttribute(字符串类型的属性名) console.log(box.getAttribute("abc")); // 2.设置 // box.setAttribute("字符串类型的属性名","属性值") box.setAttribute("abc", "rrr")
# innerHTML
操作节点内的HTML,包含标签, 属性及文本内容
# innerText
操作节点内的文本内容
# 类属性的操作及html的
- 行内样式 style
- 类样式class className
- 类样式 classList
- 添加类名 add()
- 移除类名 remove()
- 切换类名 toggle()
- 标准属性 与html属性写法一致 class除外
- src
- value
- checked
- true
- false
- 自定义属性
- 设置 data-xx="值"
- 获取 dom节点.dataset.xx
# 获取元素在页面中的位置
- offsetLeft
- offsetTop
# 根据已有节点获取节点
| DOM节点.children | 返回该节点所有子节点, 伪数组 |
|---|---|
| DOM节点.parentNode | 返回该节点的父节点 |
# 添加节点
| 1. 创建节点 | createElement("字符串类型的标签名") |
|---|---|
| 2. 添加节点 | 结尾追加 appendChild() |
| 某个节点前追加 insertBefore(追加的节点, 位置节点) | |
| 3. 移除节点 | removeChild() |
# 节点.offsetWidth
返回该节点的实际宽度 = width + border + padding
# 节点.offsetHeight
返回该节点的实际高度
# dom节点方法事件类型
# 点击事件 onclick
btn.onclick = function () { alert("btn"); }
# 获得焦点 onfocus 失去焦点 onblur
# 操作自定义属性
- 获取 getAttribute()
- 参数: 字符串类型的属性名
- 返回: 属性值
- 设置 setAttribute()
- 参数1 : 字符串类型的属性名
- 参数2: 属性值
# 鼠标事件类型
| 鼠标按下 | mousedown |
|---|---|
| 鼠标移动 | mousemove |
| 鼠标弹起 | mouseup |
# 键盘鼠标事件类型
| 键盘按下 | keydown |
|---|---|
| 键盘弹起 | keyup |
| 鼠标移入 | mouseover |
| 鼠标离开 | mouseout |
# 阻止事件冒泡
// 事件冒泡: 父子级标签都绑定相同的事件: 先执行子DOM的事件; 再执行父DOM的事件
// div 和 button绑定 click -- alert(1) div(alert(2))
var div = document.querySelector("div");
var btn = document.querySelector("button");
// 如果想要阻止事件冒泡, 必须借助事件对象
btn.onclick = function(e) {
// e表示事件对象
// 阻止事件冒泡: 只执行自己的事件, 阻止的是事件逐层向父辈元素传递
e.stopPropagation();
alert(1);
}
div.onclick = function() {
alert(2);
}
# 新的注册事件方式
// 事件源.addEventListener(事件类型,function(e){});
// 执行函数可以是匿名函数也可以是函数(如果多个相同的事件的执行函数不想被覆盖, 执行函数必须有名字)
btn.addEventListener("click", function fn1() {
alert(1);
})
btn.addEventListener("click", function fn2() {
alert(2);
})
# 事件委托
// 优化: 如果很多节点都绑定相同的事件, 计算机存储多个执行函数, 占用内存
// 方案: js事件委托
// 把子级的事件委托给父级, 只给父级绑定一次单击事件, 事件内部: 判断用户单击的到底是哪个子级节点
var father = document.querySelector(".father");
father.addEventListener("click", function(e) {
// 如果用户单击的是left,弹窗left.....
// e.target 返回用户单击的真正的事件的元素对象: DOM节点 -- 说明之前所学的所有属性和方法都能使用
// console.log(e.target); // -- DOM节点
// 访问DOM节点的class属性值 : className classList
// console.log(e.target.className); // -- DOM节点
// 如果单击的DOM节点的类名==left, 表示是left标签弹窗left...
if (e.target.className == "left") {
alert("left");
} else if (e.target.className == "right") {
alert("right");
}
});
# 事件基础
事件是有三部分组成 事件源 事件类型 事件处理程序 我们也称为事件三要素
- 事件源 事件被触发的对象 谁 按钮
- 事件类型 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
- 事件处理程序 通过一个函数赋值的方式 完成
# 执行事件步骤
// 1. 获取事件源
var div = document.querySelector('div');
// 2.绑定事件 注册事件
// div.onclick
// 3.添加事件处理程序
div.onclick = function() {
console.log('我被选中了');
}
# 添加事件监听
- 语法 dom节点.DOM节点.addEventListener(事件类型, 执行函数,事件执行阶段)
- true : 事件在捕获阶段执行
- false : 事件在冒泡阶段执行
- 优点: 多个注册不同函数, 不会被覆盖
# 事件执行流程
- 捕获阶段
- 到达目标
- 冒泡阶段 事件默认在冒泡阶段执行
# 阻止事件冒泡
- e.stopPropagation();
# 事件委托
- 优点
- 减少事件绑定次数, 优化代码
- 可以给程序添加的节点绑定事件
- 步骤
- 事件只注册一次, 只给父节点注册事件
- 需要知道事件操作的真正DOM:e.target
# 事件对象
# e.target
1.返回时间对应的真正的DOM 2.e.target.nodeName 返回字符串型的DOM标签名(大写)
# e.currentTarget
返回事件源节点
# 坐标系
- 可视区坐标系配合固定定位的盒子使用
- e.clientX
- e.clientY
- 页面坐标系配合绝对定位的盒子使用
- e.pageX
- e.pageY
# 阻止默认行为
- e.preventDefault();
- a的默认行为
- href="javascript:void(0);"
- e.preventDefault();
- return false
- 禁止浏览器右键
- document.oncontextmenu = function(e) { e.preventDefault(); }
# 事件解绑
- DOM节点.on事件类型 = null
- DOM节点.removeEventListener(事件类型, 执行函数名);
# 事件对象.keyCode
- 作用: 判断按下的是哪个键
- 回车键: 13
# 事件对象.ctrlKey
- 如果按下的是ctrl键, 返回true
# 操作元素
// innerText 和 innerHTML的区别
// 1. innerText 不识别html标签 非标准 去除空格和换行
var div = document.querySelector('div');
// div.innerText = '<strong>今天是:</strong> 2019';
// 2. innerHTML 识别html标签 W3C标准 保留空格和换行的
div.innerHTML = '<strong>今天是:</strong> 2019';
// 这两个属性是可读写的 可以获取元素里面的内容
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
# this规则
- this 规则:谁调⽤函数,this就指向谁。
var inps = document.getElementsByTagName("input");
var img = document.getElementById("img");
// this : 表示的是注册事件的标签 / 指向当前发生事件的标签
inps[0].onclick = function() {
img.src = this.dataset.guanxi;
}
inps[1].onclick = function() {
img.src = this.dataset.guanxi;
}
inps[2].onclick = function() {
img.src = this.dataset.guanxi;
}
# 本地存储
注意: 存储的key必须是字符串
- 简单类型 直接存储
- 复杂类型 JSON
- JSON.stringify() 复杂数据类型转换成json格式字符串
- JSON.parse() json格式字符串转换成复杂数据类型 数组 对象
localstorage
存储 setItem(key, vlaue) 读取 getItem(key) 移除 removeItem(key) 清除 clear()
# BOM
浏览器对象模型 window window对象的属性和方法, 大部分都可以省略window
方法
onload()
- 当页面加载完毕(包含静态资源必须书写)
- window.onload = function(){}
定时器
单次定时器
设置 var timer = setTimeout(执行函数, 延迟时间) 清除 clearTimeout(timer) 多次定时器
设置 var timer = setInterval(执行函数, 延迟时间) 清除 clearInterval(timer)
属性
- location.href 设置或获取浏览器地址栏内容
- getComputedStyle(节点) 返回值: 该节点的所有css属性的集合的对象
# 基础一
# 一. 课程介绍
学习DOM+BOM的属性和方法,并使用它们实现页面上的效果;
# 1.1 DOM

- DOM - document object model - 文档对象模型:
document上方法 - DOM树:一个
树形结构 ,把整个树状的模型,这个对象称为文档对象模型; - 节点:树形结构里面的每个交叉点(HTML标签),在JS被称为
节点,也叫DOM节点; - 我们现在认知的节点包括: 标签本身、标签上的属性(src、id、class、style等)、标签内文本;
# 二. 案例开灯关灯
# 2.1 DOM-获取ById-注册click-属性style
- 获取元素: getElementById("id名");
- 事件: 节点.onclick= function(){}
- 控制节点的行内css样式 : 节点.style
// 一 获取节点
// document.getElementById(字符串类型的id名):返回对应的DOM节点
// 文档 获取 id
var btn = document.getElementById('btn');
// console.log(btn);
// 二.单击事件: btn 加一个单击事件:弹窗1
btn.onclick = function () {
alert(1);
}
// 三个问题
// 1.事件添加(注册给谁)
// 2.用户触发方式是什么
// 3.触发之后发生什么事情
// 三. js属性控制css属性 节点属性style 只能获取和修改行内样式css样式
console.log(btn.style.width);
console.log(btn.style.height);
btn.style.backgroundColor = "red";
// 四. 拓展: html属性写法绝大多数和js节点属性写法一致的(标准属性: html标签出厂自带的属性). class属性除外
// img的src
var img = document.getElementById("img");
console.log(img.src);
# 2.2. DOM-案例-两个按钮开关灯

// 需求: 关灯按钮单击: body变黑色; 开灯按钮单击: body变白色
// 给谁添加事件? 触发方式是什么click? 触发之后发生什么事情
var close = document.getElementById("close");
var open = document.getElementById("open");
// 关灯按钮单击
close.onclick = function() {
document.body.style.backgroundColor = "#000";
}
// 开灯按钮单击
open.onclick = function() {
document.body.style.backgroundColor = "#fff";
}
# 2.3 DOM-案例-一个按钮开关灯
// 需求: 一个按钮开关灯
// 如果是关灯:执行关灯的代码; 如果是开灯:执行开灯的代码
var btn = document.getElementById("btn");
btn.onclick = function() {
// 如果btn的文字是关灯 -- 获取到value属性值 判断是否是关灯
// console.log(btn.value);
if (btn.value == "关灯") {
// 背景色变黑色
document.body.style.backgroundColor = "#000";
// 文字变开灯-控制value
btn.value = "开灯";
} else {
// body背景色变白
document.body.style.backgroundColor = "#fff";
// value - 关灯
btn.value = "关灯";
}
}
# 三. 案例-搜索案例
# 3.1 DOM-注册focus和blur
事件类型:
- 获得焦点: focus
- 失去焦点:blur
var search = document.getElementById("search");
var list = document.getElementById("list");
// 1. 文本框获得焦点: 菜单显示display:block
search.onfocus = function() {
// console.log(1);
list.style.display = "block";
}
// 2. 文本框失去焦点: 菜单隐藏display:none
search.onblur = function() {
list.style.display = "none";
}
# 3.2 DOM-类样式-className
// 需求: 按钮单击: 给box添加类名bgc_2
var btn = document.getElementById("btn");
var box = document.getElementById("box");
btn.onclick = function() {
// console.log(box.className);
// 添加类名
// box.className = "bgc_2"; // 覆盖
box.className += " bgc_2";
}
// className
// 1. 如果是控制单个类名, 没有影响
// 2. 如果要是控制多个类名: 添加可以多次添加; 思考: 删除比较麻烦
# 3.3 DOM-类样式对象-classList-语法
- 添加类: add()
- 移除类: remove()
- 切换类: toggle()
// 手动书写一个数组
var arr = [1, 2, 3, 4];
console.log(arr);
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var box = document.getElementById("box");
console.log(box.classList); // ?? 返回的是什么? 伪数组: 有索引, 有数据, 可遍历
// add() : 添加类名
btn1.onclick = function() {
box.classList.add("aa");
}
// remove(): 移除类名
btn2.onclick = function() {
box.classList.remove("dd");
}
// toggle(): 切换
btn3.onclick = function() {
box.classList.toggle("daqiu");
}
# 3.4 DOM-类样式对象-classList-搜索案例
var search = document.getElementById("search");
var list = document.getElementById("list");
// 1. 文本框获得焦点: 菜单显示: 给菜单添加show类
search.onfocus = function() {
// list.classList.add("show");
list.classList.toggle("show");
}
// 2. 文本框失去焦点: 菜单隐藏: 给菜单移除show类
search.onblur = function() {
// list.classList.remove("show");
list.classList.toggle("show");
}
# 四. 案例-美女相册
# 4.1 DOM-获取ByTagName和ByClassName
// 1. 通过标签名获取节点 : 返回伪数组
// document.getElementsByTagName(字符串类型的标签名)
var inps = document.getElementsByTagName('input');
// console.log(inps);
// 2. 通过类名获取节点: 返回伪数组
// document.getElementsByClassName(字符串类名的类名)
var btns = document.getElementsByClassName("btn");
// console.log(btns);
console.log(inps[0] == btns[0]);
# 4.2 DOM-案例-点击按钮切换图
var img = document.getElementById("img");
var inps = document.getElementsByTagName("input"); // 伪数组
// 单击按钮1, 把img的src属性值修改01.jpg
inps[0].onclick = function() {
img.src = "./images/01.jpg";
}
// 单击按钮2, 把img的src属性值修改02.jpg
inps[1].onclick = function() {
img.src = "./images/02.jpg";
}
# 4.3 DOM-案例-点击按钮切换图-自定义属性
- 属性: data-xx
- 获取:dataset.xx
// 如果保存自己业务方面需要的数据, 可以自定义HTML属性保存自己任何想要的数据
// 自定义HTML属性也要满足HTML标准属性的语法 k="v" , 工作中可以: data-xx="xx";
// **** js如何获取自定义属性值 dataset
var inps = document.getElementsByTagName("input");
// console.log(inps[0].dataset.guanxi); // dataset属性返回一个对象
// ****** 需求: 按钮单击, 修改img的src , 对应的按钮的data-xx自定义HTML属性的值
var img = document.getElementById("img");
inps[0].onclick = function() {
img.src = inps[0].dataset.guanxi;
}
inps[1].onclick = function() {
img.src = inps[1].dataset.guanxi;
}
# 4.4 DOM-案例-点击按钮切换图-this
var inps = document.getElementsByTagName("input");
var img = document.getElementById("img");
// this : 表示的是注册事件的标签 / 指向当前发生事件的标签
inps[0].onclick = function() {
img.src = this.dataset.guanxi;
}
inps[1].onclick = function() {
img.src = this.dataset.guanxi;
}
inps[2].onclick = function() {
img.src = this.dataset.guanxi;
}
# 4.5 DOM-案例-点击按钮切换图-遍历循环
var inps = document.getElementsByTagName("input");
var img = document.getElementById("img");
// 遍历inps, 修改img的src = 当前这个按钮的guanxi属性值
// for (var i = 0; i < inps.length; i++) {
// inps[i].onclick = function() {
// // img.src = this.dataset.guanxi;
// img.src = inps[i].dataset.guanxi; // i = 3
// }
// }
// console.log(i);
// let: 每次循环生成一个独立的块作用域 {i = 0}
// let: 每次循环生成一个独立的块作用域 {i = 1}
// let: 每次循环生成一个独立的块作用域 {i = 2}
for (let i = 0; i < inps.length; i++) {
inps[i].onclick = function() {
// img.src = this.dataset.guanxi;
img.src = inps[i].dataset.guanxi;
}
}
// const 常量
# 五. 案例-选选与反选
# 5.1 DOM-属性checked
// 如果是复选框, 是否勾选, checked的值是true还是false
// var ck = document.getElementById("ck");
// console.log(ck.checked);
// 按钮禁用disalbed
var btn = document.getElementById("btn");
btn.disabled = true;
# 5.2 DOM-案例-全选与反选
var checkAll = document.getElementById("checkAll");
var cks = document.getElementsByClassName("ck"); // 伪数组
// 1. 全选绑定单击事件
checkAll.onclick = function() {
// 设置子选项的选中状态 = checkAll的选中状态
// 子选项的checked = checkAll的checked的值
// console.log(checkAll.checked);
for (var i = 0; i < cks.length; i++) {
cks[i].checked = checkAll.checked;
}
}
// 2. 子选项绑定单击事件: 如果子选项的3个都选中了, 设置全选也是选中的; 否则全选不能选中
for (var i = 0; i < cks.length; i++) {
cks[i].onclick = function() {
// 看子选项中是否有某个是未选中, j不可能=3
for (var j = 0; j < cks.length; j++) {
// 如果有某个子选项是false值,说明未选中, break退出循环, j不可能=3
// 如果循环完成都没有进入到下面的分支, j从0,1,2,3 最终j的值是3
if (cks[j].checked == false) {
break;
}
}
if (j == 3) {
// 设置全选也是选中的
checkAll.checked = true;
} else {
checkAll.checked = false;
}
}
}
# 基础二
# 一. 获取-css选择器

// document.getElementById("box")
// document.querySelector(字符串类型的css选择器)
// 返回一个节点, 如果页面中有多个标签使用了这个选择器, 只返回第一个; 没有这个节点, 返回null
var father = document.querySelector(".father");
// console.log(father);
var fuqin = document.querySelectorAll(".father, li"); // 返回伪数组
console.log(fuqin);
# 二. 操作属性
// 回顾: 自定义HTML k="v" data-guanxi="" js: dataset.guanxi
var box = document.querySelector("#box");
// console.log(box.dataset.zhangsan);
// 不带格式的自定义HTML属性的获取和设置方法
// console.log(box.dataset.abc); // undefined
// 1. 获取
// box.getAttribute(字符串类型的属性名)
// console.log(box.getAttribute("abc"));
// 2. 设置
// box.setAttribute(字符串类型的属性名, 属性值)
box.setAttribute("abc", "daqiu");
# 三. 添加事件监听addEventListener
// 节点.on事件类型 = function(){}
// 1. 什么样的情况是on注册事件的方式无法解决
// A: 按钮注册单击 - alert(1); B添加功能: 单击按钮-alert(2) : 后边的覆盖前面的
var btn = document.querySelector("#btn");
// btn.onclick = function() {
// alert(1);
// }
// btn.onclick = function() {
// alert(2);
// }
// 2. 学新的注册事件的方式 : 添加事件监听
// btn.addEventListener(事件类型, 执行函数);
btn.addEventListener("click", function fn1() {
alert(1);
})
btn.addEventListener("click", function fn1() {
alert(2);
})
# 四. 事件冒泡与捕获-基础

// 看 : 事件在冒泡节点执行 , 如果父子级节点都注册了相同的单击事件 出现什么现象
// 冒泡现象: 事件默认在冒泡阶段执行: 从触发事件的节点, 逐层向父级传递
var div = document.querySelector('div');
var btn = document.querySelector('button');
btn.onclick = function() {
alert("btn");
}
div.onclick = function() {
alert("div");
}
# 五. 事件冒泡与捕获-多级注册
// 1.注册事件: 添加事件监听; 2. 看事件在冒泡阶段执行; 3. 改变事件在捕获阶段执行 addEventListener()参数3:布尔型 , 默认是false在冒泡阶段执行; true在捕获阶段执行
var box_1 = document.querySelector(".box_1")
box_1.addEventListener("click", function() {
alert("box_1");
}, true)
var box_2 = document.querySelector(".box_2")
box_2.addEventListener("click", function() {
alert("box_2");
}, true)
var box_3 = document.querySelector(".box_3")
box_3.addEventListener("click", function() {
alert("box_3");
}, true)
# 六. 阻止冒泡
// 看 : 事件在冒泡节点执行 , 如果父子级节点都注册了相同的单击事件 出现什么现象
// 冒泡现象: 事件默认在冒泡阶段执行: 从触发事件的节点, 逐层向父级传递
var div = document.querySelector('div');
var btn = document.querySelector('button');
// 阻止事件冒泡, 借助事件对象, 一个方法
btn.onclick = function(e) {
// e.stopPropagation(); 阻止事件冒泡 : 阻止事件逐层向父级传递
e.stopPropagation();
alert("btn");
}
div.onclick = function() {
alert("div");
}
# 七. 事件委托使用场景
var father = document.querySelector(".father");
var left = document.querySelector(".left");
var right = document.querySelector(".right");
left.onclick = function(e) {
alert("个人信息");
e.stopPropagation();
}
right.onclick = function(e) {
alert("配置信息");
e.stopPropagation();
}
father.onclick = function() {
alert(Math.random());
}
# 八. 事件委托
// 目标: 事件委托: 有5个子级节点, 都有相同的事件, 为了减小事件绑定的次数, 把事件委托给父级节点
var father = document.querySelector(".father");
father.addEventListener("click", function(e) {
// console.log(1);
// **** 将来用户单击不同的子级, 触发不同的代码
// 判断: 用户到底单击的是哪个子级节点: 如果单击的标签的类名是left, 表示单击到了left节点, 执行left的相关需求代码
// ?? 获取类名 className classList
// 目标: 新的知识: 确定用户单击的标签的className值
// e.target 返回用户单击的节点
// console.log(e.target.className);
var lei_name = e.target.className;
if (lei_name == "left") {
alert("left");
} else if (lei_name == "right") {
alert("right");
}
})
# 九. 事件对象的属性和方法
// 一. 事件对象的属性
// 1. e.target , e.currentTarget
var parent = document.querySelector("#parent");
parent.onclick = function(e) {
// console.log(e.target); // 用户单击的节点,用户触发事件的节点
// console.log(e.currentTarget); // 返回注册事件的节点
}
// 2.鼠标坐标系 - 不要加给节点,加给body
document.body.onclick = function(e) {
// 2.1 浏览器可视区原点的距离 - 配合固定定位的盒子使用
// console.log(e.clientX, e.clientY);
// 2.2 页面左上角的距离 - 配合绝对定位的盒子使用
console.log(e.pageX, e.pageY);
}
// 二. 事件对象方法: 阻止默认行为
//javascript:void(0)
// var aa = document.querySelector("a");
// aa.onclick = function(e) {
// // e.preventDefault();
// return false;
// }
// 浏览器右键弹菜单
document.oncontextmenu = function(e) {
e.preventDefault();
}
# 十. 事件委托
# 10.1 新增标签
// 单击按钮, ul里面新增li
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
btn.onclick = function() {
// 节点属性 节点.innerHTML: 获取和设置某个节点内的节点
// console.log(ul.innerHTML);
// 节点.innerText: 节点内的文本内容
// console.log(ul.innerText);
// 新增li
// ul.innerHTML += '<li class="son">新的li</li>'
ul.innerText += '<li class="son">新的li</li>'
}
# 10.2 所有标签注册事件
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
// 1. 按钮单击新增li
btn.onclick = function() {
ul.innerHTML += '<li class="son">我是新的li</li>';
// 2. li单击,弹窗1
var lis = document.querySelectorAll("ul li");
// console.log(lis);
// lis.onclick = function() {
// alert(1);
// }
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
alert(1);
}
}
}
// 2. li单击,弹窗1
var lis = document.querySelectorAll("ul li");
// console.log(lis);
// lis.onclick = function() {
// alert(1);
// }
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
alert(1);
}
}
# 10.3 事件委托
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
// 1. 按钮单击, ul新增li
btn.onclick = function() {
ul.innerHTML += '<li class="son">新的li</li>'
}
// 2. 所有li注册单击事件alert(1) -- 事件委托
ul.onclick = function(e) {
// 判断单击的标签如果是li弹窗
// 如果类名是son表示单击li, 弹窗 单击的节点.className
// console.log(e.target);
// if (e.target.className == "son") {
// alert(1);
// }
//拓展: 判断是哪个标签的方法
// console.log(e.target.nodeName); // 返回当前触发事件的大写的标签
if (e.target.nodeName == "LI") {
alert(2);
}
}
# 十一. 事件类型
var box = document.querySelector(".box");
// mousedown: 鼠标按下
box.onmousedown = function() {
console.log("down");
}
// mousemove: 鼠标移动
box.addEventListener("mousemove", function() {
console.log("move");
})
// mouseup: 鼠标松开/弹起
box.onmouseup = function() {
console.log("up");
}
# 十二. 案例: 鼠标跟随小天使
// 鼠标在body移动, 图片跟随: position: fixed;, 获取鼠标的位置, 设置img的left/top就是鼠标的位置的值
var img = document.querySelector("#img");
document.body.onmousemove = function(e) {
// 1. 获取鼠标坐标点 - 固定定位: 事件对象.client/Y
var x = e.clientX;
var y = e.clientY;
// console.log(x, y);
// 2. 设置img的left=鼠标水平坐标; img的top=鼠标垂直坐标
// left: 50px;
img.style.left = x + 'px';
img.style.top = y + 'px';
}
# 基础三
# 一. 获取元素对象在页面中的位置
// style: 行内
var son = document.querySelector(".son");
// console.log(son.style.left);
// offsetLeft: 获取盒子相对自己的offsetParent的水平距离
// offsetTop: 获取盒子相对自己的offsetParent的垂直距离
// 1. offsetParent: 返回定位的父节点, 没有这样的父节点, 逐层向上查找, 直到body
// console.log(son.offsetParent);
// 2. 节点属性
console.log(son.offsetLeft, son.offsetTop);
# 二. 事件解绑
var btn = document.querySelector("button");
// 注册onclick
// 解绑: 触发一次事件之后, 不能再继续触发
// btn.onclick = function() {
// alert(1);
// btn.onclick = null;
// }
// 注册: 添加事件监听: 如果事件需要解绑的话, 执行函数需要有名字
btn.addEventListener("click", function fn1() {
alert(2);
btn.removeEventListener("click", fn1);
})
// 注意: 两种事件注册方式和解绑方式不能交叉混用
# 三. 案例:鼠标拖动盒子
var box = document.querySelector(".box");
// 1. 鼠标按下box
box.onmousedown = function(e) {
// alert(1);
// 1.1 计算鼠标在盒子里面的距离(鼠标按下和鼠标移动的时候这段距离不变)
// 鼠标在盒子的水平位置 = e.pageX-盒子在页面的水平位置
var mouseLeft = e.pageX - box.offsetLeft;
var mouseTop = e.pageY - box.offsetTop;
// 2. 鼠标移动body: 盒子跟随鼠标
document.body.onmousemove = function(e) {
// console.log(1);
// 设置box盒子的left和top值. pageX/Y获取鼠标的位置
// 2.1 鼠标移动的时候计算盒子的left和top = 鼠标坐标点e.pageX - 鼠标在盒子里面的位置
var x = e.pageX - mouseLeft;
var y = e.pageY - mouseTop;
box.style.left = x + 'px';
box.style.top = y + 'px';
}
}
// 3. 鼠标松开: 取消盒子跟随鼠标 - 把鼠标移动事件解绑
box.onmouseup = function() {
document.body.onmousemove = null;
}
# 四. 操作节点
注意: 方法追加节点: 1.创建节点; 2.使用对应的方法追加
// 按钮单击, 实现用js方法新增节点
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
btn.onclick = function() {
// 如果使用js的方法新增节点, ***** 步骤:1. 创建节点, 2.新增
// document.createElement(字符串类型的标签名) -- 实现创建一个空的标签
var li = document.createElement("li");
// console.log(li);
// 往空节点里面放点内容
li.innerText = "我是新的节点";
// console.log(li);
// 1. appendChild(目标) -- 结尾新增节点
// ul.appendChild(li);
// 2. inserBefore(新增的节点, 追加的位置): 在任意位置新增节点
// 目标: ul的开头追加li
var first = document.querySelector("ul li:first-child");
ul.insertBefore(li, first);
}
# 五. 发布微博
// 发布按钮单击, 发布内容
// 发布按钮注册单击事件: 把用户输入的内容放到li的p标签, 把这个li放到ul里面开头位置
var text = document.querySelector(".weibo-text");
var btn = document.querySelector(".weibo-btn");
var ul = document.querySelector(".weibo-list");
btn.onclick = function() {
// 1. 获取用户输入内容: 如果表单控制, 获取用户输入的数据, 用到的都是value属性
// console.log(text.value);
var val = text.value;
// 2. 把用户输入的内容放到li的p里面(创建节点, 放内容)
var li = document.createElement('li'); // 空节点
// li.innerHTML = '<p>' + val + '</p><span>删除</span>';
li.innerHTML = `<p>${val}</p><span>删除</span>`
// console.log(li);
// 3. 把li添加到ul的开头
var first = document.querySelector(".weibo-list li:first-child");
ul.insertBefore(li, first)
// 4. 优化: 清空文本域
text.value = '';
}
# 六. 获取节点
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
btn.onclick = function() {
// children: 获取所有子节点, 返回伪数组
// console.log(ul.children[0]);
// parentNode: 获取父节点: 直接父级, 和定位无关
// console.log(ul.parentNode);
// 测试parentNode是否和父级定位有关
var li_2 = document.querySelector(".li_2")
// console.log(li_2.parentNode);
// 兄弟节点
// console.log(li_2.nextElementSibling);
console.log(li_2.previousElementSibling);
}
# 七. 发布微博-优化
根据已获取的DOM节点查询第一个子节点li
var text = document.querySelector(".weibo-text");
var btn = document.querySelector(".weibo-btn");
var ul = document.querySelector(".weibo-list");
// 按钮单击: 获取用户输入的数据, 放到li的p里面, 把ul的开头追加li
btn.onclick = function() {
var val = text.value;
var li = document.createElement("li");
li.innerHTML = `<p>${val}</p><span>删除</span>`;
// 获取ul节点的里面的第一个子节点
var first = ul.children[0];
ul.insertBefore(li, first);
text.value = null;
}
# 八. 删除节点
// 删除节点 removeChild(目标节点)
// 按钮单击, 删除ul里面的第一个节点
var btn = document.querySelector("#btn");
var ul = document.querySelector("ul");
btn.onclick = function() {
// 1. 选中目标节点
var first = ul.children[0];
// 2. removeChild()
ul.removeChild(first);
}
# 九. 发布微博-删除
// 二. 删除 - 未来的span和已有的span都有删除功能-事件委托
ul.onclick = function(e) {
// 判断用户单击的标签 span执行删除的功能 e.target.nodeName
if (e.target.nodeName == 'SPAN') {
// console.log("删除功能");
// 1. 找到要删除的目标单击的span的父级li parentNode
var del_li = e.target.parentNode;
// // console.log(del_li);
// // 2. removeChild
ul.removeChild(del_li);
//console.log(this);
}
}
# 十. 发布微博-删除优化-事件委托
# 十一. 数据本地化-localstorage

// 本地化存储数据 localstorage.方法
// 存储
// ***** 本地化存储数据的value必须是字符串类型
// js中有2种数据类型: 简单(可以直接存储, 自动隐式转换成字符串) 和 复杂(程序员手动书写程序转换成字符串后再存储)
// localStorage.setItem(key, value): 如果key相同,后面的覆盖前面的数据
// localStorage.setItem("a", "daqiu");
// localStorage.setItem("b", 1);
// localStorage.setItem("a", 100);
// 读取
// localStorage.getItem(key)
// console.log(localStorage.getItem("a"));
// 删除
// localStorage.removeItem(key)
// localStorage.removeItem("a");
// 清空
localStorage.clear();
# 十二. *JSON
// 1. 演示直接存储一个复杂数据类型到localstorage
var obj = {
name: "daqiu",
age: 18
}
// localStorage.setItem("dd", obj);
// 2. 学习转换方法
// 2.1 把复杂数据类型转成json格式的字符串 :都是双引号 {"name":"daqiu","age":18}
// var str = JSON.stringify(obj);
// console.log(str);
// localStorage.setItem('qq', str)
// 2.2 把json格式的字符串转成复杂数据类型
var str1 = "[1, 2, 3]";
var str2 = '{"name":"daqiu","age":18}';
// JSON.parse(字符串)
var arr1 = JSON.parse(str1);
// console.log(arr1);
var obj2 = JSON.parse(str2)
console.log(obj2);
# 十三. 微博案例-本地化存储
# 13.1 发布

# 13.2 初始化列表

# 基础四
# 一. BOM
BOM: browser object model,是把browser 浏览器看成是一个对象,就是学习浏览器对象的各种方法和属性;
浏览器对象:window对象;
# 1.1 window 对象
- 特点:
- 所有window对象的属性和方法,大部分可以直接省略
window,而直接使用 - 因为window对象在浏览器中被称为顶级对象;
- 顶级对象:页面中所有的东西都是依赖于这个对象存在的;
- 变量与函数:
- 所有的全局变量和全局函数都是window对象的属性和方法;
- 在js代码里面,不使用var声明的变量,都是隐式全局变量,这个方式是不推荐的,因为如果不使用var声明,是不会变量提升的;
- 所有window对象的属性和方法,大部分可以直接省略
# 1.2 方法: onload
<title>Document</title>
<!-- <script>
window.onload = function() {
var box = document.querySelector(".box");
console.log(box);
}
</script> -->
// 1. window是浏览器的顶级对象, 省略window
// localStorage.setItem("a", 1);
// window.localStorage.setItem("b", "daqiu");
var box = document.querySelector(".box");
// console.log(box);
var w_box = window.document.querySelector(".box");
// console.log(w_box == box);
// 2. 全局变量或函数, window属性或方法
// var a;
// console.log(a);
var a = 1;
// console.log(a);
// console.log(window.a);
// 3. 声明全局变量不加var 的 影响
// console.log(b); // 因为不能预解析, 报错b未定义
b = 10;
// console.log(window.b);
// 4. window的方法onload
// btn.onclick = function () { }
// onload 当页面加载完成的时候: 静态资源图片, html, css
// 有一种情况必须写window.onload: 当页面有图片的时候
// 图片: 预加载
window.onload = function() {}
# 1.3 属性: location
作用: 操作浏览器地址栏的信息, 可获取, 可设置
// location : 管理浏览器地址栏信息的属性, 返回对象
// window.location
// console.log(location);
location.href = "http://www.baidu.com"; // 修改浏览器地址栏的地址
# 1.4 方法: 定时器
定时器可设置, 可清除
# 1.4.1 语法-单次定时器
// 定时器window对象的方法, 定时器可开启可(清除: 关闭)
// 单次定时器
// setTimeout(执行函数, 延迟时间以毫秒为单位): 1000毫秒=1秒
// setTimeout 返回值是number类型, 是当前定时器的标识, 用来清除定时器
// var timer1 = setTimeout(function() {
// alert(1);
// }, 2000)
// var timer2 = setTimeout(function() {
// alert(1);
// }, 2000)
// console.log(timer1);
// console.log(timer2);
// // 按钮单击, 清除定时器
// btn.onclick = function() {
// // clearTimeout(定时器的标识)
// clearTimeout(timer);
// }
# 1.4.2 语法-多次定时器
// 多次定时器: 开启的函数的参数完全相同
var timer = setInterval(function() {
alert(2);
}, 2000);
btn.onclick = function() {
clearInterval(timer)
}
# 1.4.3 案例: 验证码
// 需求: 按钮单击: 按钮不能再点, 文字开始倒计时, 当倒计时到0的恢复默认
var btn = document.querySelector("#getCode");
btn.onclick = function() {
// 1. 按钮功能禁用 disabled:true
btn.disabled = true;
// 2. 文字变成 获取验证码(5) -- 开始倒计时
// 2.1 设置文字(5)
var num = 5;
btn.value = `获取验证码(${num})`;
// 2.2 倒计时
var timer = setInterval(function() {
num--;
btn.value = `获取验证码(${num})`;
// 2.3 倒计时到0的恢复默认 num=0
if (num == 0) {
// 2.3.1 按钮启用
btn.disabled = false;
// 2.3.2 定时器清除-不再倒计时
clearInterval(timer)
// 2.3.3 value值 获取验证码
btn.value = "获取验证码";
}
}, 1000);
}
# 二. 案例: 微博
# 2.1 事件类型 : keydown、keyup
var text = document.querySelector("#text");
// on... / 添加事件监听
// onkeydown: 键盘按下
text.onkeydown = function(e) {
// console.log(1);
// 一定条件判断: 判断用户按下的到底是哪个键: 借助事件对象的属性
// 事件对象.keyCode: 获取当前按下的键的键码: 回车键的键码是13
// console.log(e.keyCode);
// console.log(e.ctrlKey); // true / false
// ?? 用户同时按下了回车和ctrl键
// if (e.keyCode == 13 && e.ctrlKey == true) {
// console.log("恭喜你, 大哥, 按下ctrl+回车");
// }
if (e.keyCode == 13 && e.ctrlKey) {
console.log("恭喜你, 大哥, 按下ctrl+回车");
}
}
// onkeyup: 键盘按下 -松开
text.onkeyup = function() {
// console.log(2);
}
# 2.2 微博组合键发布
// ****** 第四天新增功能:ctrl+回车发布
text.onkeydown = function(e) {
// 如果用户同时按下ctrl+回车
if (e.ctrlKey && e.keyCode == 13) {
// console.log(1);
// btn.onclick = function () { } // 对象添加一个方法
// fn = function () { }
// btn.xx()
btn.onclick(); // 调用对象的方法
// 所有的事件类型本质就是对象的方法
}
}
# 2.3 微博-删除
数据可能是重复的, 不能直接找数据直接删除, 找到每个数据的唯一的身份标识, 按身份标识去删除
- 清空本地存储
- 存储数据: [{key:xx, shenfenzheng: xx}], 存储数据之前把对象添加身份证键值对
- 让span标签记录当前数据的身份证标识, 找到数据中和span记录的身份标识是一样的这个数据再删除
- 创建节点的时候, 把span添加了自定义HTML属性sfz=时间戳变量(span标签记录当前数据的身份证标识)
- span单击的地方: 获取span标签的sfz属性值; 遍历数组, 如果数组中对象的shenfenzheng属性值 == span的sfz属性值, log(找到我了)

需求:
- 删除li标签
- localstorage中的数据: 删除数组中的对象
// ***** 第四天删除功能: 标签 和 数据
ul.onclick = function(e) {
if (e.target.nodeName == "SPAN") {
// 删除li: 找到li, 删除它
// this.parentNode
var del_li = e.target.parentNode;
ul.removeChild(del_li);
// ------------以下是删除数据
// 找到数据中和span的sfz属性值相同的数据删除掉
// 1. 获取span的sfz属性值 -- 节点.getAtrr..()
var del_sfz = e.target.getAttribute("sfz");
// console.log(del_sfz);
// 2. 数据在数组里面, 是多条数据 , 遍历 , 如果找到相同的身份证 删除对象
for (var i = 0; i < arr.length; i++) {
if (del_sfz == arr[i].shenfenzheng) {
// console.log("大哥, 你找到我了");
// 删除数据: 删除数组中的对象, 删除一个对象
// arr.pop() arr.shift() arr.splice(位置, 个数, 添加的)
arr.splice(i, 1);
// console.log(arr); // arr的数据已经删除了 , 同步localstorage, 再往localstorage存储一遍: 先转成字符串, 再存储
var str = JSON.stringify(arr);
localStorage.setItem("aa", str)
}
}
}
}
# 三. tab栏
# 3.1 事件: mouseover 和 mouseout
var box = document.querySelector(".box");
// *** mouseover/mouseout: 当鼠标移入或离开子元素, 也能触发父元素的事件
// mouseover : 鼠标移入
// box.onmouseover = function() {
// console.log(1);
// }
// // mouseout: 鼠标离开
// box.onmouseout = function() {
// console.log(2);
// }
// mouseenter 和 mouseleave
box.onmouseenter = function() {
console.log(1);
}
// mouseout: 鼠标离开
box.onmouseleave = function() {
console.log(2);
}
# 3.2 案例: tab栏
window.onload = function() {
var lis = document.querySelectorAll(".tab-item")
var mains = document.querySelectorAll(".main");
// 排他思想: 只许州官放火不许百姓点灯: 1. 设置所有li都不能变红:删除类active;2. 设置鼠标移入的li变红
for (var i = 0; i < lis.length; i++) {
// 1.0 存储i为索引值(下边代码要用)
lis[i].setAttribute("index", i);
lis[i].onmouseover = function() {
// 1. 所有li移除active
for (var i = 0; i < lis.length; i++) {
lis[i].classList.remove("active");
}
// 2. 这个li添加active
this.classList.add("active");
// _______________ 控制内容显示
// 鼠标移入第一个li, 内容显示第一个;鼠标移入到第二个li,内容显示第二个
// 鼠标移入第一个li, 索引值0, 在四个div中找到索引值为0的显示
// 鼠标移入第二个li, 索引值1, 在四个div中找到索引值为1的显示
// .....
// 先获取鼠标移入的li的索引值, 用这个索引值找到对应的div 显示
// 1. 获取鼠标移入的li this的索引值,保存(并没有索引值属性, 自己自定义一个HTML属性, 去替代索引值) -- 1.0 在遍历的时候给li添加HTML属性存索引值i
var num = this.getAttribute("index");
// console.log(num);
// 3. 排他 - 设置所有div移除类
for (var i = 0; i < mains.length; i++) {
mains[i].classList.remove("selected");
}
// 2. 用这个索引值筛选对应的div显示,添加class属性值为selected
mains[num].classList.add("selected");
}
}
}
# 基础五
# 一. 轮播图
# 1.1 获取css属性值
# 1.1.1获取DOM节点样式
// window.getComputedStyle(节点)
// 返回的是: 对象 : 当前这个节点的所有css属性
var box = document.querySelector(".box");
var res = getComputedStyle(box);
// console.log(res);
// getComputedStyle返回的对象获取css属性值的时候, 返回的都是字符串
// 注意: *** 返回的只是属性值, 与盒子模型无关
console.log(res.width);
console.log(res.height);
console.log(res.backgroundColor);
# 1.1.2 获取元素对象的实际宽度和高度
元素的实际宽高 = border+padding+content(width和height)
// 节点属性
var box = document.querySelector(".box");
// 1. offsetWidth/offsetHeight
// console.log(box.offsetWidth); // 620 = width + padding + border
// console.log(box.offsetHeight);
// 2. clientWidth/clientHeight
console.log(box.clientWidth); // 520 = width + padding
console.log(box.clientHeight);
# 1.2 轮播图原理
布局:ul下有很多li标签;浮动在一行;
原理:切换图片的时候,把ul位置修改一下,给ul的父容器,设置一个 overflow:hidden;
功能需求:
- 左右按钮的轮播
- 自动轮播
- 鼠标在轮播图里面的时候,停止自动轮播,离开后继续自动轮播
- 基础
# 1.3 左右轮播
var points = document.querySelectorAll(".list i");
var ul = document.querySelector("#imglist");
// 1. 右侧箭头单击, 图片向左侧移动
var right = document.querySelector(".arrow-right");
// 一个索引值变量, 默认显示第一张图, 索引值为0
var index = 0;
// 获取图片的宽度
var w = document.querySelector("img").offsetWidth;
// console.log(w);
right.onclick = function() {
// 1. 索引值单击一次+1
index++;
// *** 经验: 先计算,再判断, 最后赋值
// 如果已经移动到第7张图(没有这个图片), 回到第一张
if (index == 6) {
index = 0;
}
// 2. 计算距离公式 -- 结果
var result = index * w;
// 3. 设置ul的left取值为第二步的结果 730px
ul.style.left = -result + 'px';
// *************圆点样式: 显示第几张图片, 这个数字对应的圆点添加current类, 其他的圆点删除current类
// 1. 排他:所有圆点删除类
for (var i = 0; i < points.length; i++) {
points[i].classList.remove("current");
}
// 2. 设置和图片索引对应的圆点添加类
points[index].classList.add("current");
}
// 2. 左侧箭头单击, 图片向右侧移动
var left = document.querySelector(".arrow-left");
left.onclick = function() {
// 1. 索引值单击一次-1
index--;
// *** 经验: 先计算,再判断, 最后赋值
// 如果已经移动到索引值取到-1,没有这样的图, 回到最后一张图index=5
if (index == -1) {
index = 5;
}
// 2. 计算距离公式 -- 结果
var result = index * w;
// 3. 设置ul的left取值为第二步的结果 730px
ul.style.left = -result + 'px';
// *************圆点样式: 显示第几张图片, 这个数字对应的圆点添加current类, 其他的圆点删除current类
// 1. 排他:所有圆点删除类
for (var i = 0; i < points.length; i++) {
points[i].classList.remove("current");
}
// 2. 设置和图片索引对应的圆点添加类
points[index].classList.add("current");
}
# 1.4 关联圆点
// *************圆点样式: 显示第几张图片, 这个数字对应的圆点添加current类, 其他的圆点删除current类
// 1. 排他:所有圆点删除类
for (var i = 0; i < points.length; i++) {
points[i].classList.remove("current");
}
// 2. 设置和图片索引对应的圆点添加类
points[index].classList.add("current");
# 1.5 自动轮播
// 3. 图片自动向左侧移动
var timer = setInterval(function() {
// 和右箭头单击事件是一样的效果
right.onclick();
}, 2000)
# 1.6 鼠标控制轮播
// 4. 鼠标移入到图片, 停止自动播放; 鼠标离开: 继续播放
// 不要给图片或ul注册事件, 图片是移动; ul范围比较大 -- 注册给显示区域是最合适
var box = document.querySelector("#box");
box.onmouseover = function() {
// 清除定时器
clearInterval(timer);
}
box.onmouseout = function() {
// *** 这里开启定时器不要加var, 因为添加了var导致开启多个定时器, 定时器有累加的问题
timer = setInterval(function() {
// 和右箭头单击事件是一样的效果
right.onclick();
}, 2000)
}
# 二. 案例: 手风琴
window.onload = function() {
var lis = document.querySelectorAll("#box li");
for (var i = 0; i < lis.length; i++) {
// 1. 鼠标移入: 这个li的宽度是800. 其他的li 的宽度是100
lis[i].onmouseover = function() {
// 1.1 控制所有li宽度是100
for (var i = 0; i < lis.length; i++) {
lis[i].style.width = '100px';
}
// 1.2 控制鼠标移入的li的宽度是800
this.style.width = "800px";
}
// 2. 鼠标离开: 所有li的宽度是240
lis[i].onmouseout = function() {
for (var i = 0; i < lis.length; i++) {
lis[i].style.width = '240px';
}
}
}
}
# 三. 案例: 旋转木马
原理:
- 按钮单击切换类名(类名存储到数组)
- 远近虚实效果只是css设置了不同的透明度和位置等
# 3.1 单击按钮切换(基础需求)
// 旋转木马: 用不同的css类名控制了 近实远虚, 单击切换类名
var ps = document.querySelectorAll("p");
var btn = document.querySelector("#btn");
// 把两个类名存到js中, 用js添加给2个p标签
var arr = ['pos_1', 'pos_2'];
// 1. 页面初始化
for (var i = 0; i < ps.length; i++) {
// 添加类名
ps[i].className = arr[i];
}
// 2. 按钮单击, 切换类名
btn.onclick = function() {
// ['pos_1', 'pos_2'];
// [ 'pos_2', 'pos_1']
// ['pos_1', 'pos_2'];
// p1 = pos_2
// p2 = pos_1
// 数组后面删除一个数据pop, 删除的这个数据添加到数组的开头unshift
var del_name = arr.pop();
arr.unshift(del_name);
// console.log(arr);
for (var i = 0; i < ps.length; i++) {
// 添加类名
ps[i].className = arr[i];
}
}
# 3.2 案例: 旋转木马

window.onload = function() {
// 1. 初始化: 5个li对应5个类名
var lis = document.querySelectorAll("#slide li");
var arr = ["left1", "left2", "middle", "right2", "right1"];
// for (var i = 0; i < lis.length; i++) {
// lis[i].className = arr[i];
// }
function change() {
for (var i = 0; i < lis.length; i++) {
lis[i].className = arr[i];
}
}
change();
// 2. 左右箭头单击
var left = document.querySelector("#arrLeft");
var right = document.querySelector("#arrRight");
right.onclick = function() {
// 2.1 改变数组里面类名的顺序 : left1去最后: arr 开头删除一个; 添加到结尾
var del_name = arr.shift();
arr.push(del_name);
// console.log(arr);
// 2.2 遍历把类名添加到标签li
// for (var i = 0; i < lis.length; i++) {
// lis[i].className = arr[i];
// }
change();
}
left.onclick = function() {
// 类名顺序: 结尾删除一个, 添加到开头: 发现最后一个标签的类名不是right1, 编程right2 -- 结尾删除一个类, 发现第一个标签去了最后一个位置right1(第一个标签添加类名right1)
var del_name = arr.pop();
arr.unshift(del_name);
// for (var i = 0; i < lis.length; i++) {
// lis[i].className = arr[i];
// }
change();
}
}
# 四. 360开机动画
# 4.1 动画或过渡结束事件
- 动画或者过渡结束事件:专门是指css3里面的 动画或者过渡 结束会触发的事件,css3动画有两种,结束动画事件也有两个;
- 特点:不能使用on的方式注册,只能使用addEventListener的方式注册
- transitionend:元素的过渡动画结束的时候触发;
- animationend:会在帧动画结束的时候触发,如果帧动画是无限次的,不会触发该事件animationend
// **** 这2组事件只能通过添加事件监听的形式注册
// transitionend:过渡完成之后触发的事件
// animationend: 动画完成之后触发的事件
var box = document.querySelector(".box");
// box.addEventListener("transitionend", function() {
// console.log(1);
// })
box.addEventListener("animationend", function() {
console.log(2);
})
# 4.2 案例
// 需求: x号按钮单击: 下半部分变换高度到0; 高度动画完成之后, 上半部width变换到0
var close = document.querySelector("#closeButton");
// 因为html和css是写好的, 观察添加过渡的标签到底是谁: 下半部和最大的box(改变宽度的不是上半部分是box)
var xia = document.querySelector("#bottomPart");
var box = document.querySelector("#box");
close.onclick = function() {
// 1. 下半部高度=0
xia.style.height = 0;
// 2. 下半部分高度为0后立刻触发transitionend: 大盒子box的宽度=0
// 事件添加给谁xia ; 触发方式; 触发之后发生什么事
xia.addEventListener("transitionend", function() {
box.style.width = 0;
})
}