文章目录
-
- 前言
- [Day 1 expanding-cards](#Day 1 expanding-cards)
- [Day 2 progress-steps](#Day 2 progress-steps)
- [Day 7 Split Landing Page](#Day 7 Split Landing Page)
- [Day9 Sound Board](#Day9 Sound Board)
- [Day10 Dad Jokes](#Day10 Dad Jokes)
- [Day11 Event Keycodes](#Day11 Event Keycodes)
- [Day12 FAQ collapse](#Day12 FAQ collapse)
-
- 重点1:classList.toggle('active')
- [重点2:css 伪类选择器](#重点2:css 伪类选择器)
- [重点3:css 的覆盖](#重点3:css 的覆盖)
- [Day46 Quiz App](#Day46 Quiz App)
-
- [重点 label 标签的 for 属性](#重点 label 标签的 for 属性)
前言
发现一个没有用前端框架的练手项目,很适合我这种纯后端开发夯实基础,内含50个mini project,学习一下,做做笔记。
Day 1 expanding-cards
核心代码:
<body>
<div class="container">
<!--active 标识被点击的图片 -->
<div class="panel active" >
</div>
<div class="panel" >
</div>
<div class="panel" >
</div>
<div class="panel" >
</div>
<div class="panel" >
</div>
</div>
<script src="script.js"></script>
</body>
// 为所有的 panel 注册点击事件
panels.forEach(panel => {
panel.addEventListener('click', () => {
// 清空所有 active 样式
removeActiveClasses()
// 激活被点击 panel 的 active样式
panel.classList.add('active')
})
})
function removeActiveClasses() {
panels.forEach(panel => {
panel.classList.remove('active')
})
}
知识点总结:
- 响应式布局
flex: 5;
- 操作
classList
可以动态修改节点的class
Day 2 progress-steps
核心代码:
function update() {
// Day1 中的处理方式
circles.forEach((circle, idx) => {
if(idx < currentActive) {
circle.classList.add('active')
} else {
circle.classList.remove('active')
}
})
// 按钮的禁用控制
if(currentActive === 1) {
prev.disabled = true
} else if(currentActive === circles.length) {
next.disabled = true
} else {
prev.disabled = false
next.disabled = false
}
}
知识点总结:
- Day1 中的样式控制
- 通用的前进后退按钮禁用逻辑
- 当前节点为第一个节点:后退按钮禁用
- 当前节点为最后一个节点:前进按钮禁用
- 其他情况,都不禁用
Day 7 Split Landing Page
核心代码:
const left = document.querySelector('.left')
const right = document.querySelector('.right')
const container = document.querySelector('.container')
left.addEventListener('mouseenter', () => container.classList.add('hover-left'))
left.addEventListener('mouseleave', () => container.classList.remove('hover-left'))
right.addEventListener('mouseenter', () => container.classList.add('hover-right'))
right.addEventListener('mouseleave', () => container.classList.remove('hover-right'))
知识点总结:
- 两种样式的互斥交互,成对编写 classList.add/remove
- mouseenter 是鼠标移入事件,mouseleave 是鼠标移出事件
Day9 Sound Board
效果预览 (打开音频设备)
核心代码:
<audio id="applause" src="sounds/applause.mp3"></audio>
<audio id="boo" src="sounds/boo.mp3"></audio>
<audio id="gasp" src="sounds/gasp.mp3"></audio>
<audio id="tada" src="sounds/tada.mp3"></audio>
<audio id="victory" src="sounds/victory.mp3"></audio>
<audio id="wrong" src="sounds/wrong.mp3"></audio>
<!-- 作为容器给js添加按钮 -->
<div id="buttons"></div>
<script src="script.js"></script>
const sounds = ['applause', 'boo', 'gasp', 'tada', 'victory', 'wrong']
sounds.forEach(sound => {
const btn = document.createElement('button')
btn.classList.add('btn')
btn.innerText = sound
// 注册事件 点击按钮就停止所有音效后,播放当前选中的音乐
btn.addEventListener('click', () => {
stopSongs()
document.getElementById(sound).play()
})
// 加进h5渲染页面
document.getElementById('buttons').appendChild(btn)
})
function stopSongs() {
sounds.forEach(sound => {
const song = document.getElementById(sound)
song.pause()
song.currentTime = 0;
})
}
知识点总结:
- html中声明一个 div 作为容器,提供js渲染
audio元素.play()
播放audio元素.pause() audio元素.currentTime = 0
停止
Day10 Dad Jokes
核心代码:
jokeBtn.addEventListener('click', generateJoke)
generateJoke()
async function generateJoke() {
const config = {
headers: {
Accept: 'application/json',
},
}
const res = await fetch('https://icanhazdadjoke.com', config)
const data = await res.json()
jokeEl.innerHTML = data.joke
}
-
第二种generateJoke的写法
function generateJoke() {
const config = {
headers: {
Accept: 'application/json',
},
}
fetch('https://icanhazdadjoke.com', config)
.then((res) => res.json())
.then((data) => {
jokeEl.innerHTML = data.joke
})
}
知识点总结:
- 使用js发起异步http请求的两种方式
- async await fetch
- Promise形式的链式调用 fetch then
Day11 Event Keycodes
-
keyCode 是一个属性,这个项目可以当个字典用。原文演示地址
const insert = document.getElementById('insert')
window.addEventListener('keydown', (event) => {
insert.innerHTML = `
{event.key === ' ' ? 'Space' : event.key} event.key {event.keyCode} event.keyCode
${event.code} event.code ` })
其中一个应用场景是禁止回车提交表单。
<form method="post">
<input type="text" name="username" id="username" onKeyPress="return EnterStop(event);"/>
<input type="button" value="提交" id="submint"/>
</form>
function EnterStop(e){
if(e.keyCode == 13){
return false;
}
}
Day12 FAQ collapse
跟 day 1 一样,使用了 active 的思路,并且在js层面用 dom 查找父元素进行样式操作
<body>
<h1>Frequently Asked Questions</h1>
<div class="faq-container">
<div class="faq active">
<h3 class="faq-title">
Why shouldn't we trust atoms?
</h3>
<p class="faq-text">
They make up everything
</p>
<button class="faq-toggle">
<i class="fas fa-chevron-down"></i>
<i class="fas fa-times"></i>
</button>
</div>
</div>
<script src="script.js"></script>
</body>
重点1:classList.toggle('active')
toggle 函数的能力:本例中,如果元素有 active 属性,那么就删除 ative。如果没有则追加。做到了一种类似开关的效果。
const toggles = document.querySelectorAll('.faq-toggle')
toggles.forEach(toggle => {
toggle.addEventListener('click', () => {
toggle.parentNode.classList.toggle('active')
})
})
重点2:css 伪类选择器
类选择器被激活后,包裹住div,用了一个css中的伪类的技巧。
.faq.active::before,
.faq.active::after {
content: '075';
font-family: 'Font Awesome 5 Free';
color: #2ecc71;
font-size: 7rem;
position: absolute;
opacity: 0.2;
top: 20px;
left: 20px;
z-index: 0;
}
重点3:css 的覆盖
这个图是拿css来画出来的,可以观察代码实现,利用了css覆盖的知识
.faq.active::before,
.faq.active::after {
content: '075';
font-family: 'Font Awesome 5 Free';
color: #2ecc71;
font-size: 7rem;
position: absolute;
opacity: 0.2;
top: 20px;
left: 20px;
z-index: 0;
}
// 覆盖样式,形成蓝色的图形
.faq.active::before {
color: #3498db;
top: -10px;
left: -30px;
transform: rotateY(180deg);
}
Day46 Quiz App
重点 label 标签的 for 属性
-
html
Question text
- Question
Submit
- Question
-
label for
当点击label标签内的文本后,就会触发绑定的表单元素。
上面的场景是点击问题的文字,input元素就会被激活