什么是数据驱动?
数据驱动视图是指通过数据来驱动页面的显示和行为,使得页面的展示和交互元素可以根据数据的变化而自动更新。这种开发模式通常使用前端框架或库来实现,例如Vue.js、React等。简单来说,其实就是通过操作原始数据来进行显示更新页面,通过更改原始数据重新渲染页面。而并非使用dom操作。
数据驱动应用场景
数据驱动应用场景非常广泛,比如,在管理系统、电子商务平台、社交网络等复杂应用中,页面上的数据和用户交互元素需要频繁地更新和响应,数据驱动视图的开发模式能够极大地提高开发效率,并且使得页面的维护和拓展更加容易。
数据驱动案例(学生管理系统)
下面,我们来通过学生管理系统深入了解一下数据驱动,这个项目涉及到了增删改的操作,全部用的是数据驱动。
页面总体效果
页面结构 :
html与页面布局
css样式:
通过css来对页面进行美化和装饰
数据渲染:
这个部分用于直接渲染页面的基本结构,其中用于数据驱动的事思想,这里是直接封装了一个函数
// 渲染视图封装成方法,可以复用
function render() {
$$('#container').innerHTML = list.map((item, index) => {
return `
<tr>
<td>${item.id}</td>
<td>
<input class="user-name-input" style="display: ${item.isEdit ? '' : 'none'};" value="${item.name}" />
<span style="display: ${item.isEdit ? 'none' : ''};">${item.name}</span>
</td>
<td>${item.password}</td>
<td>${item.email}</td>
<td>
<button style="background: ${item.isEdit ? 'green' : 'blue'};" class="edit" data-id="${item.id}" data-type="${item.isEdit ? 'ok' : 'edit'}" data-index="${index}">${item.isEdit ? '完成' : '编辑'}</button>
<button class="del" data-id="${item.id}">删除</button>
</td>
</tr>
`
}).join('')
handleDeleteStudent() // 删除学生数据
handleEditStudent() // 编辑学生数据
handleSetStorage('list', list) // 注意:删除操作执行完后再执行本地存储操作
}
render()
删除部分:
这里是封装了一个函数的用于调用方便我们去调用,去实时的实现删除功能
重置按钮:
这里的实现思路的话,是用户输入文本框的文本删的麻烦,可以点击重置按钮,可以一键清空用户输入的文字
添加部分:
这里实现用户输入的数据可以添加在页面上,以及给该文本框实现一个成功添加后清空输入框里面的数据,下面是实现思路
本地存储:
实现刷新不会使用户输入的数据丢失,所以这块我们就用到了本地存储
编辑功能:
我们为了实现用户想改输入的数据时,设置了修改的按钮,这样可以大大有用户的体验
html5的本地存储里只能存字符串,所以如果存储的数据是引用数据要先转化为字符串再存进去
全代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学籍管理系统</title>
<style>
.red {
font-size: 12px;
color: red;
}
.none {
display: none;
}
.inline {
display: '';
}
</style>
</head>
<body>
<h1>学生管理系统</h1>
<label for=""><span>*</span>用户名:<input type="text" id="userName"></label>
<br />
<span class="valid-user red none">请输入正确的用户名</span>
<br />
<label for=""><span>*</span>密码:<input type="text" id="userPassword"></label>
<br />
<span class="valid-pwd red none">请输入正确的密码</span>
<br />
<label for=""><span>*</span>邮箱:<input type="text" id="userEmail"></label>
<br />
<span class="valid-email red none">请输入正确的邮箱</span>
<br />
<button id="add">添加</button>
<button id="reset">重置</button>
<table border="1">
<thead>
<tr>
<td>编号</td>
<td>姓名</td>
<td>密码</td>
<td>邮箱</td>
<td>操作</td>
</tr>
</thead>
<tbody id="container">
</tbody>
</table>
<script>
window.onload = function () { // 获取DOM对象的工具方法
function $$(selector, all = false) {
if(typeof selector !== 'string') return
return all ? document.querySelectorAll(selector) : document.querySelector(selector)
}
// 清空方法
function handleClear() {
userName.value = ''
userPassword.value = ''
userEmail.value = ''
}
const userName = $$('#userName')
const userPassword = $$('#userPassword')
const userEmail = $$('#userEmail')
const emailRegExp = /^[\w-]+(\.[\w-]+)*@([a-zA-Z0-9-]+\.)+(com|org|net|edu|gov|co|io|info|biz|me|us)$/
// 1. 写页面结构,以及涉及到布局的样式
// 2. 先写表格数据渲染
let list = handleGetStorage('list').length ? handleGetStorage('list') : [
{ id: 1, name: '张三1', password: '666', email: '11@qq.com', isEdit: false },
{ id: 2, name: '张三2', password: '666', email: '11@qq.com', isEdit: false },
{ id: 3, name: '张三3', password: '666', email: '11@qq.com', isEdit: false },
]
// 渲染视图封装成方法,可以复用
function render() {
$$('#container').innerHTML = list.map((item, index) => {
return `
<tr>
<td>${item.id}</td>
<td>
<input class="user-name-input" style="display: ${item.isEdit ? '' : 'none'};" value="${item.name}" />
<span style="display: ${item.isEdit ? 'none' : ''};">${item.name}</span>
</td>
<td>${item.password}</td>
<td>${item.email}</td>
<td>
<button style="background: ${item.isEdit ? 'green' : 'blue'};" class="edit" data-id="${item.id}" data-type="${item.isEdit ? 'ok' : 'edit'}" data-index="${index}">${item.isEdit ? '完成' : '编辑'}</button>
<button class="del" data-id="${item.id}">删除</button>
</td>
</tr>
`
}).join('')
handleDeleteStudent() // 删除学生数据
handleEditStudent() // 编辑学生数据
handleSetStorage('list', list) // 注意:删除操作执行完后再执行本地存储操作
}
render()
// 3. 写表单结构和布局样式
// 4. 实现表格删除功能
function handleDeleteStudent() {
$$('.del', true).forEach(el => {
el.addEventListener('click', function () {
if (confirm('此操作将永久删除该文件,是否继续?')) {
list = list.filter(v => v.id !== +this.dataset.id)
// 渲染视图
render()
}
})
})
}
// 5. 实现表单重置按钮功能
$$('#reset').onclick = function () {
handleClear()
}
// 6. 实现表单添加功能
$$('#add').onclick = function () {
const validUser = $$('.valid-user')
const valiePwd = $$('.valid-pwd')
const validEmail = $$('.valid-email')
let flag = true // 因为要根据多个字段的校验结果控制return,所以给一个全局开关,默认为true通过
// 7. 实现表单校验功能
if (!userName.value) { // 用户名校验不通过,直接退出
validUser.classList.remove('none')
validUser.classList.add('inline')
flag = false
} else {
validUser.classList.add('none')
validUser.classList.remove('inline')
}
if (!userPassword.value) { // 密码校验不通过,直接退出
valiePwd.classList.remove('none')
valiePwd.classList.add('inline')
flag = false
} else {
valiePwd.classList.add('none')
valiePwd.classList.remove('inline')
}
if (!userEmail.value || !emailRegExp.test(userEmail.value)) { // 邮箱校验不通过,直接退出
validEmail.classList.remove('none')
validEmail.classList.add('inline')
flag = false
} else {
validEmail.classList.add('none')
validEmail.classList.remove('inline')
}
if (!flag) { // 如果校验不通过就不执行后面代码
return false // 提前退出
}
list = [...list, {
id: list.length + 1,
name: userName.value,
password: userPassword.value,
email: userEmail.value,
}]
handleClear() // 清空表单数据
render() // 重新渲染视图/通知视图重新渲染
}
// 8. 实现本地存储功能
function handleSetStorage(key, value) {
window.localStorage.setItem(key, JSON.stringify(value))
}
function handleGetStorage(key) {
return JSON.parse(window.localStorage.getItem(key)) || []
}
// 编辑功能
function handleEditStudent() {
$$('.edit', true).forEach(el => {
el.addEventListener('click', function () {
const id = this.dataset.id
const type = this.dataset.type
const index = this.dataset.index
list.forEach(item => {
if(+id === item.id) { // 找到点击编辑按钮的当前行数据了
item.isEdit = type !== 'ok'
type === 'ok' && (item.name = $$('.user-name-input', true)[index].value)
}
})
// 渲染视图
render()
})
})
}
}
// html5的本地存储里只能存字符串,所以如果存储的数据是引用数据要先转化为字符串再存进去
const utils = {
get(key) {
return window.localStorage.getItem(key)
},
set(key, value) {
window.localStorage.setItem(key, value)
},
remove(key) {
window.localStorage.removeItem(key)
},
clear() {
window.localStorage.clear()
}
}
</script>
</body>
</html>