数据驱动实现学生管理系统

数据驱动视图的思想在Web开发中的应用

引言

随着Web技术的不断发展,前端开发模式也在不断革新。数据驱动视图(Data-Driven View)作为其中的一种重要开发范式,已经成为现代Web开发中的重要概念之一。本文将从数据驱动视图的含义、应用场景、优势以及示例项目中的具体实现等方面进行深入分析。

什么是数据驱动视图?

数据驱动视图是指通过数据来驱动页面的显示和行为,使得页面的展示和交互元素可以根据数据的变化而自动更新。这种开发模式通常使用前端框架或库来实现,例如Vue.js、React等。

应用场景

数据驱动视图的思想在各种Web应用中都有广泛的应用场景。比如,在管理系统、电子商务平台、社交网络等复杂应用中,页面上的数据和用户交互元素需要频繁地更新和响应,数据驱动视图的开发模式能够极大地提高开发效率,并且使得页面的维护和拓展更加容易。

优势

分离逻辑与视图

数据驱动视图模式可以帮助开发者更好地分离逻辑与视图,使得前端代码更加清晰、易于维护。通过将业务逻辑与界面表现分离,开发者可以专注于处理数据逻辑,而不必过多关注DOM操作。

响应式更新

采用数据驱动视图的开发模式,在数据发生变化时,相关视图会自动更新,无需手动操作DOM。这样可以极大地减少手动更新页面的工作量,提高页面渲染的效率。

更好的可测试性

由于数据驱动视图将业务逻辑与界面表现分离,使得前端代码更易于进行单元测试和集成测试。这样可以提高代码质量和可靠性。

示例项目分析

这是名为“学生管理系统”的项目,通过该项目可以添加、编辑和删除学生信息,并且学生信息列表会根据数据的增删改实时更新。该项目采用了数据驱动视图的开发模式,具体分析如下:

视图结构

首先,项目包含HTML文件,其中定义了学生管理系统的整体结构和布局。通过CSS对页面样式进行了设计和美化。

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .active {
            border: 1px solid red !important;
        }

        .father {
            width: 800px;
            background-color: #fafafa;
            height: 100vh;
            margin: 50px auto;

            & h1 {
                line-height: 70px;
                text-align: center;
            }

            .box {
                width: 660px;
                margin: 0 auto;

                &>div:first-child {
                    margin-top: 10px;
                }

                &>div {
                    margin-top: 5px;

                    & div {
                        font-size: 14px;
                        color: red;
                        display: inline-block;
                        margin-left: 75px;
                        opacity: 0;
                    }
                }

                & span {
                    display: inline-block;
                    padding-right: 10px;
                    width: 60px;
                    text-align: right;
                }

                & input {
                    width: 580px;
                    height: 40px;
                    box-sizing: border-box;
                    padding: 10px;
                    border-radius: 5px;
                    border: 1px solid #ccc;


                }
            }

            .btnc {
                width: 660px;
                margin: 0 auto;
                margin-left: 144px;
                margin-top: 5px;

                & span {
                    display: inline-block;
                    padding: 10px;
                    font-size: 15px;
                    color: #fff;
                    border-radius: 5px;
                    cursor: pointer;
                }

                .add {
                    background-color: #66c13a;
                }

                .emply {
                    background-color: #419cff;
                    margin-left: 10px;
                }
            }

            & table {
                margin: 10px auto;

                & tr {
                    background-color: #fff;
                    border-bottom: 1px solid #444;
                    line-height: 45px;

                    & td {
                        font-size: 14px;
                        width: 150px;

                        .trInp {
                            width: 70%;
                        }

                        .enter {
                            background-color: #419cff;
                        }

                        & span {
                            display: inline-block;
                            width: 40px;
                            background-color: #419cff;
                            height: 23px;
                            text-align: center;
                            color: #fff;
                            font-size: 12px;
                            cursor: pointer;
                            line-height: 23px;
                            border-radius: 5px;
                        }

                        & span:last-child {
                            background-color: #f36c6c;
                            margin-left: 5px;
                        }
                    }

                    & td:nth-child(1) {
                        width: 70px;
                        text-align: center;
                    }
                }
            }
        }
    </style>
<div class="father">
        <h1>学生管理系统</h1>
        <div class="box">
            <div class="username">
                <span>用户名</span>
                <input type="text" placeholder="请输入6位以上的用户名">
                <div>请输入用户名</div>
            </div>
            <div class="password">
                <span>密码</span>
                <input type="password" placeholder="请输入6位以上的密码">
                <div>请输入密码</div>
            </div>
            <div class="email">
                <span>邮箱</span>
                <input type="email" placeholder="请输入正确格式的邮箱地址">
                <div>请输入邮箱地址</div>
            </div>
        </div>
        <div class="btnc">
            <span class="add">添加</span>
            <span class="emply">重置</span>
        </div>
        <table cellspacing="0">
            <thead>
                <tr>
                    <td>编号</td>
                    <td>姓名</td>
                    <td>密码</td>
                    <td>邮箱</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
    </div>

数据处理

该项目通过JavaScript实现了数据的处理和页面的渲染。在JavaScript中,数据的增删改操作会触发页面视图的更新,通过封装渲染函数和事件监听器实现数据与视图的双向绑定。

