作用和分类
作用: 就是使用 JS 去操作 html 和浏览器
分类:DOM (文档对象模型)、BOM(浏览器对象模型)
什么是DOM
lDOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API
白话文:DOM是浏览器提供的一套专门用来 操作网页内容 的功能
lDOM作用
开发网页内容特效和实现用户交互。
DOM树
- 将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
- 描述网页内容关系的名词
- 作用:文档树直观的体现了标签与标签之间的关系
节点
说明
DOM树里每一个内容都称之为节点
nodeType常用属性值
nodeType值 | 节点类型 |
---|---|
1 | 元素节点,例如 |
3 | 文本节点 |
8 | 注释节点 |
9 | document节点 |
10 | DTD节点 |
节点的关系
关系 | 考虑所有节点(包括文本节点) | 只考虑元素节点 |
---|---|---|
子节点 | childNodes | children |
父节点 | parentNode | parentNode |
第一个子节点 | firstChild | firstElementChild |
最后一个节点 | lastChild | lastElementChild |
前一个子节点 | previousSibling | previousElementSibling |
后一个子节点 | nextSibling | nextElementSibling |
节点类型
元素节点
- 所有的标签 比如 body、 div
- html 是根节点
属性节点
- 所有的属性 比如 href
文本节点
- 所有的文本
父节点查找
parentNode
属性- 返回最近一级的父节点
找不到返回为null
子元素.parentNode
- 案例
<div>
<p>去领红包</p>
<img src="./imgs/gd.png" alt="">
<span><img src="./imgs/1.png" alt=""></span>
</div>
<script>
let span = document.querySelector("span");
//点击span让他的父节点也就是div整个隐藏
span.addEventListener('click', function() {
span.parentNode.style.display = 'none'
})
子节点查找
childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
children (重点)
- 仅获得所有元素节点
- 返回的还是一个伪数组
父元素.children
//需求:点击哪个ul,哪个ul的所有li都隐藏
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
let uls = document.querySelectorAll("ul");
for (let i = 0; i < uls.length; i++) {
uls[i].addEventListener('click', function() {
for (let j = 0; j < this.children.length; j++) {
// 得到的子元素是伪数组,所以需要遍历才能得到每个元素
this.children[j].style.display = 'none'
}
})
}
</script>
兄弟节点查找
下一个兄弟节点
nextElementSibling
属性
上一个兄弟节点
previousElementSibling
属性
案例
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let lis = document.querySelectorAll("li");
// 循环遍历li标签
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
// 上一个兄弟节点变粉
this.previousElementSibling.style.backgroundColor='pink';
// 下一个兄弟节点变蓝
this.nextElementSibling.style.backgroundColor = 'skyblue';
})
}
</script>
增加节点
- 即创造出一个新的网页元素,再添加到网页内,
一般先创建节点,然后插入节点
<ul>
<li></li>
</ul>
<script>
let ul = document.querySelector("ul")
// 必须要声明获取li才能给他添加样式什么的
let li = document.createElement("li");
//给ul增加节点
ul.appendChild(li)
li.style.backgroundColor = 'pink'
li.innerText = '被插入的li'
</script>
先创建节点
- 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
- 创建元素节点方法:
document.createElement('标签名')
再追加节点
- 要想在界面看到,还得插入到某个父元素中
插入到父元素的最后一个子元素:
父元素.appendChild(要插入的元素)
插入到父元素中某个子元素的前面:
父元素.insertBefore(要插入的元素,在哪个元素前面)
<ul class="right">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
// insertBefore 也能插入元素 功能也类似 appendChild。
// 1 如果要插入的元素 是已经存在的,那么insertBefore作用 移动
// 2 如果要插入的元素 是新创建的 insertBefore作用 仅仅 插入
let leftLi = document.querySelector('.left li:nth-child(3)');
let two = document.querySelector('.right li:nth-child(2)');
let right = document.querySelector('.right');
// 在右边添加父元素就是右边的ul,在右边的第二个li也就是two前面添加
right.insertBefore(leftLi, two);
let li = document.createElement('li');
li.innerText = '新创建的';
right.insertBefore(li, two);
// 父元素.insertBefore(要插入的元素,哪个元素的上面);
</script>
克隆节点
复制一个原有的节点
- 把复制的节点放入到指定的元素内部
- cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
元素.cloneNode(布尔值)
- 若为true,则代表克隆时会包含后代节点一起克隆—深拷贝。
- 若为false,则代表克隆时不包含后代节点—浅拷贝。(默认false)
删除节点
- 若一个节点在页面中已不需要时,可以删除它
- 在 JavaScript 原生DOM操作中,要删除元素节点,元素节点不能主动删除自己,必须由父节点删除
必须通过父元素删除
- 语法
父元素.removeChild(要删除的元素)
- 如不存在父子关系则删除不成功
- 删除节点和隐藏节点(display:none 有区别的:
隐藏节点还是存在的,但是删除则从html中删除节点
DOM对象
- 浏览器根据html标签生成的 JS对象
- 所有的标签属性都可以在这个对象上面找到
- 修改这个对象的属性会自动映射到标签身上
lDOM的核心思想
把网页内容当做对象来处理
document 对象
- 是 DOM 里提供的一个对象
- 所以它提供的属性和方法都是用来访问和操作网页内容的
- 例:document.write()
- 网页所有内容都在document里面
获取dom元素
查找元素DOM元素就是选择页面中标签元素
根据CSS选择器来获取
选择匹配的第一个元素
语法:
document.querySelector('css选择器')
参数:
包含一个或多个有效的CSS选择器 字符串
返回值:
- CSS选择器匹配的
第一个元素
,一个 HTMLElement对象。 - 如果没有匹配到,则返回null。
- querySelector() 方法获取到的元素能直接操作修改
选择匹配的多个元素
语法:
document.querySelectAll('css选择器')
参数:
包含一个或多个有效的CSS选择器 字符串
返回值:
CSS选择器匹配的NodeList 对象集合
。
得到的是一个伪数组:
有长度有索引号的数组,但是没有 pop() push() 等数组方法。
哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已。
- 想要得到里面的每一个对象,则需要遍历(如 for)的方式获得。
其他获取方式
了解
document.getElementById('id名');
document.getElementByTagName('div');
document.getElementByClassName('选择器名')
设置/修改DOM元素内容
- DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象。
- 就是操作对象使用的点语法。
document.write() 方法
- 只能将文本内容追加到 前面的位置
- 文本中包含的标签会被解析
对象.innerText 属性
- 将文本内容添加/更新到任意标签位置
- 文本中包含的标签不会被解析
- 只能以纯文本的形式设置节点中的内容
对象.innerHTML 属性
- 将文本内容添加/更新到任意标签位置
- 文本中包含的标签会被解析
设置/修改元素常用属性
最常见的属性比如: href、title、src 等。
语法:
对象.属性 = 值
let pic = document.querySelector('img');
pic.src = './images/1.png';
pic.title = '标题';
通过 style 属性操作CSS
对象.style.样式属性 = 值
- 修改样式通过style属性引出
- 如果属性有-连接符,需要转换为小驼峰命名法
- 赋值的时候,需要的时候不要忘记加css单位
操作类名(className) 操作CSS
元素.className = '类名'
- 修改的样式多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式。
- className是使用新值换旧值, 如果需要添加一个类,需要保留之前的类名。
通过 classList 操作类控制CSS
//追加一个类
元素.classList.add('类名')
//删除一个类
元素.classList.remove('类名')
//切换一个类
元素.classList.toggle('类名')
为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
设置/修改 表单元素属性
获取: DOM对象.属性名
设置: DOM对象.属性名 = 新值
表单.value = '用户名'
表单.type = 'password'
//单选框
radio.checked = true //选中
//复选框
checkbox.checked = false //取消选中
- 表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框。
- 正常的有属性有取值的 跟其他的标签属性没有任何区别。
- 表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 如果为true 代表添加了该属性 如果是false 代表移除了该属性
比如:disabled、checked、selected - innerText innerHTML 主要是用来设置 双标签的文本内容的
input
```javascript 要被更改的文字
let userName = document.querySelector(“.userName”); // innerText innerHTML 主要是用来设置 双标签的文本内容的 userName.innerText = ‘不会有变化呀’ serName.value = ‘有变化了呀’
<a name="Button"></a>
##### Button
<a name="Select"></a>
##### Select
<a name="cb375de3"></a>
##### 文本域textarea
<a name="10b2761d"></a>
## 事件
<a name="3356c263"></a>
### 什么是事件
1. 事件是在编程时系统内发生的**动作**或者发生的事情
1. 比如用户在网页上**单击**一个按钮
<a name="ba62f7ef"></a>
### **事件监听**
1. 让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
```javascript
元素.addEvenListerener('事件',要执行的函数)
事件取消绑定
- removeEventListener 可以取消对应的事件类型和事件处理函数
- 无法取消addEventListener 事件对应的匿名函数
- 元素.addEventListener(‘事件’,处理函数名称)
<button>按钮</button>
<script>
let btn = document.querySelector("button");
// 匿名函数 无法取消绑定
btn.addEventListener('click', function() {
console.log('hh');
})
function fun1() {
console.log('fun1');
}
// 绑定事件
btn.addEventListener('click', fun1);
// 取消绑定
btn.removeEventListener('click', fun1)
</script>
事件监听三要素:
- 事件源: 那个dom元素被事件触发了,要获取dom元素
- 事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
- 事件调用的函数: 要做什么事
事件类型
鼠标事件
鼠标触发
- click 鼠标点击
- mouseenter 鼠标经过
- mouseleave 鼠标离开
焦点事件
表单获得光标
- focus 获得焦点
- blur 失去焦点
键盘事件
- Keydown 键盘按下触发
- Keyup 键盘抬起触发
文本事件
- 表单输入触发
- input 用户输入事件
事件对象
描述
- 也是个对象,这个对象里有
事件触发时的相关信息
- 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
获取
- 在
事件绑定的回调函数的第一个参数
就是事件对象 - 一般命名为event、ev、e
部分常用属性
type
- 获取当前的事件类型
获取鼠标位置
属性 | |
---|---|
clientX | 获取光标相对于浏览器 的水平位置 |
clientY | 获取光标相对于浏览器 的垂直位置 |
offsetX | 获取光标相对于整张网页 的水平位置 |
offsetY | 获取光标相对于整张网页 的垂直位置 |
pageX | 获取光标相对于当前DOM元素 的水平位置 |
pageY | 获取光标相对于当前DOM元素 的垂直位置 |
案例
// 图片跟着鼠标移动
```javascript
//练习-右键菜单
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
}
.menu {
/* 固定定位 */
position: fixed;
width: 150px;
height: 200px;
background-color: rgb(255, 255, 255);
text-align: center;
display: none;
}
li {
list-style: none;
border: 1px solid #ccc;
padding: 10px;
}
li:hover {
background-color: skyblue;
}
</style>
</head>
<body>
<ul class="menu">
<li>选择1</li>
<li>选择2</li>
<li>选择3</li>
<li>选择4</li>
</ul>
<script>
const menu = document.querySelector(".menu");
document.body.addEventListener('contextmenu', function(event) {
event.preventDefault();
const left = event.clientX;
const top = event.clientY;
menu.style.display = "block"
menu.style.left = left + 'px'
menu.style.top = top + 'px'
});
document.body.addEventListener("click", function() {
menu.style.display = 'none'
})
</script>
键盘 key
- 用户按下的键盘键的值
- 现在不提倡使用keyCode
//微博发布案例
// 文本域
let textarea = document.querySelector("textarea");
// 获取发布按钮
let btn = document.querySelector("button");
// 放置发布内容的div
let content = document.querySelector(".content")
// 点击发布将文本域内容插入到div中
btn.addEventListener('click', function() {
content.innerHTML = `${textarea.value}`
if ((textarea.value.trim()) == '') {
console.log('不输出');
return
}
})
// 当键盘按下将文本域内容插入到div中
textarea.addEventListener('keydown', function(event) {
if (event.key == "Enter") {
btn.click()
}
})
</script>
元素位置-三大家族
client家族
获取宽高
- clientWidth 获取可视区域的宽度(不包含滚动条)
- clientHeight 获取可视区域的宽度(不包含滚动条)
获取位置
- clientLeft
获取左边框的大小(只读属性)
- clientTop
获取上边框的大小(只读属性)
- resize 会在窗口尺寸改变的时候触发事件 resize window来绑定
window.addEvenlistener('resize',function(){
//执行的代码
})
const clientDom = document.querySelector('.client');
// 宽度和高度
console.log(clientDom.clientWidth); // 不包含 滚动条(类似 scrollWidth)
console.log(clientDom.clientHeight); // 不包含 滚动条(类似 scrollHeight)
// 获取边框的大小
console.log(clientDom.clientLeft); // 左边框
console.log(clientDom.clientRight);// 不能获取,没有clientRight
console.log(clientDom.clientTop); // 上边框
offset家族
获取元素距离自己**定位父级**元素的左、上距离
- offsetLeft和offsetTop,是
只读属性
- 获取元素的自身宽高、
包含元素自身设置的宽高、padding、border
- offsetWidth/offsetHeight获取容器宽度和高度,
包含滚动条的大小
- offsetWidth
- offsetHeight
- offsetTop/offsetLeft 获取当前元素距离,定位了的父元素的大小(找不到定位了的父元素,相对于页面来计算)
- offsetLeft 获取定位了的父元素的 水平距离 左
- offsetTop 获取定位了的父元素的 垂直距离 上
//某个元素的
let box1 = document.querySelector(".box1");
console.log(box1.offsetWidth);//获取可视区域宽度,不包含滚动条
console.log(box1.offsetHeight);
console.log(box1.offsetLeft);//获取已经定位了的父级元素的左距离
console.log(box1.offsetTop);
scroll家族
- scrollTop
- scrollLeft
- scrollWidth
- scrollHeight
页面滚动
- 监听整个页面滚动:
window.addEventListener("scroll", function() {
console.log(`页面滚动距离顶部${document.documentElement.scrollTop`};
console.log(`页面滚动距离左边${document.documentElement.scrollLeft`};
})
获取元素滚动距离
获取元素内容往左、往上滚出去看不到的距离
- dom.scrollTop
属性可修改
- dom.scrollLeft
属性可修改
// 获取元素滚动的距离
let div = document.querySelector("div");
div.addEventListener("scroll", function() {
console.log(`距离顶端的距离是${div.scrollTop}`);
console.log(`距离左边的距离是${div.scrollLeft}`);
})
获取高度和宽度
- 获取元素的内容总宽高
(包含padding,不包括margin、border)(不包含滚动条)
返回值不带单位
- 整个可以滚动的区域的高度 scrollHeight (包含滚动的区域)
- 整个可以滚动的区域的宽度 scrollWidth (包含滚动的区域)
let box = document.querySelector(".box");
box.addEventListener("scroll", function() {
console.log(box.scrollHeight); //获得滚动高度(包含padding,不包括margin、border)(不包含滚动条)
console.log(box.scrollWidth); //获得滚动宽度(不包含滚动条)
})
滚动条大小
- pc端滚动条大小占17px
- 移动端滚动条不占大小
案例
//滚动一定高度,nav固定定位在顶部
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
header {
height: 250px;
background-color: yellow;
}
nav {
background-color: orange;
height: 150px;
}
.fixed {
position: fixed;
left: 0;
top: 0;
width: 100%;
}
div {
/* height: 150vh; */
background-color: aqua;
}
</style>
</head>
<body>
<header></header>
<nav></nav>
<div>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>10</h1>
<h1>11</h1>
<h1>12</h1>
。。。。
</div>
<script>
// 需求: 当页面滚动到一定的高度 nav变成了固定定位
// 1 一定高度 其实就是header标签的高 250px
// 步骤:
// 1 需要在页面滚动距离 大于或者等于 250 的高时候
// 1 设置nav标签做一个 固定定位
// 2 否则就取消固定定位
// 3 小bug 因为 nav标签做固定定位,不再拥有高度,自然把下面的标签给挡住!!!
// 解决它
// 给nav上面的标签 header标签 添加下外边距,大小 等于 nav的高
const nav = document.querySelector('nav');
const header = document.querySelector('header');
window.addEventListener('scroll', function() {
// 获取页面滚动的高度
const scrollTop = document.documentElement.scrollTop;
// 判断页面滚动高度
if (scrollTop >= 250) {
nav.classList.add('fixed');
header.style.marginBottom = 150 + 'px';
} else {
nav.classList.remove('fixed');
header.style.marginBottom = 0;
}
});
</script>
//点击图片回到最顶部
<style>
body {
height: 200vw;
background-image: linear-gradient(black, skyblue, pink);
}
a {
position: fixed;
right: 0;
bottom: 50px;
width: 100px;
height: 100px;
background-color: #fff;
/* display: none; */
cursor: pointer;
background-image: url(http://md.zbztb.cn/uploads/454095101142/gotop.png);
background-size: 100%;
}
a:hover {
background-image: url(http://md.zbztb.cn/uploads/454095101142/gotop.gif);
}
</style>
</head>
<body>
<a href="javascript:;"></a>
<script>
let a = document.querySelector("a")
window.addEventListener('scroll', function() {
// 获取页面滚动的高度
const scrollTop = document.documentElement.scrollTop;
// 判断页面滚动高度
if (scrollTop >= 800) {
a.style.display = "block"
} else {
a.style.display = "none"
}
});
a.addEventListener('click', function() {
let timeId = setInterval(function() {
document.documentElement.scrollTop -= 10
// 如果滚动高度等于0则关闭定时器
if (document.documentElement.scrollTop == 0) {
clearInterval(timeId)
}
}, 10)
})
</script>
事件流
描述
事件流指的是事件完整执行过程中的流动路径
例:
- 假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
- 简单来说:
- 捕获阶段是 从父到子。
- 冒泡阶段是 从子到父
阻止默认冒泡
- 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素。
- 若想把事件就限制在当前元素内,就需要阻止事件流动。
- 阻止事件流动需要拿到事件对象。
事件对象.stopPropagation()
- 事件对象.preventDefault(),可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。
阻止默认行为
event.preventDefault()
例子
- a标签的点击跳转
- return false也可以实现超链接阻止默认行为的效果,`但是return false后面的代码将不被执行。阻止默认行为 - form表单 有一个 submit 事件 不放置type=submit的按钮,回车不会提交表单。
推荐使用 event.preventDefault()
- 阻止form表单 button默认行为
- 给button按钮 添加一个 type = “button”。
- 换成 input标签 type = “button”。
- 把button 移出form表单的区域。
a.addEventListener("click", function(event) {
console.log("a标签的点击触发啦");
// 阻止a标签的默认行为,让他不要跳转
event.preventDefault();
})
form.addEventListener("submit", function(event) {
// 不要让页面再刷新
event.preventDefault();
})
鼠标经过事件
- mouseenter 和 mouseleave 没有冒泡效果(推荐)
- mouseover 和 mouseout 会有冒泡效果
注册事件的区别
传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
事件监听注册(L2)
- 语法:
addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
事件委托
- 优点:给父级元素加事件(可以提高性能)
- 原理:事件委托其实是
利用事件冒泡的特点
, 给父元素添加事件,子元素可以触发 - 实现:
事件对象.target
可以获得真正触发事件的元素 - 案例
<ul>
<li>1
<span>span</span>
</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
let ul = document.querySelector("ul");
// event.target 有可能是ul标签, 有可能是li标签, 还有可能是 a标签
ul.addEventListener('click', function(event) {
// event.target 当前点击的是哪个标签(点击最深最底层的那个标签即可)
event.target.style.backgroundColor = 'skyblue';
// 获取到被点击的标签
console.log(event.target);
})
</script>
Window对象
BOM(浏览器对象模型)
- window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
- window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
- document 是实现 DOM 的基础,它其实是依附于 window 的属性。
- 注:依附于 window 对象的所有属性和方法,使用时可以省略 window
定时器
- setInterval()函数可以重复调用一个函数,在每次调用之间具有固定的时间间隔
- 定时器返回的是一个id数字
开启定时器
setInterval(函数名字,间隔时间) //函数名字不需要加括号
setInterval(function() {
console.log('hhh');
}, 1000)
每隔一段时间调用这个函数,间隔时间是毫秒。
关闭定时器
let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
延时器
- setTimeout()函数可以设置一个延时器,当指定时间到了 之后,会执行函数一次,不再重复执行。
- 平时省略window
开启延时器
setTimeout(函数名字,间隔时间) //函数名字不需要加括号
setTimeout(function() {
console.log('hhh');
}, 1000)
用延时器实现定时器的效果
// 延时器不主动清除,定时器可以一直执行
// 延时器只会执行一次
// 延时器实现定时器功能
// 在延时器又开启延时器,延时器又再开启延时器,延时器又再开启延时器
let num = 0
// 递归自己调用自己
function fun() {
console.log(++num);
setTimeout(fun, 1000)
};
fun();
清除定时器
clearTimeout()函数
Js执行机制
location对象
- location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
- 常用属性和方法:
- href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
- search 属性获取地址中携带的参数,符号 ?后面部分
- hash 属性获取地址中的啥希值,符号 # 后面部分
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
<button>跳转</button>
<script>
//http://127.0.0.1:5500/7location.html
let btn = document.querySelector("button");
btn.addEventListener('click', function() {
console.log(location.href); //目的:点击刷新 解决:让location.href等于当前页面location.href=location.href
// location.href = 'http://127.0.0.1:5500/7-location.html'
console.log(location.hash); //获取hash值 #号后面的字符
// http://127.0.0.1:5500/7-location.html#/indes 输出 #/indes
console.log(location.search); //获取问好后面字符 输出 a=2&b=23
//http://127.0.0.1:5500/7-location.html?a=2&b=23
})
</script>
为后期vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如 网易云音乐
navigator对象
- navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
常用属性和方法:
通过 userAgent 检测浏览器的版本及平台。
// 检测 userAgent(浏览器信息)
!(function () {
const userAgent = navigator.userAgent
// 验证是否为Android或iPhone
const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
// 如果是Android或iPhone,则跳转至移动站点
if (android || iphone) {
location.href = 'http://m.itcast.cn'
}
})()
histroy对象
- history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
- 常用属性和方法:
| history对象方法 | 作用 | | —- | —- | | back() | 可以后退功能 | | forward() | 可以前进功能 | | go(参数) | 前进后退功能都可以,例如参数是 1代表前进一个页面,-1代表后退一个页面 |
<a href="https://www.baidu.com/">百度</a>
<button class="btn1">前进</button>
<button class="btn2">后退</button>
<script>
let btn1 = document.querySelector(".btn1")
let btn2 = document.querySelector(".btn2")
btn1.addEventListener('click', function() {
history.forward()
history.go(1)
})
btn1.addEventListener('click', function() {
history.back()
history.go(-1)
})
本地储存
数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage和localStorage约 5M 左右
localStorage
生命周期永久生效
,除非手动删除,否则关闭页面也会存在- 可以
多窗口(页面)共享(同一浏览器可以共享)
- 以
键值对的形式存储
使用
存储数据
localStorage.setItem(key, value)
获取数据
localStorage.getItem(key)
删除数据
localStorage.removeItem(key)
//存 localStorage.setItem(key,value);
//取 localStorage.getItem(key);
//删除一个 localStorage.removeItem(key);
//清空 localStorage.clear();
// 生成一百个本地存储数据
for (let i = 0; i < 100; i++) {
localStorage.setItem(`abc${i}`, i)
}
// 清空所有本地存储
// localStorage.clear();
存储复杂数据类型存储
本地只能存储字符串
,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串再存储到本地- 本地存储存储复杂类型、引用类型的数据 ,会出现数据丢失的问题
JSON.stringify(复杂数据类型)
- 将复杂数据转换成JSON字符串 ,存储 本地存储中
JSON.parse(JSON字符串)
- 将JSON字符串转换成对象 , 取出 时候使用
// console.log( localStorage.getItem("sdfdfdd") );// 如果没有数据的时候 本地存储会返回什么?
// let str= localStorage.getItem("sdfdfdd");// null
// JSON.parse(null)// 不正确了呀
// 判断有没有数据 如果没有数据 返回一个空数组
// 有数据 将字符串 解析成数组 再返回
对象 数组
// localStorage.setItem('test', 123);
// const test = localStorage.getItem('test');
// console.log( typeof test ); // string
// const obj = { name: '路飞' };
// localStorage.setItem('obj', obj); // 存了一个对象数据进去 写法不对了
// const newObj = localStorage.getItem('obj');
// console.log(newObj);
// 数组和对象 适合管理 比较复杂的数据
// const obj = `{ name: '路飞', height: 100, weight: 200 }`;
// // 丧失 对象 简洁用法的意义
// console.log(obj.name );
// console.log(obj.height );
// console.log(obj.weight );
// 把对象格式转成 字符串格式,继续使用 本地存储
// localStorage.setItem("obj",obj);// obj 是一个长得像 对象的 字符串
// 在行业中我们会这么做
// // 1. 还是正常定义对象
// const obj = {
// name: '路飞',
// height: 100,
// weight: 200,
// };
// 2. 把一个对象转成字符串
// const objStr = JSON.stringify(obj);
// 3. 本地存储 可以存储字符串类型的数据
// localStorage.setItem("obj",objStr);
// 4. 把本地存储的数据重新读取出来
// const newObjStr = localStorage.getItem("obj");
// // console.log(newObjStr);
// 5. 重新把这个字符串解析成原来的对象
// const newObj = JSON.parse(newObjStr);
// console.log(newObj);
/*
1 本地存储无法存放 复杂类型的数据
2 复杂类型的数据 通过JSON对象 字符串 相互之间的转换
*/
sessionStorage
1、生命周期为关闭浏览器窗口
2、在同一个窗口(页面)下数据可以共享
3.以键值对的形式存储使用
4.用法跟localStorage 基本相同
5.会话(打开页面到关闭页面的一次会话 ,在ajax、node)存储
6.登陆的时候可能会用
// 存
sessionStorage.setItem('name', 123);
// 取
sessionStorage.getItem('name');
// 删除一个
sessionStorage.removeItem('name');
// 清空
sessionStorage.clear();
自定义属性
固有属性
- 标签天生自带的属性 比如class id title等, 可以
直接使用点语法
操作
自定义属性
- 由程序员自己添加的属性,在DOM对象中找不到,
无法使用点语法操作,必须使用专门的API
- 获取自定义属性
getAttribute('属性名')
getAttribute(key)
- 设置自定义属性
setAttribute('属性名', '属性值')
setAttribute(key,value)
- 删除自定义属性
removeAttribute('属性名')
removeAttribute(key)
data-自定义属性
- 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在标签上一律以data-开头
- 在DOM对象上一律以dataset对象方式获取
// 自定义属性 -> h5建议的自定义属性
// 属性的时候 data-xxx 开头
// 获取的时候 a.dataset.xxx
// 设置 a.dataset.index = 3;
<a data-index="0" id="nav" href="http://www.baidu.com" hello="no" aa="bb" >跳转</a >
console.log( a.getAttribute("data-index") );
console.log( a.getAttribute("id") );
console.log( a.getAttribute("href") );
console.log( a.getAttribute("hello") );
console.log( a.getAttribute("aa") );
自定义属性案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>13-自定义属性使用演示.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<ul></ul>
<script>
// 根据数组 渲染出li标签 点击li标签的时候 根据它对应的颜色 设置到 我body标签背景中
// 数组
let arr = [{
price: '100',
title: '去旅游',
color: 'yellow'
}, {
price: '200',
title: '去读书',
color: 'red'
}, {
price: '300',
title: '去吃饭',
color: 'blue'
}, ];
const ul = document.querySelector('ul');
let html = ``;
for (let index = 0; index < arr.length; index++) {
html += `<li data-price="${arr[index].price}" data-color="${arr[index].color}" >${arr[index].title}</li>`;
}
ul.innerHTML = html;
// 事件委托
ul.addEventListener('click', function(event) {
// 当前点击的是li标签
if (event.target.nodeName === 'LI') {
// 设置body标签的背景颜色 等于什么 = 等于当前被点击的元素(li) 身上的自定义属性 data-color
// document.body.style.backgroundColor = event.target.dataset.color;
document.body.style.backgroundColor =
event.target.getAttribute('data-color');
// alert(
// // `你想要去做的事情,要花这么多钱哦 ${event.target.dataset.price}`
// );
}
});
</script>
</body>
</html>
属性补充知识点
- setAttribute removeAttribute 可以获取到任意的属性(固有属性和h5建议的自定义属性)
字符串
转大写 toUpperCase()
转小写 toLowerCase()
排他思想
案例
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
//获取所有li标签
let lis = document.querySelectorAll("li");
//遍历所有li
for (let i = 0; i < lis.length; i++) {
//哪个li点击就让让所有的li恢复基础样式,再单独给自己设置样式
lis[i].addEventListener('click', function() {
for (let j = 0; j < lis.length; j++) {
lis[j].style.backgroundColor = '#fff'
}
//单独给自己设置样式
this.style.backgroundColor = 'red'
})
}
</script>
案例
点名(定时器)
<h1></h1>
<button class="btn1">start</button>
<button class="btn2">end</button>
<script>
let h1 = document.querySelector("h1");
let btn1 = document.querySelector(".btn1")
let btn2 = document.querySelector(".btn2")
let arr = [11, 22, 43, 54, 56, 7, 77];
let timeId;
function intervalDo() {
let i = Math.round(Math.random() * (arr.length - 1));
h1.innerText = arr[i];
// 不给return,就返回return undefined
}
btn1.addEventListener('click', function() {
if (timeId !== undefined) {
clearInterval(timeId)
}
// 开启定时器
timeId = setInterval(intervalDo, 100)
})
// 清除定时器
btn2.addEventListener('click', function() {
clearInterval(timeId)
})
删除广告
<div>
<p>去领红包</p>
<img src="./images/gd.png" alt="">
<span>×</span>
</div>
<script>
let div = document.querySelector("div");
let span = document.querySelector("span");
span.addEventListener('click', function() {
div.style.display = 'none'
})
</script>
全选反选
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll" />
<span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
<script>
// checked值为true代表选中状态
let checkAll = document.querySelector("#checkAll");
let checkboxList = document.querySelectorAll(".ck");
// 监听事件,绑定点击,注册点击,订阅点击
console.log(checkAll.checked)
// 当全选框点击,循环遍历复选框
checkAll.addEventListener("click", function() {
for (let i = 0; i < checkboxList.length; i++) {
// 设置每个复选框的值为全选框的选中状态
checkboxList[i].checked = checkAll.checked;
}
});
for (let i = 0; i < checkboxList.length; i++) {
checkboxList[i].addEventListener('click', function() {
// 全选按钮 Allchecked
// 函数isAllchecked()判断是否达到了全选条件,赋值给全选按钮
let Allchecked = isAllchecked();
// 设置页面全选框的值为 Allchecked,如果Allchecked值为true自然为全选
checkAll.checked = Allchecked
});
}
// 函数判断
function isAllchecked() {
// 存放选中复选框状态的数量
let checkedNum = 0;
// 循环复选框
for (let i = 0; i < checkboxList.length; i++) {
// 判断复选框的选中状态
if (checkboxList[i].checked) {
// 选中就+1
checkedNum++
}
}
// 循环结束, 判断选中的复选框的数量和所有复选框的总长度
// 如果全等,则表示全部选中,返回true
if (checkedNum === checkboxList.length) {
return true
} else {
return false
}
}
</script>