文章目录

    • 前言
    • Day 1 expanding-cards
    • Day 2 progress-steps
    • Day 7 Split Landing Page
    • Day9 Sound Board
    • Day10 Dad Jokes

前言

发现一个没有用前端框架的练手项目,很适合我这种纯后端开发夯实基础,内含50个mini project,学习一下,做做笔记。

  • 项目地址:https://github.com/bradtraversy/50projects50days

Day 1 expanding-cards

效果预览

核心代码:

<body><div class="container"><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 = falsenext.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><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