JavaScript練習(xí)語法及建議總結(jié)大全
基礎(chǔ)文件
- index.html:主入口頁面,它鏈接了所有示例頁面(如DOM操作、事件處理等)和對應(yīng)的JS文件。
- om.html :展示DOM操作的各種方法
- event.html :展示事件處理的各種類型
- animation.html :展示JavaScript動畫效果
- ajax.html :展示AJAX請求和數(shù)據(jù)處理
- js: 存放js文件
- todo.js - 實現(xiàn)待辦事項列表功能,包括添加、刪除和標記任務(wù)完成
- counter.js - 實現(xiàn)計數(shù)器功能,支持增減、重置、本地存儲和動畫效果
- color.js - 實現(xiàn)顏色選擇器,支持實時預(yù)覽、本地存儲和隨機顏色生成
- form.js - 實現(xiàn)表單驗證功能,包括用戶名、郵箱和密碼的實時驗證
這些JS文件通過“ script ”標簽被引入到HTML頁面中,為頁面添加交互功能。每個文件都專注于實現(xiàn)特定的功能模塊,遵循了模塊化的開發(fā)原則。
綜合練習(xí):在線筆記本
project.html :一個完整的在線筆記本應(yīng)用,整合了所有JavaScript知識點
- 功能包括:
- 筆記的增刪改查
- 標簽管理和篩選
- 搜索功能
- 本地存儲
- 動畫效果
- 事件處理
- 模態(tài)框操作
練習(xí)建議 :
- 先從基礎(chǔ)開始,依次練習(xí):
- 主頁面(index.html)
- DOM操作(dom.html)
- 事件處理(event.html)
- 動畫效果(animation.html)
- AJAX請求(ajax.html)
- 最后練習(xí)綜合項目(project.html),理解如何將各個知識點結(jié)合使用

