dataset 对象
- 预定义属性:
id,class,style, title...
- 自定义属性:
data-
前缀 - 注:
data-
不要写,蛇形->驼峰
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>dataset: 自定义属性</title>
</head>
<body>
<!--
属性
1. 内置属性: id, class, style,...
2. 自定义属性: data-前缀
data-uname, data-my-email
-->
<div
id="user_id"
class="user_class"
style="color: red"
data-uname="朱老师"
data-my-email="zhu@qq.com"
>
用户信息
</div>
<script>
const div = document.querySelector("div");
// 1. 访问内置属性: obj.prop
console.log(div.id);
// class是关键字, className -> class
console.log(div.className);
// 返回CSSStyleDeclaration对象
console.log(div.style);
console.log(div.style.color);
// ====================================
// 2. 自定义属性: dataset.prop
// data-uname="朱老师"
// data-: 省略
console.log(div.dataset["uname"]);
// 合法属性可以直接用点语法访问
console.log(div.dataset.uname);
// data-my-email="zhu@qq.com"
// 蛇形 -> 小驼峰, user_name -> userName
console.log(div.dataset["my-email"]);
console.log(div.dataset["myEmail"]);
console.log(div.dataset.myEmail);
</script>
</body>
</html>
getComputedStyle对象
- 计算样式: 元素上的全样样式,包括行内,文档,外部等
- 只读
style1.css代码:
h2 {
background-color: yellow;
}
完整示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>getComputedStyle: 计算样式</title>
<link rel="stylesheet" href="style1.css" />
<!-- 文档样式 -->
<style>
h2 {
border: 1px solid #000;
width: 200px;
height: 50px;
}
</style>
</head>
<body>
<!-- 行内样式 -->
<h2 style="color: red">Hello world</h2>
<script>
const h2 = document.querySelector("h2");
// 行内样式style=""
console.log(h2.style.color);
// 文档样式<style>
console.log(h2.style.width);
console.log(h2.style.height);
console.log(h2.style.backgroundColor);
// 一个元素最终样式,由行内,文档,外部css共同作用的结果
// 全局函数, 计算属性,可以获取元素上的任何css属性
// console.log(window.getComputedStyle(h2));
console.log(window.getComputedStyle(h2).width);
console.log(window.getComputedStyle(h2).height);
console.log(typeof window.getComputedStyle(h2).height);
console.log(window.getComputedStyle(h2).backgroundColor);
// 宽度
let width = window.getComputedStyle(h2).width;
console.log(typeof width);
// 转换为整数
console.log(typeof parseInt(width), parseInt(width));
// 根据 任何数乘以1 都不变,但是一个数字字符串乘以1, 会发生类型的自动转换
console.log(typeof ("123" * 1), "123" * 1);
width = parseInt(width);
h2.style.width = "300px";
h2.style.width = width + 100 + "px";
</script>
</body>
</html>
classList
这是专用于操作元素的class
属性
- 添加:
classList.add()
- 判断:
classList.contains()
- 替换:
classList.replace()
- 移除:
classList.remove()
- 切换:
classList.toggle()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>classList: class属性</title>
<style>
.red {
color: red;
}
.blue {
color: blue;
}
.bgc {
background-color: yellow;
}
</style>
</head>
<body>
<h2 class="red">Hello world</h2>
<script>
const h2 = document.querySelector("h2");
// 1. 传统: className
// 添加 <h2 class="red">...</h2>
h2.className = "red";
h2.className = "red bgc";
// 删除
h2.className = "";
// =================================
// 2. classList
// 添加
h2.classList.add("red");
h2.classList.add("bgc");
h2.classList.add("red", "bgc");
/// 替换
h2.classList.replace("red", "blue");
// 删除
h2.classList.remove("bgc", "blue");
// 切换: 自动在 add() , remove() 之间自动切换
h2.classList.toggle("red");
</script>
</body>
</html>
事件基础
- 事件 3 要素
- 事件名称: 字符串,
click, keydown, scroll
- 事件主体: 元素,
<button>,<div>,<form>...
- 事件方法: 函数,
function(ev){}, ()=>{}
- 事件增删
- 事件添加: 事件属性,
addEventListener()
- 事件删除:
null
,removeEventListener()
- 事件派发:
dispatchEvent()
- 定时器
- 一次性:
setTimeout()
- 间歇式:
setInterval()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件添加与派发</title>
</head>
<body>
<!-- 1. 标签属性: 事件属性 tag.on+事件名称 -->
<button onclick="alert('登陆成功')">登录</button>
<!-- =================================== -->
<!-- 2. html对象属性: obj.onclick -->
<button class="save">保存</button>
<script>
let saveBtn = document.querySelector(".save");
saveBtn.onclick = function () {
alert("保存成功");
};
saveBtn.onclick = function () {
alert("保存失败");
};
// 删除
saveBtn.onclick = null;
// onclick: 不能重复添加同名事件
</script>
<!-- =================================== -->
<!-- 3. 事件监听器: obj.addEventListener() -->
<button class="submit">提交</button>
<script>
let submitBtn = document.querySelector(".submit");
// submitBtn.addEventListener(事件名称,事件方法,是否冒泡false)
submitBtn.addEventListener("click", function () {
alert("提交成功");
});
// 简写
submitBtn.addEventListener("click", () => alert("提交成功"));
submitBtn.addEventListener("click", function () {
alert("提交失败");
});
// submitBtn.removeEventListener('click', 不能用匿名函数)
// addEventListener():注册的同名事件方法会依次触发
</script>
<!-- =================================== -->
<!-- 4. (自定义)事件派发 -->
<button class="ads">广告位</button>
<script>
const adsBtn = document.querySelector(".ads");
let money = 0;
// 点击一次赚10元
adsBtn.addEventListener("click", function () {
console.log((money += 10) + " 元");
});
// 定时器: 自动累加赚钱
/**
* 定时器
* 1. 一次性: setTimeout(function(){}, time)
* 2. 间歇式: setInterval(function(){}, time)
*/
setTimeout(function () {
console.log("大家晚上好");
}, 2000);
setInterval(function () {
console.log("大家晚上好");
}, 2000);
setInterval(function () {
console.log((money += 10) + " 元");
}, 1000);
// 创建一个机器人, 帮我去点击
// 机器人 -> 自定义事件去模拟它
const myClick = new Event("click");
setInterval(function () {
adsBtn.dispatchEvent(myClick);
}, 1000);
// 赚够250元, 就停止
let timer = setInterval(function () {
adsBtn.dispatchEvent(myClick);
// 如果money >= 250 ,就不要点击
if (money >= 250) {
// 清除定时器
// 如果是setTimeout(),用 clearTimeout()来清除
// 如果是setInterval(), 用clearInterval()
clearInterval(timer);
console.warn(`今天已经赚了${money}元,明天再来吧`);
}
}, 1000);
</script>
</body>
</html>
事件冒泡
- 事件由内向外,逐级向上传递,直到根元素
- 事件冒泡可以被禁用:
ev.stopPropagation()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件冒泡</title>
<style>
.box {
border: 1px solid;
padding: 15px;
}
</style>
</head>
<body>
<div class="box box1">
box1
<div class="box box2">
box2
<div class="box box3">box3</div>
</div>
</div>
<script>
const boxes = document.querySelectorAll(".box");
// 为每个div添加一个点击事件
boxes.forEach(function (box) {
box.addEventListener(
"click",
function () {
console.log(this.className.replace("box", ""));
// 取消冒泡
// 事件对象 event, 总是可用
console.log(event.stopPropagation());
},
false
);
});
/**
* 冒泡前提
* 1. 元素之间存在层次关系
* 2. 祖先元素也定义与之同名的事件
*/
/**
* addEventListener(event,callback,是否冒泡false)
* 1. false: 默认值,冒泡(从内向外)
* 2. true: 捕获 ( 从外向内 )
*/
</script>
</body>
</html>
事件代理
- 利用事件冒泡,将子元素事件委托到父级上触发
- 事件代理机制,可以极大的简化事件添加操作
- 事件绑定主体
ev.currentTarge
- 事件触发主体:
ev.target
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件冒泡: 事件代理/委托</title>
</head>
<body>
<ul class="list1">
<li class="item">电脑</li>
<li class="item">手机</li>
<li class="item">外套</li>
</ul>
<hr />
<ul class="list2">
<li class="item">西瓜</li>
<li class="item">苹果</li>
<li class="item">草莓</li>
</ul>
<script>
// 任务: 点击任何一个<li>,显示内容
// 1. 传统
const items = document.querySelectorAll(".list1 > .item");
items.forEach((item) => {
item.onclick = function (ev) {
// ev: 事件对象
console.log(ev);
// 事件绑定者: ev.currentTarget
console.log(ev.currentTarget);
// 事件触发者: ev.target
console.log(ev.target);
// this
console.log(this);
console.log(this === ev.target);
console.log(ev.currentTarget === ev.target);
// 因为三者完全相同所以用哪个都可以获取内容
console.log(ev.currentTarget.textContent);
};
});
// ====================================
// 事件冒泡: 子元素上的同名事件,会自动冒泡到父元素上面去触发
// 2. 事件代理
const list = document.querySelector(".list2");
list.onclick = function (ev) {
// 事件绑定者: ev.currentTarget, 父元素
console.log(ev.currentTarget);
// 事件触发者: ev.target, 子元素
console.log(ev.target);
// this
console.log(this);
console.log(this === ev.currentTarget);
console.log(this === ev.target);
// 需要用时间触发者来获取元素文本
console.log(ev.target.textContent);
};
</script>
</body>
</html>
实战计算器
index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>计算器</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- 事件代理, eval() -->
<div class="calculator">
<!-- 结果区 -->
<input type="text" class="result" value="0" readonly />
<!-- 按键区 -->
<div class="btns" onclick="calculator(event)">
<button>F1</button>
<button>F2</button>
<button>CE</button>
<button>AC</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>/</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>X</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>-</button>
<button>0</button>
<button>.</button>
<button>=</button>
<button>+</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
style.css:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #eee;
}
.calculator {
min-width: 360px;
max-width: 460px;
border-radius: 8px;
background-color: #666;
padding: 15px;
display: grid;
grid-template-rows: 60px 1fr;
gap: 20px;
margin: 40px auto;
}
.calculator .result {
font-size: 32px;
font-weight: bolder;
text-align: right;
padding: 6px;
border: none;
outline: none;
border-radius: 8px;
background-color: #cecece;
box-shadow: 2px 2px 2px #333 inset;
}
.calculator .btns {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 50px;
gap: 15px;
}
.calculator .btns > * {
font-size: 32px;
font-weight: bolder;
border-radius: 8px;
color: #888;
border: none;
outline: none;
background-color: #444;
box-shadow: 2px 2px 2px #000;
}
.calculator .btns *:nth-child(-n + 4) {
background-color: #222;
}
.calculator .btns *:nth-child(-n + 4):hover,
.calculator .btns > *:hover {
cursor: pointer;
opacity: 0.7;
color: white;
transition: 0.3s;
}
script.js:
// 计算函数
function calculator(ev) {
// 显示结果区
const result = document.querySelector('.result')
// 当前按钮(事件代理)
if (ev.target.tagName !== 'BUTTON') return false
// 当前按钮
const curBtn = ev.target
// 按钮内容
let content = curBtn.textContent
// eval('字符串表达式'): 将一个字符串表达式进行计算并返回结果
// 将内容显示到结果区
// 根据用户点击的按钮内容确定要执行的操作
switch (content) {
// AC 清零
case 'AC':
result.value = 0
break
// CE: 退格
case 'CE':
// 如果结果区有内容
if (result.value.length == 1 || result.value == '错误') {
result.value = 0
} else {
// 删除最后一个字符
// slice(startIndex,endIndex),结果中不包含结束索引的值
result.value = result.value.slice(0, -1)
}
break
// F1
case 'F1':
break
// F2
case 'F2':
break
// = : 计算结果
case '=':
// 缓存结果
let tmpResult = 0
try {
// 如果是乘法,将 "X" 换成 "*"
result.value = result.value.replace('X', '*')
// 计算字符串表达式
tmpResult = eval(result.value)
// 如果结果是小数,仅保留5位就可以了
if (tmpResult.toString().includes('.')) {
tmpResult = tmpResult.toFixed(5)
// 如果小数部分出现了多余的0,应该去掉(对结果精度没影响)
tmpResult = parseFloat(tmpResult)
}
// 显示出结果
result.value = tmpResult
} catch {
result.value = '错误'
}
break
default:
// 如果当前结果区显示有前导0,先清空, 防止出现前导0
if (result.value == 0 || result.value == '错误') result.value = ''
result.value += content
}
}
/**
* 知识点总结
* 1. 事件代理
* 2. eval()
* 3. try-catch
* 4. toFixed()
*/
/**
* 作业
* 1. 处理除零错误
* 2. 处理操作符位于表达式首位的错误
*/
完整代码附件:
calculator.zip大小:3KB
已经过安全软件检测无毒,请您放心下载。
本文地址:https://www.mainblog.cn/330.html
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。