1 JavaScript课程中提到的案例分析
eg.间隔li奇偶标签行颜色不同案例
1 普通隔行变换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Interlaced_discoloration 隔行变色</title>
</head>
<body>
<div class="inter-color">
<ul class="til">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
</body>
</html>
* {
margin: 10;
padding: 0;
}
li {
list-style: none;
}
.til li {
width: 200px;
height: 20px;
/* border: 1px solid; */
}
function getTag(n) {
return document.getElementsByTagName(n)
}
var url = getTag('li')
for (var i = 0; i < url.length; i++) {
if (i % 2 == 0) {
url[i].style.background = 'lightgray'
} else {
url[i].style.background = 'lightgreen'
}
}
思路:用css写一个li列表,通过在函数里return出来一个document.getElementsByTagName方法,执行这个函数,传参获取所有的li,是一个类数组,然后用for循环循环出所有li,当循环到第几个li标签的时候,对该li标签的索引'i%2 == 0'判断为偶数则颜色为'orange',否则颜色为'lightgreen'
2 鼠标滑过变色
<div class="inter-color">
<ul class="til">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
* {
margin: 10;
padding: 0;
}
li {
list-style: none;
}
.til li {
width: 200px;
height: 20px;
/* border: 1px solid; */
}
function getTag(n) {
return document.getElementsByTagName(n)
}
var url = getTag('li')
for (var i = 0; i < url.length; i++) {
if (i % 2 == 0) {
url[i].style.background = 'lightgray'
} else {
url[i].style.background = 'azure'
}
}
// this的思想:把初始色值存储到了每一个li的自定义属性上,当划出li标签时,再用li标签上自定义的值,赋给li的背景色
for (var i = 0; i < url.length; i++) {
url[i].myli = url[i].style.background
url[i].onmouseover = function () {
this.style.background = 'orange'
}
url[i].onmouseout = function () {
this.style.background = this.myli
}
}
思路:在隔行变色的基础上加上一个for循环,在该for循环中,将初始色值存储到每一个li标签自定义的url[i].myli属性上,当鼠标划到(onmouseover)中,this.style.background赋值为orange,当鼠标移出(onmouseout)时,this.style.background赋值为this.myli
- 编程范式:命令式与声明式
eg.命令式--详细的命令机器怎么去处理一件事情以达到想要的结果
eg.声明式--只告诉想要的结果,机器自己摸索过程let list = [1,2,3,4] let mapl = [] for(let i = 0; i < list.length; i++){ mapl.push(list[i] * 2) }let list = [1,2,3,4] const double = x => x * 2 list.map(double)
举例来说:
- 命令式编程:描述详细路径(1、下一个路口左转;2、下个有红灯的路口右转;3、前进100米;4、在下个路口掉头;5、到达王府井大街出租车停车区)
- 声明式编程:只告诉目的地(带我到王府井大街)
1.4 一些案例分析
1.4.1 交通灯状态转换
- 状态模式:实现一个切换多个交通灯状态切换的功能
状态模式的定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。将这句话分为两部分来看,第一部分的意思是将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态改变时,会带来不同的行为变化;第二部分是从客户的角度看,使用的对象在不同的状态下具有截然不同的行为,这个对象看起来是从不同的类中实例化而来的,实际上这是使用了委托的效果。
- 方法一:把每种状态嵌套进去
该方法一开始就获取了class=traffic的元素,然后声明一个reset函数,这个函数的功能是:默认情况下,将这个traffic元素的className属性设置为's1'.这样设置后,就命中了下面这个CSS设置,使得li元素的背景变成了绿色。然后,让setTimeout方法嵌套。
- 方法一:把每种状态嵌套进去
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用JS实现交通信号灯</title>
<style>
#traffic {
display: flex;
flex-direction: column;
}
#traffic li {
list-style: none;
width: 50px;
height: 50px;
background-color: lightgray;
margin: 5px;
border-radius: 50%;
}
#traffic.s1 li:nth-child(1) {
background-color: #a00;
}
#traffic.s2 li:nth-child(2) {
background-color: #0a0;
}
#traffic.s3 li:nth-child(3) {
background-color: #00a;
}
#traffic.s4 li:nth-child(4) {
background-color: #a0a;
}
#traffic.s5 li:nth-child(5) {
background-color: #0aa;
}
</style>
</head>
<body>
<div class="traffic-light-page">
<ul id="traffic" class="wait">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
const traffic = document.getElementById('traffic')(function reset() {
// 默认情况下,将traffic的className属性设置为's1'
traffic.className = 's1'
setTimeout(function () {
traffic.className = 's2'
setTimeout(function () {
traffic.className = 's3'
setTimeout(function () {
traffic.className = 's4'
setTimeout(function () {
traffic.className = 's5'
setTimeout(reset, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
})()
</script>
</body>
</html>
缺点:1、如果修改了HTML代码,元素就不叫做traffic了,这个函数就不工作了
2、如果想把这个函数复用到其他地方,还得在那个地方重建这个traffic对象
- 方法二:抽象数据做状态的切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用JS实现交通信号灯--方法二:抽象数据做状态的切换</title>
<style>
#traffic {
display: flex;
flex-direction: column;
}
#traffic li {
display: inline-block;
width: 50px;
height: 50px;
background-color: lightgray;
margin: 5px;
border-radius: 50%;
}
#traffic.stop li:nth-child(1) {
background-color: #a00;
}
#traffic.wait li:nth-child(2) {
background-color: rgb(245, 245, 12);
}
/* 将class=traffic&class=pass元素下的第一个li的元素的背景色设为绿色 */
#traffic.pass li:nth-child(3) {
background-color: #0a0;
}
</style>
</head>
<body>
<div class="traffic-light-page">
<ul id="traffic" class="wait">
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
// 获取class=traffic的元素
const traffic = document.getElementById('traffic')
// 抽象数据状态
const stateList = [
{
state: 'stop',
last: 1000,
},
{
state: 'wait',
last: 1000,
},
{
state: 'pass',
last: 1000,
},
]
// 异步的递归调用
function start(traffic, stateList) {
// 会根据stateIdx进行切换
function applyState(stateIdx) {
const { state, last } = stateList[stateIdx]
traffic.className = state
setTimeout(() => {
applyState((stateIdx + 1) % stateList.length)
}, last)
}
applyState(0)
}
start(traffic, stateList)
</script>
</body>
</html>
数据抽象就是把数据定义并聚合成能被过程处理的对象,交由特定的过程处理。简单来说,就是数据的结构化。经过数据抽象的代码可以适应不同状态和时间的业务需求,只需要修改数据抽象即可,而不修改start方法。
缺点:采用数据抽象重构后,start方法还未达到完全封装。因为start函数中存在一部分改变外部状态的代码。把改变外部状态的部分叫做代码的副作用。通常情况下,可以考虑把函数体内部分有副作用的代码剥离出来,这样往往能提升函数的通用性、稳定性和可测试性。
- 方法三:过程抽象出一个轮询的方法
// 其他不变
<script>
const traffic = document.getElementById('traffic')
function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
function poll(...fnList) {
let stateIndex = 0
return async function (...args) {
let fn = fnList[stateIndex++ % fnList.length]
return await fn.apply(this, args)
}
}
async function setState(state, ms) {
traffic.className = state
await wait(ms)
}
// 过程抽象
let trafficStatePoll = poll(setState.bind(null, 'wait', 1000), setState.bind(null, 'pass', 3000), setState.bind(null, 'stop', 3000))
;(async function () {
while (1) {
await trafficStatePoll()
}
})()
</script>
- 方法四:
<script>
const traffic = document.getElementById('traffic')
// 等待多长时间
function wait(time) {
return new Promise((resolve) => setTimeout(resolve, time))
}
// 状态的切换
function setState(state) {
traffic.className = state
}
async function start() {
while (1) {
setState('wait')
await wait(1000)
setState('pass')
await wait(3000)
setState('stop')
await wait(3000)
}
}
start()
</script>
原理:将setTimeout方法封装成wait函数,这个函数将setTimeout方法用promise包裹起来,并返回这个Promise对象。有了这个wait函数之后,setTimeout嵌套,比较容易改写成一个async函数中的await函数。
-
判断是否是4的幂
- 直接判断是否能被4整除(性能不是最好的)
- 按位与0b11
- O1时间复杂的一种算法
-
洗牌
1.5 一些JavaScript性能优化小技巧
2 用JavaScript实现一个完整的项目实例演示
解决一个问题或实现一个功能
- 有意思的参考:blog.csdn.net/Anterior_co…
2.1 完成“动态选中并删除表格多行”的案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用javascript动态选中并删除表格多行</title>
<style>
h2 {
margin-left: 350px;
}
table {
width: 800px;
height: 400px;
border: 2px solid lightgray;
border-collapse: collapse;
background-color: lightgoldenrodyellow;
padding: 5px;
}
table tr td {
color: rgb(82, 82, 82);
text-align: center;
}
</style>
</head>
<body>
<div id="tb">
<caption>
<h2>我的购物车</h2>
</caption>
<table>
<tr>
<td><input type="checkbox" id="all" value="全选" onclick="all_check()" /></td>
<td>商品</td>
<td>价格(元)</td>
<td>数量</td>
</tr>
<tr>
<td><input type="checkbox" name="Cfj" value="1" onclick="single_check()" /></td>
<td>飞科吹风机</td>
<td>79</td>
<td>12</td>
</tr>
<tr>
<td><input type="checkbox" name="Cfj" value="2" onclick="single_check()" /></td>
<td>松下小吹筒家用大吹风机</td>
<td>139</td>
<td>9</td>
</tr>
<tr>
<td><input type="checkbox" name="Cfj" value="3" onclick="single_check()" /></td>
<td>博锐吹风机</td>
<td>49</td>
<td>14</td>
</tr>
<tr>
<td><input type="checkbox" name="Cfj" value="4" onclick="single_check()" /></td>
<td>飞利浦吹风机</td>
<td>56</td>
<td>6</td>
</tr>
<tr>
<td colspan="4" onclick="tremove()"><button>删除选中项</button></td>
</tr>
</table>
<script>
var allcheck = document.getElementById('all')
var oinput = document.getElementsByName('Cfj')
var tb = document.getElementById('tb')
function all_check() {
for (var i = 0; i < oinput.length; i++) {
if (allcheck.checked == true) {
oinput[i].checked = true
} else {
oinput[i].checked = false
}
}
}
function single_check() {
var j = 0
for (var i = 0; i < oinput.length; i++) {
if (oinput[i].checked == true) {
j = j + 1
}
}
if (j == oinput.length) {
// 当所有的都被选中
allcheck.checked = true
} else {
allcheck.checked = false
}
}
function tremove() {
for (var k = 0; k < oinput.length; k++) {
if (oinput[k].checked == true) {
tb.deleteRow(k + 1)
k = -1
}
}
}
</script>
</div>
</body>
</html>
总结
经过这次对JavaScript的学习,回顾并加深了我对JavaScript的理解,且在使用JavaScript完成某个功能或解决问题的过程中体会到使用JavaScript有趣并奇妙的地方。同时,我了解到了,实现一个功能我们要尽可能通过不同的方式去实现,提高页面的展现效果和效率。