JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
$$demo <div class="operators"> <input id="name" type="text" placeholder="学生姓名" /> <input id="score" type="number" placeholder="分数" /> <button id="submit" onclick="controller.submit()">确认添加</button> <button id="cancel" onclick="controller.cancel()" hidden>取消编辑</button> </div> <table id="table"> <!-- <tr> <th>姓名</th> <th>分数</th> <th>操作</th> </tr> --> </table> <script> // Model: start // 数据管理 const model = { init() { this.loadStudents() }, students: [ { name: "小明", score: 56 }, { name: "鸣人", score: 80 }, { name: "路飞", score: 70 }, ], // 编辑的下标 _editIdx: null, get editIdx() { return this._editIdx }, set editIdx(value) { this._editIdx = value
// 映射模型
view.render()
},
get isEdit() {
return this._editIdx !== null
},
set isEdit(value) {
if (value) {
console.error("不允许直接设置 isEdit 为 true")
return
} else {
this.editIdx = null
}
},
get editedStudent() {
return model.students[model.editIdx]
},
loadStudents() {
// 尝试读取数据
if (localStorage.students) {
this.students = JSON.parse(localStorage.students)
}
view.render()
},
saveStudents() {
// 保存数据
localStorage.students = JSON.stringify(this.students)
view.render()
},
addStudent(name, score) {
this.students.push({
name,
score,
})
// 更新后保存数据
this.saveStudents()
},
editStudent(name, score) {
this.students[this.editIdx] = {
name,
score,
}
// 更新后保存数据
this.saveStudents()
},
removeStudent(index) {
this.students.splice(index, 1)
// 更新后保存数据
this.saveStudents()
},
}
// Model: end
// View: start
const view = {
render() {
// 映射模型数据到页面
this.renderTable()
this.renderOperators()
},
renderTable() {
// 表格
let html = `
<tr>
<th>姓名</th>
<th>分数</th>
<th>操作</th>
</tr>
`
for (const index in model.students) {
html += `
<tr>
<td>${model.students[index].name}</td>
<td>${model.students[index].score}</td>
<td>
<button onclick="controller.edit(${index})">
修改
</button>
<button onclick="controller.remove(${index})">
删除
</button>
</td>
</tr>`
}
document.getElementById("table").innerHTML = html
},
renderOperators() {
// 输入框和按钮
if (model.isEdit) {
document.getElementById("name").value = model.editedStudent.name
document.getElementById("score").value =
model.editedStudent.score
document.getElementById("submit").textContent = "确认编辑"
document.getElementById("cancel").hidden = false
} else {
document.getElementById("submit").textContent = "确认添加"
document.getElementById("name").value = ""
document.getElementById("score").value = ""
document.getElementById("cancel").hidden = true
}
},
}
// View: end
// Controller: start
const controller = {
submit() {
// 确认
const nameEl = document.getElementById("name")
const scoreEl = document.getElementById("score")
if (nameEl.value === "") {
alert("请输入姓名")
return
}
if (scoreEl.value === "") {
alert("请输入分数")
return
}
if (model.isEdit) {
model.editStudent(nameEl.value, scoreEl.value)
model.isEdit = false
} else {
model.addStudent(nameEl.value, scoreEl.value)
}
},
cancel() {
// 取消编辑
model.isEdit = false
},
edit(index) {
// 编辑学生
model.editIdx = index
},
remove(index) {
// 删除学生
const isDelete = confirm("确认删除吗?")
if (isDelete) {
model.removeStudent(index)
}
},
}
// Controller: end
model.init()
</script> <style> body { --primary-color: #eee; }
table {
border-collapse: collapse;
margin: 10px 0;
}
th {
color: white;
background-color: teal;
}
th,
td {
border: 4px solid var(--primary-color);
padding: 10px 60px;
text-align: center;
}
button {
padding: 5px 20px;
cursor: pointer;
background-color: var(--primary-color);
border: none;
}
button:hover {
background-color: #ddd;
}
input {
padding: 5px 10px;
border: 2px solid var(--primary-color);
outline: none;
}
.operators {
display: flex;
gap: 10px;
}
</style>
$$ $$answer
<div class="operators">
<input id="name" type="text" placeholder="学生姓名" />
<input id="score" type="number" placeholder="分数" />
<button id="submit" onclick="controller.submit()">确认添加</button>
<button id="cancel" onclick="controller.cancel()" hidden>取消编辑</button>
</div>
<table id="table">
<!-- <tr>
<th>姓名</th>
<th>分数</th>
<th>操作</th>
</tr> -->
</table>
<script>
// Model: start
// 数据管理
const model = {
init() {
this.loadStudents()
},
students: [
{ name: "小明", score: 56 },
{ name: "鸣人", score: 80 },
{ name: "路飞", score: 70 },
],
// 编辑的下标
_editIdx: null,
get editIdx() {
return this._editIdx
},
set editIdx(value) {
this._editIdx = value
// 映射模型
view.render()
},
get isEdit() {
return this._editIdx !== null
},
set isEdit(value) {
if (value) {
console.error("不允许直接设置 isEdit 为 true")
return
} else {
this.editIdx = null
}
},
get editedStudent() {
return model.students[model.editIdx]
},
loadStudents() {
// 尝试读取数据
if (localStorage.students) {
this.students = JSON.parse(localStorage.students)
}
view.render()
},
saveStudents() {
// 保存数据
localStorage.students = JSON.stringify(this.students)
view.render()
},
addStudent(name, score) {
this.students.push({
name,
score,
})
// 更新后保存数据
this.saveStudents()
},
editStudent(name, score) {
this.students[this.editIdx] = {
name,
score,
}
// 更新后保存数据
this.saveStudents()
},
removeStudent(index) {
this.students.splice(index, 1)
// 更新后保存数据
this.saveStudents()
},
}
// Model: end
// View: start
const view = {
render() {
// 映射模型数据到页面
this.renderTable()
this.renderOperators()
},
renderTable() {
// 表格
let html = `
<tr>
<th>姓名</th>
<th>分数</th>
<th>操作</th>
</tr>
`
for (const index in model.students) {
html += `
<tr>
<td>${model.students[index].name}</td>
<td>${model.students[index].score}</td>
<td>
<button onclick="controller.edit(${index})">
修改
</button>
<button onclick="controller.remove(${index})">
删除
</button>
</td>
</tr>`
}
document.getElementById("table").innerHTML = html
},
renderOperators() {
// 输入框和按钮
if (model.isEdit) {
document.getElementById("name").value = model.editedStudent.name
document.getElementById("score").value =
model.editedStudent.score
document.getElementById("submit").textContent = "确认编辑"
document.getElementById("cancel").hidden = false
} else {
document.getElementById("submit").textContent = "确认添加"
document.getElementById("name").value = ""
document.getElementById("score").value = ""
document.getElementById("cancel").hidden = true
}
},
}
// View: end
// Controller: start
const controller = {
submit() {
// 确认
const nameEl = document.getElementById("name")
const scoreEl = document.getElementById("score")
if (nameEl.value === "") {
alert("请输入姓名")
return
}
if (scoreEl.value === "") {
alert("请输入分数")
return
}
if (model.isEdit) {
model.editStudent(nameEl.value, scoreEl.value)
model.isEdit = false
} else {
model.addStudent(nameEl.value, scoreEl.value)
}
},
cancel() {
// 取消编辑
model.isEdit = false
},
edit(index) {
// 编辑学生
model.editIdx = index
},
remove(index) {
// 删除学生
const isDelete = confirm("确认删除吗?")
if (isDelete) {
model.removeStudent(index)
}
},
}
// Controller: end
model.init()
</script>
<style>
body {
--primary-color: #eee;
}
table {
border-collapse: collapse;
margin: 10px 0;
}
th {
color: white;
background-color: teal;
}
th,
td {
border: 4px solid var(--primary-color);
padding: 10px 60px;
text-align: center;
}
button {
padding: 5px 20px;
cursor: pointer;
background-color: var(--primary-color);
border: none;
}
button:hover {
background-color: #ddd;
}
input {
padding: 5px 10px;
border: 2px solid var(--primary-color);
outline: none;
}
.operators {
display: flex;
gap: 10px;
}
</style>
$$
本实例应用了 MVC 模式。