//添加功能
 $$('.add').onclick = function () {
                let flag = true // 因为要根据多个字段的校验结果控制return,所以给一个全局开关,默认为true通过
                var emailValue = $$(".email input").value;
                if ($$(".username input").value.length < 2) {
                    emplyInputF('username')
                    flag = false
                }
                if ($$(".password input").value.length < 5) {
                    emplyInputF('password')
                    flag = false
                }
                if (!emailRegExp.test(emailValue)) {
                    emplyInputF('email')
                    flag = false
                }
                if (!flag) { // 如果校验不通过就不执行后面代码
                    return false // 提前退出
                }
                // 添加数据
                list = [...list, {
                    id: list.length + 1,
                    name: userName.value,
                    password: userPassword.value,
                    email: userEmail.value,
                    isEdit: false,
                    isDeleted: false
                }]
                handleClear() // 清空表单数据
                render(list) // 重新渲染视图/通知视图重新渲染
            }
//删除功能
  function handleDeleteStudent() {
                $$('.del', true).forEach(el => {
                    el.addEventListener('click', function () {
                        if (confirm('此操作将永久删除该文件,是否继续?')) {
                            list.map(v => {
                                if (v.id === +this.dataset.id) {
                                    // 将数据的是否删除属性改为true,保留数据的完整
                                    v.isDeleted = true;
                                }
                            })
                            // 渲染视图
                            render(list)
                        }
                    })
                })
            }
 // 编辑功能
            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) {
                                if (type === 'ok') { // 如果点击的是完成按钮
                                    // 第一步:拿到修改后的值
                                    const name = $$('.user-name-input', true)[index].value
                                    const pass = $$('.user-pass-input', true)[index].value
                                    const email = $$('.user-email-input', true)[index].value
                                    // 第二步:在原数组里通过id找到当前行的数据,把修改后的值重新赋值
                                    if (name.length < 2 || pass.length < 5 || !emailRegExp.test(email)) {
                                        alert("格式错误,编辑失败")
                                    } else {
                                        item.name = name
                                        item.password = pass
                                        item.email = email
                                        item.isEdit = false
                                    }
                                }
                                else { // 点击的是编辑按钮
                                    item.isEdit = true
                                }
                            }
                        })
                        // 渲染视图
                        render(list)
                    })
                })
            }

实时更新

当数据发生变化时,页面会自动更新学生信息列表,无需手动操作DOM。这样提高了用户体验,同时降低了开发者的工作量。

let list = handleGetStorage('list').length ? handleGetStorage('list') : [
                { id: 1, name: 'zhong333', password: '123456', email: 'zhong333@qq.com', isEdit: false, isDeleted: false },
            ]
function render(data) {
                // 过滤是否删除属性为true的数据
                data = data.filter(item => item.isDeleted === false)
                $$('tbody').innerHTML = data.map((item, index) => {
                    return `
                    <tr>
                        <td>${item.id}</td>
                        <td>
                            <input class="user-name-input trInp" style="display: ${item.isEdit ? '' : 'none'};" value="${item.name}" />
                            <div style="display: ${item.isEdit ? 'none' : ''};">${item.name}</div>
                        </td>
                        <td>
                            <input class="user-pass-input trInp" style="display: ${item.isEdit ? '' : 'none'};" value="${item.password}" />
                            <div style="display: ${item.isEdit ? 'none' : ''};">${item.password}</div>    
                        </td>
                        <td>
                            <input class="user-email-input trInp" style="display: ${item.isEdit ? '' : 'none'};" value="${item.email}" />
                            <div style="display: ${item.isEdit ? 'none' : ''};">${item.email}</div>     
                        </td>
                        <td>
                            <span style="background: ${item.isEdit ? 'green' : 'blue'};" class="edit" data-id="${item.id}" data-type="${item.isEdit ? 'ok' : 'edit'}" data-index="${index}">${item.isEdit ? '完成' : '编辑'}</span>
                            <span class="del" data-id="${item.id}">删除</span>
                        </td>
                    </tr>
                `
                }).join('')
                handleDeleteStudent() // 删除学生数据
                handleEditStudent() // 编辑学生数据
                handleSetStorage('list', list) // 注意:删除操作执行完后再执行本地存储操作
            }
            // 初始化
            render(list)

本地存储功能

项目还实现了本地存储功能,保证了数据的持久化存储,避免了页面刷新导致数据丢失的问题。

function handleSetStorage(key, value) {
                window.sessionStorage.setItem(key, JSON.stringify(value))
            }

            function handleGetStorage(key) {
                return JSON.parse(window.sessionStorage.getItem(key)) || []
            }

结论

通过项目,我们获得了宝贵的经验和知识。首先,我们学会了如何构建清晰的前端架构,将业务逻辑与界面表现分离,使得前端代码更易于组织和维护。其次,我们掌握了实现响应式页面更新的技巧,当数据发生变化时,页面元素能够自动更新,极大地提升了用户体验。此外,我们深入了解了本地存储技术,通过它实现了数据的持久化存储,避免了因页面刷新而导致数据丢失的问题,从而增强了用户体验。另外,在采用数据驱动视图的开发模式中,我们通过单元测试与集成测试进一步提高了代码质量和可靠性。这些收获让我们更专注于业务逻辑处理,降低了对DOM操作的关注,提高了开发效率。总结来说,数据驱动视图的开发模式在现代Web开发中具有显著优势,能够提高开发效率、加强页面交互体验,并且使得前端代码更加清晰、易于维护。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值