index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript綜合練習(xí)項目</title>
<style>
/* 基礎(chǔ)樣式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
nav {
background-color: #fff;
padding: 1rem;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
nav ul {
list-style: none;
display: flex;
gap: 20px;
}
nav a {
text-decoration: none;
color: #333;
padding: 5px 10px;
border-radius: 4px;
transition: background-color 0.3s;
}
nav a:hover {
background-color: #e6e6e6;
}
.section {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1, h2 {
margin-bottom: 1rem;
color: #333;
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
input, textarea {
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
width: 100%;
margin-bottom: 10px;
}
.todo-list {
list-style: none;
}
.todo-item {
display: flex;
align-items: center;
padding: 10px;
background-color: #fafafa;
margin-bottom: 5px;
border-radius: 4px;
}
.todo-item input[type="checkbox"] {
width: auto;
margin-right: 10px;
}
.completed {
text-decoration: line-through;
color: #999;
}
</style>
</head>
<body>
<div class="container">
<h1>JavaScript綜合練習(xí)項目</h1>
<nav>
<ul>
<li><a href="index.html" rel="external nofollow" >首頁</a></li>
<li><a href="dom.html" rel="external nofollow" >DOM操作</a></li>
<li><a href="event.html" rel="external nofollow" >事件處理</a></li>
<li><a href="ajax.html" rel="external nofollow" >AJAX請求</a></li>
<li><a href="animation.html" rel="external nofollow" >動畫效果</a></li>
</ul>
</nav>
<!-- 待辦事項列表部分 -->
<section class="section" id="todo-section">
<h2>待辦事項列表</h2>
<div>
<input type="text" id="todo-input" placeholder="輸入新的待辦事項">
<button id="add-todo">添加</button>
</div>
<ul class="todo-list" id="todo-list">
<!-- 待辦事項將通過JavaScript動態(tài)添加 -->
</ul>
</section>
<!-- 計數(shù)器部分 -->
<section class="section" id="counter-section">
<h2>計數(shù)器</h2>
<div>
<button id="decrease">-</button>
<span id="count">0</span>
<button id="increase">+</button>
<button id="reset">重置</button>
</div>
</section>
<!-- 顏色選擇器部分 -->
<section class="section" id="color-section">
<h2>顏色選擇器</h2>
<div>
<input type="color" id="color-picker">
<div id="color-display" style="width: 100px; height: 100px; margin-top: 10px; border: 1px solid #ccc;"></div>
</div>
</section>
<!-- 表單驗證部分 -->
<section class="section" id="form-section">
<h2>表單驗證</h2>
<form id="validation-form">
<div>
<input type="text" id="username" placeholder="用戶名(3-10個字符)">
<span id="username-error" style="color: red;"></span>
</div>
<div>
<input type="email" id="email" placeholder="郵箱地址">
<span id="email-error" style="color: red;"></span>
</div>
<div>
<input type="password" id="password" placeholder="密碼(至少6個字符)">
<span id="password-error" style="color: red;"></span>
</div>
<button type="submit">提交</button>
</form>
</section>
</div>
<!-- 引入JavaScript文件 -->
<script src="js/todo.js"></script>
<script src="js/counter.js"></script>
<script src="js/color.js"></script>
<script src="js/form.js"></script>
</body>
</html>
1.dom.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM操作示例</title>
<style>
/* 基礎(chǔ)樣式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
.demo-box {
border: 1px solid #d9d9d9;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}
.highlight {
background-color: #fff7e6;
border-color: #ffd591;
}
.list-item {
padding: 8px;
margin: 4px 0;
background-color: #f5f5f5;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
}
.success {
color: #52c41a;
}
.error {
color: #f5222d;
}
</style>
</head>
<body>
<div class="container">
<h1>DOM操作示例</h1>
<nav>
<button onclick="location.href='index.html'">返回首頁</button>
</nav>
<!-- 元素選擇和修改 -->
<section class="section">
<h2>元素選擇和修改</h2>
<div class="demo-box" id="select-demo">
<p id="target-text">這是目標文本</p>
<p class="sample-class">使用類選擇器選擇的文本</p>
<p data-type="special">使用屬性選擇器選擇的文本</p>
</div>
<div>
<button onclick="changeText()">修改文本</button>
<button onclick="changeStyle()">修改樣式</button>
<button onclick="changeAttribute()">修改屬性</button>
</div>
</section>
<!-- 元素創(chuàng)建和添加 -->
<section class="section">
<h2>元素創(chuàng)建和添加</h2>
<div class="demo-box" id="create-demo">
<div id="element-container"></div>
</div>
<div>
<button onclick="createElement()">創(chuàng)建元素</button>
<button onclick="cloneElement()">克隆元素</button>
<button onclick="insertElement()">插入元素</button>
</div>
</section>
<!-- 元素刪除和替換 -->
<section class="section">
<h2>元素刪除和替換</h2>
<div class="demo-box" id="modify-demo">
<ul id="item-list">
<li class="list-item">項目 1</li>
<li class="list-item">項目 2</li>
<li class="list-item">項目 3</li>
</ul>
</div>
<div>
<button onclick="removeElement()">刪除元素</button>
<button onclick="replaceElement()">替換元素</button>
<button onclick="resetList()">重置列表</button>
</div>
</section>
<!-- 事件處理 -->
<section class="section">
<h2>事件處理</h2>
<div class="demo-box" id="event-demo">
<div id="event-target" style="padding: 20px; background-color: #f5f5f5; text-align: center;">
在此區(qū)域內(nèi)移動鼠標或點擊
</div>
<p id="event-info"></p>
</div>
</section>
</div>
<script>
// 元素選擇和修改
function changeText() {
// 通過ID選擇元素并修改文本
const element = document.getElementById('target-text');
element.textContent = '文本已被修改!' + new Date().toLocaleTimeString();
}
function changeStyle() {
// 通過類名選擇元素并修改樣式
const elements = document.getElementsByClassName('sample-class');
for (let element of elements) {
element.classList.toggle('highlight');
}
}
function changeAttribute() {
// 通過屬性選擇器選擇元素并修改屬性
const element = document.querySelector('[data-type="special"]');
const currentType = element.getAttribute('data-type');
element.setAttribute('data-type', currentType === 'special' ? 'normal' : 'special');
element.textContent = `當(dāng)前屬性值:${element.getAttribute('data-type')}`;
}
// 元素創(chuàng)建和添加
let elementCount = 0;
function createElement() {
elementCount++;
// 創(chuàng)建新元素
const newElement = document.createElement('div');
newElement.className = 'list-item';
newElement.textContent = `新元素 ${elementCount}`;
// 添加到容器
document.getElementById('element-container').appendChild(newElement);
}
function cloneElement() {
const container = document.getElementById('element-container');
if (container.children.length > 0) {
// 克隆最后一個元素
const lastElement = container.lastElementChild;
const clone = lastElement.cloneNode(true);
clone.textContent += ' (克隆)';
container.appendChild(clone);
}
}
function insertElement() {
const container = document.getElementById('element-container');
// 創(chuàng)建新元素
const newElement = document.createElement('div');
newElement.className = 'list-item';
newElement.textContent = '插入的元素';
// 在第一個子元素之前插入
if (container.firstChild) {
container.insertBefore(newElement, container.firstChild);
} else {
container.appendChild(newElement);
}
}
// 元素刪除和替換
function removeElement() {
const list = document.getElementById('item-list');
if (list.children.length > 0) {
list.removeChild(list.lastElementChild);
}
}
function replaceElement() {
const list = document.getElementById('item-list');
if (list.children.length > 0) {
// 創(chuàng)建新元素
const newElement = document.createElement('li');
newElement.className = 'list-item';
newElement.textContent = '替換的項目 ' + new Date().toLocaleTimeString();
// 替換第一個元素
list.replaceChild(newElement, list.firstElementChild);
}
}
function resetList() {
document.getElementById('item-list').innerHTML = `
<li class="list-item">項目 1</li>
<li class="list-item">項目 2</li>
<li class="list-item">項目 3</li>
`;
}
// 事件處理
document.addEventListener('DOMContentLoaded', function() {
const eventTarget = document.getElementById('event-target');
const eventInfo = document.getElementById('event-info');
// 鼠標移動事件
eventTarget.addEventListener('mousemove', function(e) {
const rect = eventTarget.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
eventInfo.textContent = `鼠標位置 - X: ${Math.round(x)}px, Y: ${Math.round(y)}px`;
});
// 點擊事件
eventTarget.addEventListener('click', function(e) {
eventTarget.style.backgroundColor =
'#' + Math.floor(Math.random()*16777215).toString(16);
});
// 鼠標進入事件
eventTarget.addEventListener('mouseenter', function() {
eventTarget.style.transform = 'scale(1.02)';
});
// 鼠標離開事件
eventTarget.addEventListener('mouseleave', function() {
eventTarget.style.transform = 'scale(1)';
});
});
</script>
</body>
</html>
2.event.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件處理示例</title>
<style>
/* 基礎(chǔ)樣式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.demo-box {
border: 1px solid #d9d9d9;
padding: 15px;
margin: 10px 0;
border-radius: 4px;
background-color: #fafafa;
}
.event-log {
height: 100px;
overflow-y: auto;
padding: 10px;
background-color: #f5f5f5;
border-radius: 4px;
margin-top: 10px;
font-family: monospace;
}
.interactive-area {
width: 200px;
height: 200px;
background-color: #e6f7ff;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
user-select: none;
}
.key-display {
font-size: 2em;
text-align: center;
padding: 20px;
background-color: #f0f0f0;
border-radius: 4px;
margin: 10px 0;
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
input[type="text"] {
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
width: 200px;
margin: 5px;
}
.drag-item {
width: 100px;
height: 100px;
background-color: #91d5ff;
display: flex;
align-items: center;
justify-content: center;
cursor: move;
margin: 10px;
transition: transform 0.2s;
}
.drop-zone {
width: 200px;
height: 200px;
border: 2px dashed #1890ff;
display: flex;
align-items: center;
justify-content: center;
margin: 10px;
}
.drop-zone.dragover {
background-color: #e6f7ff;
border-style: solid;
}
</style>
</head>
<body>
<div class="container">
<h1>事件處理示例</h1>
<nav>
<button onclick="location.href='index.html'">返回首頁</button>
</nav>
<!-- 鼠標事件 -->
<section class="section">
<h2>鼠標事件</h2>
<div class="demo-box">
<div id="mouse-area" class="interactive-area">在此區(qū)域操作鼠標</div>
<div id="mouse-log" class="event-log"></div>
</div>
</section>
<!-- 鍵盤事件 -->
<section class="section">
<h2>鍵盤事件</h2>
<div class="demo-box">
<input type="text" id="key-input" placeholder="在此輸入文字">
<div id="key-display" class="key-display">按下任意鍵</div>
<div id="key-log" class="event-log"></div>
</div>
</section>
<!-- 表單事件 -->
<section class="section">
<h2>表單事件</h2>
<div class="demo-box">
<form id="demo-form">
<input type="text" id="form-input" placeholder="輸入文字">
<select id="form-select">
<option value="">請選擇</option>
<option value="1">選項1</option>
<option value="2">選項2</option>
<option value="3">選項3</option>
</select>
<button type="submit">提交</button>
</form>
<div id="form-log" class="event-log"></div>
</div>
</section>
<!-- 拖放事件 -->
<section class="section">
<h2>拖放事件</h2>
<div class="demo-box">
<div style="display: flex;">
<div id="drag-item" class="drag-item" draggable="true">拖動我</div>
<div id="drop-zone" class="drop-zone">放置區(qū)域</div>
</div>
<div id="drag-log" class="event-log"></div>
</div>
</section>
</div>
<script>
// 工具函數(shù):記錄事件到日志
function logEvent(logElement, message) {
const log = document.createElement('div');
log.textContent = `${new Date().toLocaleTimeString()} - ${message}`;
logElement.insertBefore(log, logElement.firstChild);
// 限制日志條數(shù)
if (logElement.children.length > 10) {
logElement.removeChild(logElement.lastChild);
}
}
// 鼠標事件處理
document.addEventListener('DOMContentLoaded', function() {
const mouseArea = document.getElementById('mouse-area');
const mouseLog = document.getElementById('mouse-log');
// 鼠標進入
mouseArea.addEventListener('mouseenter', function(e) {
mouseArea.style.backgroundColor = '#bae7ff';
logEvent(mouseLog, '鼠標進入?yún)^(qū)域');
});
// 鼠標移動
mouseArea.addEventListener('mousemove', function(e) {
const rect = mouseArea.getBoundingClientRect();
const x = Math.round(e.clientX - rect.left);
const y = Math.round(e.clientY - rect.top);
mouseArea.textContent = `X: ${x}, Y: ${y}`;
});
// 鼠標離開
mouseArea.addEventListener('mouseleave', function(e) {
mouseArea.style.backgroundColor = '#e6f7ff';
mouseArea.textContent = '在此區(qū)域操作鼠標';
logEvent(mouseLog, '鼠標離開區(qū)域');
});
// 鼠標點擊
mouseArea.addEventListener('click', function(e) {
mouseArea.style.transform = 'scale(0.95)';
setTimeout(() => mouseArea.style.transform = 'scale(1)', 200);
logEvent(mouseLog, '鼠標點擊');
});
// 鼠標右鍵
mouseArea.addEventListener('contextmenu', function(e) {
e.preventDefault();
logEvent(mouseLog, '鼠標右鍵點擊');
});
});
// 鍵盤事件處理
document.addEventListener('DOMContentLoaded', function() {
const keyInput = document.getElementById('key-input');
const keyDisplay = document.getElementById('key-display');
const keyLog = document.getElementById('key-log');
// 鍵盤按下
keyInput.addEventListener('keydown', function(e) {
keyDisplay.textContent = e.key;
keyDisplay.style.backgroundColor = '#bae7ff';
logEvent(keyLog, `按下鍵: ${e.key}`);
});
// 鍵盤釋放
keyInput.addEventListener('keyup', function(e) {
keyDisplay.style.backgroundColor = '#f0f0f0';
logEvent(keyLog, `釋放鍵: ${e.key}`);
});
// 輸入事件
keyInput.addEventListener('input', function(e) {
logEvent(keyLog, `輸入內(nèi)容: ${e.target.value}`);
});
});
// 表單事件處理
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('demo-form');
const formInput = document.getElementById('form-input');
const formSelect = document.getElementById('form-select');
const formLog = document.getElementById('form-log');
// 表單提交
form.addEventListener('submit', function(e) {
e.preventDefault();
logEvent(formLog, '表單提交');
});
// 輸入框焦點
formInput.addEventListener('focus', function(e) {
this.style.borderColor = '#40a9ff';
logEvent(formLog, '輸入框獲得焦點');
});
formInput.addEventListener('blur', function(e) {
this.style.borderColor = '#d9d9d9';
logEvent(formLog, '輸入框失去焦點');
});
// 選擇框變化
formSelect.addEventListener('change', function(e) {
logEvent(formLog, `選擇值改變: ${e.target.value}`);
});
});
// 拖放事件處理
document.addEventListener('DOMContentLoaded', function() {
const dragItem = document.getElementById('drag-item');
const dropZone = document.getElementById('drop-zone');
const dragLog = document.getElementById('drag-log');
// 拖動開始
dragItem.addEventListener('dragstart', function(e) {
this.style.opacity = '0.5';
logEvent(dragLog, '開始拖動');
});
// 拖動結(jié)束
dragItem.addEventListener('dragend', function(e) {
this.style.opacity = '1';
logEvent(dragLog, '結(jié)束拖動');
});
// 拖動進入放置區(qū)域
dropZone.addEventListener('dragenter', function(e) {
e.preventDefault();
this.classList.add('dragover');
logEvent(dragLog, '進入放置區(qū)域');
});
// 拖動在放置區(qū)域上方
dropZone.addEventListener('dragover', function(e) {
e.preventDefault();
});
// 離開放置區(qū)域
dropZone.addEventListener('dragleave', function(e) {
this.classList.remove('dragover');
logEvent(dragLog, '離開放置區(qū)域');
});
// 在放置區(qū)域釋放
dropZone.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('dragover');
this.appendChild(dragItem);
logEvent(dragLog, '成功放置');
});
});
</script>
</body>
</html>
3.animation.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>動畫效果示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.demo-box {
border: 1px solid #d9d9d9;
padding: 15px;
margin: 10px 0;
border-radius: 4px;
background-color: #fafafa;
min-height: 200px;
position: relative;
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
.animation-box {
width: 50px;
height: 50px;
background-color: #1890ff;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
.bounce-box {
width: 50px;
height: 50px;
background-color: #52c41a;
border-radius: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 0;
}
.rotate-box {
width: 100px;
height: 100px;
background-color: #722ed1;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.particle {
width: 10px;
height: 10px;
background-color: #f5222d;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #f5f5f5;
border-radius: 10px;
overflow: hidden;
margin: 10px 0;
}
.progress-fill {
width: 0;
height: 100%;
background-color: #1890ff;
transition: width 0.3s ease;
}
.controls {
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>動畫效果示例</h1>
<nav>
<button onclick="location.href='index.html'">返回首頁</button>
</nav>
<!-- 基礎(chǔ)動畫 -->
<section class="section">
<h2>基礎(chǔ)動畫</h2>
<div class="demo-box">
<div class="controls">
<button onclick="startBasicAnimation()">開始動畫</button>
<button onclick="pauseBasicAnimation()">暫停</button>
<button onclick="resetBasicAnimation()">重置</button>
</div>
<div id="basic-animation" class="animation-box"></div>
</div>
</section>
<!-- 彈跳動畫 -->
<section class="section">
<h2>彈跳動畫</h2>
<div class="demo-box">
<div class="controls">
<button onclick="startBounceAnimation()">開始彈跳</button>
<button onclick="stopBounceAnimation()">停止</button>
</div>
<div id="bounce-animation" class="bounce-box"></div>
</div>
</section>
<!-- 旋轉(zhuǎn)和縮放 -->
<section class="section">
<h2>旋轉(zhuǎn)和縮放</h2>
<div class="demo-box">
<div class="controls">
<button onclick="startRotateScale()">開始動畫</button>
<button onclick="stopRotateScale()">停止</button>
</div>
<div id="rotate-scale" class="rotate-box"></div>
</div>
</section>
<!-- 粒子效果 -->
<section class="section">
<h2>粒子效果</h2>
<div class="demo-box">
<div class="controls">
<button onclick="createParticles()">創(chuàng)建粒子</button>
</div>
<div id="particle-container"></div>
</div>
</section>
<!-- 進度條動畫 -->
<section class="section">
<h2>進度條動畫</h2>
<div class="demo-box">
<div class="controls">
<button onclick="startProgress()">開始進度</button>
<button onclick="resetProgress()">重置</button>
</div>
<div class="progress-bar">
<div id="progress" class="progress-fill"></div>
</div>
</div>
</section>
</div>
<script>
// 基礎(chǔ)動畫
let basicAnimationId = null;
let basicAnimationPaused = false;
let basicAnimationPosition = 0;
let lastTimestamp = 0;
function startBasicAnimation() {
if (basicAnimationPaused) {
basicAnimationPaused = false;
lastTimestamp = performance.now();
requestAnimationFrame(animateBasic);
return;
}
const box = document.getElementById('basic-animation');
const container = box.parentElement;
const maxDistance = container.clientWidth - box.clientWidth;
function animateBasic(timestamp) {
if (basicAnimationPaused) return;
if (!lastTimestamp) lastTimestamp = timestamp;
const progress = timestamp - lastTimestamp;
lastTimestamp = timestamp;
basicAnimationPosition += progress * 0.2;
if (basicAnimationPosition >= maxDistance) {
basicAnimationPosition = 0;
}
box.style.left = `${basicAnimationPosition}px`;
basicAnimationId = requestAnimationFrame(animateBasic);
}
basicAnimationId = requestAnimationFrame(animateBasic);
}
function pauseBasicAnimation() {
basicAnimationPaused = true;
}
function resetBasicAnimation() {
basicAnimationPaused = true;
cancelAnimationFrame(basicAnimationId);
basicAnimationPosition = 0;
lastTimestamp = 0;
const box = document.getElementById('basic-animation');
box.style.left = '0px';
}
// 彈跳動畫
let bounceAnimationId = null;
let bounceVelocity = 5;
const gravity = 0.5;
const bounce = -0.7;
function startBounceAnimation() {
const box = document.getElementById('bounce-animation');
const container = box.parentElement;
let position = 0;
function animate() {
position += bounceVelocity;
bounceVelocity += gravity;
// 碰到底部
if (position + box.clientHeight > container.clientHeight) {
position = container.clientHeight - box.clientHeight;
bounceVelocity *= bounce;
}
box.style.top = `${position}px`;
bounceAnimationId = requestAnimationFrame(animate);
}
bounceAnimationId = requestAnimationFrame(animate);
}
function stopBounceAnimation() {
cancelAnimationFrame(bounceAnimationId);
const box = document.getElementById('bounce-animation');
box.style.top = '0px';
bounceVelocity = 5;
}
// 旋轉(zhuǎn)和縮放
let rotateScaleId = null;
let angle = 0;
let scale = 1;
let scaleGrowing = true;
function startRotateScale() {
const box = document.getElementById('rotate-scale');
function animate() {
angle = (angle + 2) % 360;
if (scaleGrowing) {
scale += 0.01;
if (scale >= 1.5) scaleGrowing = false;
} else {
scale -= 0.01;
if (scale <= 0.5) scaleGrowing = true;
}
box.style.transform = `translate(-50%, -50%) rotate(${angle}deg) scale(${scale})`;
rotateScaleId = requestAnimationFrame(animate);
}
rotateScaleId = requestAnimationFrame(animate);
}
function stopRotateScale() {
cancelAnimationFrame(rotateScaleId);
const box = document.getElementById('rotate-scale');
box.style.transform = 'translate(-50%, -50%)';
angle = 0;
scale = 1;
scaleGrowing = true;
}
// 粒子效果
function createParticles() {
const container = document.getElementById('particle-container');
container.innerHTML = '';
const particleCount = 20;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
container.appendChild(particle);
const angle = (Math.PI * 2 * i) / particleCount;
const velocity = 5;
let x = 0;
let y = 0;
let vx = Math.cos(angle) * velocity;
let vy = Math.sin(angle) * velocity;
let opacity = 1;
function animate() {
x += vx;
y += vy;
vy += 0.1; // 重力
opacity -= 0.01;
if (opacity <= 0) {
particle.remove();
return;
}
particle.style.transform = `translate(${x}px, ${y}px)`;
particle.style.opacity = opacity;
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
}
}
// 進度條動畫
let progressInterval = null;
function startProgress() {
const progress = document.getElementById('progress');
let width = 0;
progressInterval = setInterval(() => {
if (width >= 100) {
clearInterval(progressInterval);
return;
}
width += 1;
progress.style.width = `${width}%`;
}, 50);
}
function resetProgress() {
clearInterval(progressInterval);
const progress = document.getElementById('progress');
progress.style.width = '0%';
}
</script>
</body>
</html>
4.ajax.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX請求示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.demo-box {
border: 1px solid #d9d9d9;
padding: 15px;
margin: 10px 0;
border-radius: 4px;
background-color: #fafafa;
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
button:disabled {
background-color: #d9d9d9;
cursor: not-allowed;
}
.result {
margin-top: 10px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 4px;
font-family: monospace;
white-space: pre-wrap;
max-height: 200px;
overflow-y: auto;
}
.error {
color: #f5222d;
}
.success {
color: #52c41a;
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #1890ff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-left: 10px;
vertical-align: middle;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
input[type="text"], textarea {
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
width: 100%;
margin: 5px 0;
}
.status {
margin-top: 10px;
font-style: italic;
}
</style>
</head>
<body>
<div class="container">
<h1>AJAX請求示例</h1>
<nav>
<button onclick="location.href='index.html'">返回首頁</button>
</nav>
<!-- XMLHttpRequest GET請求 -->
<section class="section">
<h2>XMLHttpRequest GET請求</h2>
<div class="demo-box">
<button onclick="makeXHRGet()">發(fā)送GET請求</button>
<div id="xhr-get-result" class="result"></div>
</div>
</section>
<!-- Fetch API GET請求 -->
<section class="section">
<h2>Fetch API GET請求</h2>
<div class="demo-box">
<button onclick="makeFetchGet()">發(fā)送GET請求</button>
<div id="fetch-get-result" class="result"></div>
</div>
</section>
<!-- POST請求 -->
<section class="section">
<h2>POST請求</h2>
<div class="demo-box">
<textarea id="post-data" rows="4" placeholder="輸入要發(fā)送的JSON數(shù)據(jù)">{
"name": "張三",
"age": 25,
"message": "Hello, World!"
}</textarea>
<button onclick="makePost()">發(fā)送POST請求</button>
<div id="post-result" class="result"></div>
</div>
</section>
<!-- 文件上傳 -->
<section class="section">
<h2>文件上傳</h2>
<div class="demo-box">
<input type="file" id="file-input">
<button onclick="uploadFile()">上傳文件</button>
<div id="upload-progress" class="status"></div>
<div id="upload-result" class="result"></div>
</div>
</section>
<!-- 并發(fā)請求 -->
<section class="section">
<h2>并發(fā)請求</h2>
<div class="demo-box">
<button onclick="makeConcurrentRequests()">發(fā)送并發(fā)請求</button>
<div id="concurrent-result" class="result"></div>
</div>
</section>
</div>
<script>
// 模擬API端點
const API_ENDPOINT = 'https://jsonplaceholder.typicode.com';
// 工具函數(shù):格式化響應(yīng)數(shù)據(jù)
function formatResponse(data) {
return typeof data === 'object' ? JSON.stringify(data, null, 2) : data;
}
// 工具函數(shù):顯示結(jié)果
function showResult(elementId, data, isError = false) {
const element = document.getElementById(elementId);
element.textContent = formatResponse(data);
element.className = `result ${isError ? 'error' : 'success'}`;
}
// 工具函數(shù):顯示加載狀態(tài)
function showLoading(elementId, isLoading) {
const element = document.getElementById(elementId);
const loadingSpinner = element.parentElement.querySelector('.loading');
if (isLoading) {
if (!loadingSpinner) {
const spinner = document.createElement('div');
spinner.className = 'loading';
element.parentElement.insertBefore(spinner, element);
}
} else {
if (loadingSpinner) {
loadingSpinner.remove();
}
}
}
// XMLHttpRequest GET請求
function makeXHRGet() {
const resultId = 'xhr-get-result';
showLoading(resultId, true);
const xhr = new XMLHttpRequest();
xhr.open('GET', `${API_ENDPOINT}/posts/1`, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
showLoading(resultId, false);
if (xhr.status === 200) {
showResult(resultId, JSON.parse(xhr.responseText));
} else {
showResult(resultId, `請求失敗: ${xhr.status} ${xhr.statusText}`, true);
}
}
};
xhr.onerror = function() {
showLoading(resultId, false);
showResult(resultId, '網(wǎng)絡(luò)錯誤', true);
};
xhr.send();
}
// Fetch API GET請求
async function makeFetchGet() {
const resultId = 'fetch-get-result';
showLoading(resultId, true);
try {
const response = await fetch(`${API_ENDPOINT}/posts/1`);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
showResult(resultId, data);
} catch (error) {
showResult(resultId, `請求失敗: ${error.message}`, true);
} finally {
showLoading(resultId, false);
}
}
// POST請求
async function makePost() {
const resultId = 'post-result';
showLoading(resultId, true);
try {
const postData = JSON.parse(document.getElementById('post-data').value);
const response = await fetch(`${API_ENDPOINT}/posts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
});
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
showResult(resultId, data);
} catch (error) {
showResult(resultId, `請求失敗: ${error.message}`, true);
} finally {
showLoading(resultId, false);
}
}
// 文件上傳
function uploadFile() {
const resultId = 'upload-result';
const progressElement = document.getElementById('upload-progress');
const fileInput = document.getElementById('file-input');
const file = fileInput.files[0];
if (!file) {
showResult(resultId, '請選擇文件', true);
return;
}
showLoading(resultId, true);
const formData = new FormData();
formData.append('file', file);
const xhr = new XMLHttpRequest();
xhr.open('POST', `${API_ENDPOINT}/posts`, true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
const percentComplete = Math.round((e.loaded / e.total) * 100);
progressElement.textContent = `上傳進度: ${percentComplete}%`;
}
};
xhr.onload = function() {
showLoading(resultId, false);
if (xhr.status === 200) {
showResult(resultId, '文件上傳成功');
} else {
showResult(resultId, `上傳失敗: ${xhr.status} ${xhr.statusText}`, true);
}
};
xhr.onerror = function() {
showLoading(resultId, false);
showResult(resultId, '網(wǎng)絡(luò)錯誤', true);
};
xhr.send(formData);
}
// 并發(fā)請求
async function makeConcurrentRequests() {
const resultId = 'concurrent-result';
showLoading(resultId, true);
try {
const requests = [
fetch(`${API_ENDPOINT}/posts/1`).then(r => r.json()),
fetch(`${API_ENDPOINT}/posts/2`).then(r => r.json()),
fetch(`${API_ENDPOINT}/posts/3`).then(r => r.json())
];
const results = await Promise.all(requests);
showResult(resultId, results);
} catch (error) {
showResult(resultId, `請求失敗: ${error.message}`, true);
} finally {
showLoading(resultId, false);
}
}
// 自定義AJAX函數(shù)封裝
function ajax(options) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', options.url, true);
if (options.headers) {
Object.keys(options.headers).forEach(key => {
xhr.setRequestHeader(key, options.headers[key]);
});
}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve({
data: JSON.parse(xhr.responseText),
status: xhr.status,
statusText: xhr.statusText
});
} else {
reject(new Error(`請求失敗: ${xhr.status} ${xhr.statusText}`));
}
}
};
xhr.onerror = () => reject(new Error('網(wǎng)絡(luò)錯誤'));
xhr.send(options.data);
});
}
</script>
</body>
</html>
5. color.js
// color.js - 顏色選擇器功能實現(xiàn)
// 等待DOM完全加載后執(zhí)行
document.addEventListener('DOMContentLoaded', function() {
// 獲取DOM元素
const colorPicker = document.getElementById('color-picker'); // 顏色選擇輸入框
const colorDisplay = document.getElementById('color-display'); // 顏色顯示區(qū)域
// 從localStorage加載保存的顏色
function loadColor() {
// 嘗試從localStorage獲取保存的顏色值
const savedColor = localStorage.getItem('selectedColor');
if (savedColor) {
// 如果有保存的顏色,更新選擇器和顯示區(qū)域
colorPicker.value = savedColor;
updateColorDisplay(savedColor);
}
}
// 保存顏色到localStorage
function saveColor(color) {
localStorage.setItem('selectedColor', color);
}
// 更新顏色顯示
function updateColorDisplay(color) {
// 更新顯示區(qū)域的背景顏色
colorDisplay.style.backgroundColor = color;
// 計算顏色的亮度
const rgb = hexToRgb(color);
const brightness = calculateBrightness(rgb);
// 根據(jù)背景色的亮度設(shè)置文本顏色
colorDisplay.style.color = brightness > 128 ? '#000' : '#fff';
// 顯示顏色值
colorDisplay.textContent = color.toUpperCase();
// 添加過渡動畫
addTransitionEffect();
}
// 將十六進制顏色轉(zhuǎn)換為RGB
function hexToRgb(hex) {
// 移除#號(如果有)
hex = hex.replace('#', '');
// 將十六進制轉(zhuǎn)換為RGB值
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}
// 計算顏色的亮度
function calculateBrightness({ r, g, b }) {
// 使用相對亮度公式:(0.299*R + 0.587*G + 0.114*B)
return (0.299 * r + 0.587 * g + 0.114 * b);
}
// 添加過渡效果
function addTransitionEffect() {
// 添加過渡類
colorDisplay.classList.add('color-transition');
// 移除過渡類
setTimeout(() => {
colorDisplay.classList.remove('color-transition');
}, 300);
}
// 生成隨機顏色
function generateRandomColor() {
// 生成隨機的RGB值
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
// 轉(zhuǎn)換為十六進制
const hex = '#' + [
r.toString(16).padStart(2, '0'),
g.toString(16).padStart(2, '0'),
b.toString(16).padStart(2, '0')
].join('');
return hex;
}
// 添加雙擊事件來生成隨機顏色
colorDisplay.addEventListener('dblclick', function() {
const randomColor = generateRandomColor();
colorPicker.value = randomColor;
updateColorDisplay(randomColor);
saveColor(randomColor);
});
// 添加顏色選擇事件監(jiān)聽器
colorPicker.addEventListener('input', function(e) {
// 獲取選擇的顏色
const selectedColor = e.target.value;
// 更新顯示并保存
updateColorDisplay(selectedColor);
saveColor(selectedColor);
});
// 添加動畫樣式
const style = document.createElement('style');
style.textContent = `
#color-display {
display: flex;
align-items: center;
justify-content: center;
font-family: monospace;
transition: background-color 0.3s ease;
cursor: pointer;
}
.color-transition {
animation: colorPulse 0.3s ease;
}
@keyframes colorPulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
`;
document.head.appendChild(style);
// 添加提示信息
colorDisplay.title = '雙擊生成隨機顏色';
// 頁面加載時加載保存的顏色
loadColor();
});
6. counter.js
// counter.js - 計數(shù)器功能實現(xiàn)
// 等待DOM完全加載后執(zhí)行
document.addEventListener('DOMContentLoaded', function() {
// 獲取DOM元素
const decreaseBtn = document.getElementById('decrease'); // 減少按鈕
const increaseBtn = document.getElementById('increase'); // 增加按鈕
const resetBtn = document.getElementById('reset'); // 重置按鈕
const countSpan = document.getElementById('count'); // 顯示計數(shù)的span元素
// 計數(shù)變量
let count = 0;
// 從localStorage加載保存的計數(shù)
function loadCount() {
// 嘗試從localStorage獲取保存的計數(shù)值
const savedCount = localStorage.getItem('count');
if (savedCount !== null) {
// 如果有保存的值,更新count和顯示
count = parseInt(savedCount);
updateDisplay();
}
}
// 保存計數(shù)到localStorage
function saveCount() {
localStorage.setItem('count', count.toString());
}
// 更新顯示
function updateDisplay() {
// 更新顯示的數(shù)字
countSpan.textContent = count;
// 根據(jù)數(shù)值設(shè)置顏色
if (count > 0) {
countSpan.style.color = 'green';
} else if (count < 0) {
countSpan.style.color = 'red';
} else {
countSpan.style.color = 'black';
}
}
// 減少計數(shù)
function decrease() {
// 計數(shù)減1
count--;
// 保存并更新顯示
saveCount();
updateDisplay();
// 添加動畫效果
addAnimation('decrease');
}
// 增加計數(shù)
function increase() {
// 計數(shù)加1
count++;
// 保存并更新顯示
saveCount();
updateDisplay();
// 添加動畫效果
addAnimation('increase');
}
// 重置計數(shù)
function reset() {
// 重置為0
count = 0;
// 保存并更新顯示
saveCount();
updateDisplay();
// 添加動畫效果
addAnimation('reset');
}
// 添加動畫效果
function addAnimation(type) {
// 移除之前的動畫類
countSpan.classList.remove('animate-increase', 'animate-decrease', 'animate-reset');
// 添加新的動畫類
countSpan.classList.add(`animate-${type}`);
// 動畫結(jié)束后移除類
setTimeout(() => {
countSpan.classList.remove(`animate-${type}`);
}, 500);
}
// 添加事件監(jiān)聽器
decreaseBtn.addEventListener('click', decrease);
increaseBtn.addEventListener('click', increase);
resetBtn.addEventListener('click', reset);
// 添加鍵盤事件支持
document.addEventListener('keydown', function(e) {
// 根據(jù)按鍵執(zhí)行相應(yīng)操作
switch(e.key) {
case 'ArrowDown':
case '-':
decrease();
break;
case 'ArrowUp':
case '+':
increase();
break;
case 'r':
case 'R':
reset();
break;
}
});
// 添加動畫樣式
const style = document.createElement('style');
style.textContent = `
@keyframes increase {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
@keyframes decrease {
0% { transform: scale(1); }
50% { transform: scale(0.8); }
100% { transform: scale(1); }
}
@keyframes reset {
0% { transform: rotate(0); }
100% { transform: rotate(360deg); }
}
.animate-increase {
animation: increase 0.5s ease;
}
.animate-decrease {
animation: decrease 0.5s ease;
}
.animate-reset {
animation: reset 0.5s ease;
}
`;
document.head.appendChild(style);
// 頁面加載時加載保存的計數(shù)
loadCount();
});
7. todo.js
// todo.js - 待辦事項列表功能實現(xiàn)
// 等待DOM完全加載后執(zhí)行
document.addEventListener('DOMContentLoaded', function() {
// 獲取DOM元素
const todoInput = document.getElementById('todo-input'); // 輸入框
const addButton = document.getElementById('add-todo'); // 添加按鈕
const todoList = document.getElementById('todo-list'); // 待辦事項列表
// 存儲待辦事項的數(shù)組
let todos = [];
// 從localStorage加載保存的待辦事項
function loadTodos() {
// 嘗試從localStorage獲取數(shù)據(jù)
const savedTodos = localStorage.getItem('todos');
if (savedTodos) {
// 如果有數(shù)據(jù),解析JSON字符串并更新todos數(shù)組
todos = JSON.parse(savedTodos);
// 渲染待辦事項列表
renderTodos();
}
}
// 保存待辦事項到localStorage
function saveTodos() {
// 將todos數(shù)組轉(zhuǎn)換為JSON字符串并保存
localStorage.setItem('todos', JSON.stringify(todos));
}
// 渲染待辦事項列表
function renderTodos() {
// 清空列表
todoList.innerHTML = '';
// 遍歷todos數(shù)組,創(chuàng)建并添加列表項
todos.forEach((todo, index) => {
// 創(chuàng)建列表項
const li = document.createElement('li');
li.className = 'todo-item';
// 創(chuàng)建復(fù)選框
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = todo.completed;
// 添加復(fù)選框改變事件
checkbox.addEventListener('change', () => toggleTodo(index));
// 創(chuàng)建文本span
const span = document.createElement('span');
span.textContent = todo.text;
// 如果待辦事項已完成,添加completed類
if (todo.completed) {
span.classList.add('completed');
}
// 創(chuàng)建刪除按鈕
const deleteButton = document.createElement('button');
deleteButton.textContent = '刪除';
deleteButton.style.marginLeft = 'auto';
// 添加刪除按鈕點擊事件
deleteButton.addEventListener('click', () => deleteTodo(index));
// 將元素添加到列表項
li.appendChild(checkbox);
li.appendChild(span);
li.appendChild(deleteButton);
// 將列表項添加到列表
todoList.appendChild(li);
});
}
// 添加新的待辦事項
function addTodo() {
// 獲取輸入的文本并去除首尾空格
const text = todoInput.value.trim();
// 如果文本不為空
if (text) {
// 創(chuàng)建新的待辦事項對象
const todo = {
text: text,
completed: false
};
// 添加到數(shù)組
todos.push(todo);
// 清空輸入框
todoInput.value = '';
// 保存并重新渲染
saveTodos();
renderTodos();
}
}
// 刪除待辦事項
function deleteTodo(index) {
// 從數(shù)組中刪除指定索引的項
todos.splice(index, 1);
// 保存并重新渲染
saveTodos();
renderTodos();
}
// 切換待辦事項的完成狀態(tài)
function toggleTodo(index) {
// 切換指定索引項的completed狀態(tài)
todos[index].completed = !todos[index].completed;
// 保存并重新渲染
saveTodos();
renderTodos();
}
// 添加事件監(jiān)聽器
// 點擊添加按鈕時添加待辦事項
addButton.addEventListener('click', addTodo);
// 在輸入框中按回車鍵時添加待辦事項
todoInput.addEventListener('keypress', function(e) {
// 如果按下的是回車鍵(keyCode 13)
if (e.keyCode === 13) {
addTodo();
}
});
// 頁面加載時加載保存的待辦事項
loadTodos();
});
8. form.js
// form.js - 表單驗證功能實現(xiàn)
// 等待DOM完全加載后執(zhí)行
document.addEventListener('DOMContentLoaded', function() {
// 獲取DOM元素
const form = document.getElementById('validation-form'); // 表單
const username = document.getElementById('username'); // 用戶名輸入框
const email = document.getElementById('email'); // 郵箱輸入框
const password = document.getElementById('password'); // 密碼輸入框
const usernameError = document.getElementById('username-error'); // 用戶名錯誤提示
const emailError = document.getElementById('email-error'); // 郵箱錯誤提示
const passwordError = document.getElementById('password-error'); // 密碼錯誤提示
// 驗證規(guī)則對象
const validationRules = {
// 用戶名驗證規(guī)則
username: {
test: (value) => {
return value.length >= 3 && value.length <= 10;
},
message: '用戶名長度必須在3-10個字符之間'
},
// 郵箱驗證規(guī)則
email: {
test: (value) => {
// 使用正則表達式驗證郵箱格式
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(value);
},
message: '請輸入有效的郵箱地址'
},
// 密碼驗證規(guī)則
password: {
test: (value) => {
// 密碼至少6個字符,包含至少一個數(shù)字和一個字母
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,}$/;
return passwordRegex.test(value);
},
message: '密碼至少6個字符,必須包含數(shù)字和字母'
}
};
// 驗證單個字段
function validateField(field, errorElement) {
// 獲取字段值并去除首尾空格
const value = field.value.trim();
// 獲取字段名
const fieldName = field.id;
// 獲取對應(yīng)的驗證規(guī)則
const rule = validationRules[fieldName];
// 如果輸入為空
if (!value) {
showError(errorElement, '此字段不能為空');
return false;
}
// 使用驗證規(guī)則測試值
if (!rule.test(value)) {
showError(errorElement, rule.message);
return false;
}
// 驗證通過,清除錯誤提示
clearError(errorElement);
return true;
}
// 顯示錯誤信息
function showError(element, message) {
element.textContent = message;
element.style.display = 'block';
// 添加抖動動畫
element.classList.add('error-shake');
setTimeout(() => {
element.classList.remove('error-shake');
}, 500);
}
// 清除錯誤信息
function clearError(element) {
element.textContent = '';
element.style.display = 'none';
}
// 添加實時驗證
username.addEventListener('input', () => validateField(username, usernameError));
email.addEventListener('input', () => validateField(email, emailError));
password.addEventListener('input', () => validateField(password, passwordError));
// 添加表單提交事件處理
form.addEventListener('submit', function(e) {
// 阻止表單默認提交行為
e.preventDefault();
// 驗證所有字段
const isUsernameValid = validateField(username, usernameError);
const isEmailValid = validateField(email, emailError);
const isPasswordValid = validateField(password, passwordError);
// 如果所有字段都驗證通過
if (isUsernameValid && isEmailValid && isPasswordValid) {
// 創(chuàng)建成功提示
showSuccessMessage();
// 重置表單
form.reset();
// 清除所有錯誤提示
clearError(usernameError);
clearError(emailError);
clearError(passwordError);
}
});
// 顯示成功消息
function showSuccessMessage() {
// 創(chuàng)建成功消息元素
const successMessage = document.createElement('div');
successMessage.textContent = '表單提交成功!';
successMessage.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background-color: #4caf50;
color: white;
padding: 15px 25px;
border-radius: 4px;
animation: slideIn 0.5s ease;
`;
// 添加到頁面
document.body.appendChild(successMessage);
// 3秒后移除消息
setTimeout(() => {
successMessage.style.animation = 'slideOut 0.5s ease';
setTimeout(() => {
document.body.removeChild(successMessage);
}, 500);
}, 3000);
}
// 添加動畫樣式
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes slideOut {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(100%); opacity: 0; }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px); }
75% { transform: translateX(10px); }
}
.error-shake {
animation: shake 0.5s ease;
color: #f44336;
}
#username-error, #email-error, #password-error {
font-size: 0.8em;
margin-top: -8px;
margin-bottom: 10px;
display: none;
}
`;
document.head.appendChild(style);
});
綜合練習(xí)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在線筆記本 - JavaScript綜合練習(xí)</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
background-color: #f0f2f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.notes-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.note {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
position: relative;
}
.note:hover {
transform: translateY(-5px);
}
.note-title {
font-size: 1.2em;
margin-bottom: 10px;
color: #1890ff;
}
.note-content {
margin-bottom: 15px;
color: #333;
}
.note-footer {
display: flex;
justify-content: space-between;
align-items: center;
color: #999;
font-size: 0.9em;
}
.note-actions {
display: flex;
gap: 10px;
}
button {
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
button.delete {
background-color: #ff4d4f;
}
button.delete:hover {
background-color: #ff7875;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #fff;
padding: 20px;
border-radius: 8px;
width: 90%;
max-width: 500px;
position: relative;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from { transform: translateY(-100px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.modal-close {
position: absolute;
top: 10px;
right: 10px;
font-size: 24px;
cursor: pointer;
color: #999;
}
input[type="text"], textarea {
width: 100%;
padding: 8px;
margin: 10px 0;
border: 1px solid #d9d9d9;
border-radius: 4px;
}
textarea {
height: 150px;
resize: vertical;
}
.search-box {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.search-box input {
flex: 1;
}
.loading {
display: none;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #1890ff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.toast {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
background-color: #52c41a;
color: white;
border-radius: 4px;
display: none;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.error {
background-color: #ff4d4f;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin: 10px 0;
}
.tag {
padding: 2px 8px;
background-color: #e6f7ff;
border-radius: 12px;
font-size: 0.9em;
color: #1890ff;
cursor: pointer;
transition: background-color 0.3s;
}
.tag:hover {
background-color: #bae7ff;
}
</style>
</head>
<body>
<div class="container">
<nav>
<button onclick="location.href='index.html'">返回首頁</button>
</nav>
<div class="header">
<h1>在線筆記本</h1>
<button id="add-note-btn">添加筆記</button>
</div>
<div class="search-box">
<input type="text" id="search-input" placeholder="搜索筆記...">
<button id="search-btn">搜索</button>
</div>
<div class="tags" id="tags-container"></div>
<div class="loading" id="loading"></div>
<div class="notes-container" id="notes-container"></div>
</div>
<!-- 添加/編輯筆記的模態(tài)框 -->
<div class="modal" id="note-modal">
<div class="modal-content">
<span class="modal-close">×</span>
<h2 id="modal-title">添加筆記</h2>
<input type="text" id="note-title-input" placeholder="筆記標題">
<textarea id="note-content-input" placeholder="筆記內(nèi)容"></textarea>
<input type="text" id="note-tags-input" placeholder="標簽(用逗號分隔)">
<button id="save-note-btn">保存</button>
</div>
</div>
<div class="toast" id="toast"></div>
<script>
// 狀態(tài)管理
const state = {
notes: [],
tags: new Set(),
currentNoteId: null,
filterTag: null
};
// DOM元素
const elements = {
notesContainer: document.getElementById('notes-container'),
modal: document.getElementById('note-modal'),
modalClose: document.querySelector('.modal-close'),
modalTitle: document.getElementById('modal-title'),
addNoteBtn: document.getElementById('add-note-btn'),
saveNoteBtn: document.getElementById('save-note-btn'),
titleInput: document.getElementById('note-title-input'),
contentInput: document.getElementById('note-content-input'),
tagsInput: document.getElementById('note-tags-input'),
searchInput: document.getElementById('search-input'),
searchBtn: document.getElementById('search-btn'),
loading: document.getElementById('loading'),
toast: document.getElementById('toast'),
tagsContainer: document.getElementById('tags-container')
};
// 工具函數(shù)
const utils = {
// 生成唯一ID
generateId: () => Date.now().toString(36) + Math.random().toString(36).substr(2),
// 格式化日期
formatDate: (date) => new Date(date).toLocaleString(),
// 顯示加載動畫
showLoading: () => elements.loading.style.display = 'block',
// 隱藏加載動畫
hideLoading: () => elements.loading.style.display = 'none',
// 顯示提示消息
showToast: (message, isError = false) => {
elements.toast.textContent = message;
elements.toast.style.display = 'block';
elements.toast.className = `toast ${isError ? 'error' : ''}`;
setTimeout(() => elements.toast.style.display = 'none', 3000);
},
// 防抖函數(shù)
debounce: (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
};
// 筆記相關(guān)操作
const noteOperations = {
// 添加筆記
addNote: (note) => {
state.notes.unshift(note);
note.tags.forEach(tag => state.tags.add(tag));
localStorage.setItem('notes', JSON.stringify(state.notes));
renderNotes();
renderTags();
},
// 編輯筆記
editNote: (id, updates) => {
const index = state.notes.findIndex(note => note.id === id);
if (index !== -1) {
state.notes[index] = { ...state.notes[index], ...updates };
localStorage.setItem('notes', JSON.stringify(state.notes));
renderNotes();
renderTags();
}
},
// 刪除筆記
deleteNote: (id) => {
state.notes = state.notes.filter(note => note.id !== id);
localStorage.setItem('notes', JSON.stringify(state.notes));
renderNotes();
renderTags();
},
// 搜索筆記
searchNotes: (query) => {
const searchTerm = query.toLowerCase();
return state.notes.filter(note => {
const matchesSearch = note.title.toLowerCase().includes(searchTerm) ||
note.content.toLowerCase().includes(searchTerm);
const matchesTag = !state.filterTag || note.tags.includes(state.filterTag);
return matchesSearch && matchesTag;
});
}
};
// 渲染函數(shù)
function renderNotes(notes = state.notes) {
elements.notesContainer.innerHTML = '';
notes.forEach(note => {
const noteElement = document.createElement('div');
noteElement.className = 'note';
noteElement.innerHTML = `
<h3 class="note-title">${note.title}</h3>
<div class="note-content">${note.content}</div>
<div class="tags">
${note.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div>
<div class="note-footer">
<span>${utils.formatDate(note.date)}</span>
<div class="note-actions">
<button onclick="openEditNoteModal('${note.id}')">編輯</button>
<button class="delete" onclick="deleteNoteWithConfirm('${note.id}')">刪除</button>
</div>
</div>
`;
elements.notesContainer.appendChild(noteElement);
// 添加動畫效果
setTimeout(() => noteElement.style.opacity = '1', 10);
});
}
function renderTags() {
elements.tagsContainer.innerHTML = '';
Array.from(state.tags).forEach(tag => {
const tagElement = document.createElement('span');
tagElement.className = `tag ${state.filterTag === tag ? 'active' : ''}`;
tagElement.textContent = tag;
tagElement.onclick = () => filterByTag(tag);
elements.tagsContainer.appendChild(tagElement);
});
}
// 模態(tài)框操作
function openAddNoteModal() {
state.currentNoteId = null;
elements.modalTitle.textContent = '添加筆記';
elements.titleInput.value = '';
elements.contentInput.value = '';
elements.tagsInput.value = '';
elements.modal.style.display = 'flex';
}
function openEditNoteModal(id) {
const note = state.notes.find(note => note.id === id);
if (note) {
state.currentNoteId = id;
elements.modalTitle.textContent = '編輯筆記';
elements.titleInput.value = note.title;
elements.contentInput.value = note.content;
elements.tagsInput.value = note.tags.join(', ');
elements.modal.style.display = 'flex';
}
}
function closeModal() {
elements.modal.style.display = 'none';
}
// 事件處理函數(shù)
function saveNote() {
const title = elements.titleInput.value.trim();
const content = elements.contentInput.value.trim();
const tags = elements.tagsInput.value
.split(',').map(tag => tag.trim())
.filter(tag => tag.length > 0);
if (!title || !content) {
utils.showToast('標題和內(nèi)容不能為空', true);
return;
}
const note = {
title,
content,
tags,
date: new Date().toISOString()
};
if (state.currentNoteId) {
noteOperations.editNote(state.currentNoteId, note);
utils.showToast('筆記已更新');
} else {
note.id = utils.generateId();
noteOperations.addNote(note);
utils.showToast('筆記已添加');
}
closeModal();
}
function deleteNoteWithConfirm(id) {
if (confirm('確定要刪除這個筆記嗎?')) {
noteOperations.deleteNote(id);
utils.showToast('筆記已刪除');
}
}
function filterByTag(tag) {
state.filterTag = state.filterTag === tag ? null : tag;
renderNotes(noteOperations.searchNotes(elements.searchInput.value));
renderTags();
}
// 搜索功能
const handleSearch = utils.debounce(() => {
const searchResults = noteOperations.searchNotes(elements.searchInput.value);
renderNotes(searchResults);
}, 300);
// 初始化
function init() {
// 加載保存的筆記
const savedNotes = localStorage.getItem('notes');
if (savedNotes) {
state.notes = JSON.parse(savedNotes);
state.notes.forEach(note => {
note.tags.forEach(tag => state.tags.add(tag));
});
}
// 渲染筆記和標簽
renderNotes();
renderTags();
// 事件監(jiān)聽
elements.addNoteBtn.onclick = openAddNoteModal;
elements.modalClose.onclick = closeModal;
elements.saveNoteBtn.onclick = saveNote;
elements.searchInput.oninput = handleSearch;
elements.searchBtn.onclick = handleSearch;
// 點擊模態(tài)框外部關(guān)閉
window.onclick = (event) => {
if (event.target === elements.modal) {
closeModal();
}
};
// 鍵盤事件
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && elements.modal.style.display === 'flex') {
closeModal();
}
});
}
// 啟動應(yīng)用
init();
</script>
</body>
</html>總結(jié)
到此這篇關(guān)于JavaScript練習(xí)語法及建議總結(jié)大全的文章就介紹到這了,更多相關(guān)JS練習(xí)語法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
鼠標選擇動態(tài)改變網(wǎng)頁背景顏色的JS代碼
這篇文章主要介紹了鼠標選擇動態(tài)改變網(wǎng)頁背景顏色的JS代碼,有需要的朋友可以參考一下2013-12-12
layui監(jiān)聽下拉選框選中值變化的方法(包含監(jiān)聽普通下拉選框)
今天小編大家分享一篇layui監(jiān)聽下拉選框選中值變化的方法(包含監(jiān)聽普通下拉選框),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
JS實現(xiàn)給json數(shù)組動態(tài)賦值的方法示例
這篇文章主要介紹了JS實現(xiàn)給json數(shù)組動態(tài)賦值的方法,結(jié)合實例形式分析了javascript針對json數(shù)組的遍歷、賦值等常用操作技巧,需要的朋友可以參考下2017-07-07

