前端实验(序)——前端开发基础

实验目的

  1. 了解前端页面组成及html、css、JavaScript分工;
  2. 熟悉MVVM设计模式;
  3. 掌握JavaScript中函数的使用
  4. 掌握异步编程中promise的使用
  5. 掌握模块化导入导出技术
  6. 掌握前端调试技术

实验过程

通过制作一个前端网页,完成HTML、CSS和JavaScript相关语法的学习,并了解MVVM架构模式及模块化开发。

实验步骤

  1. 创建一个名为studentModel.js文件,提供学生信息数据。该模块首先定义学生数据,并模拟异步获取数据fetchStudents,最后通过模块导出获取学生数据方法。代码如下:
javascript 复制代码
// 学生数据模型模块
const studentModule = (function() {
    // 私有学生数据,使用字面量定义对象数组
    const students = [
        {
            id: 'S001',
            firstName: '小明',
            lastName: '张',
            age: 20,
            major: '计算机科学',
            grade: 85,
            gpa: 3.7,
            email: 'zhangxiaoming@example.com'
        },
        {
            id: 'S002',
            firstName: '小红',
            lastName: '李',
            age: 21,
            major: '数学',
            grade: 92,
            gpa: 3.9,
            email: 'lixiaohong@example.com'
        },
        {
            id: 'S003',
            firstName: '小刚',
            lastName: '王',
            age: 19,
            major: '物理',
            grade: 78,
            gpa: 3.2,
            email: 'wangxiaogang@example.com'
        }
    ];

    // 模拟异步获取数据
    function fetchStudents() {
        return new Promise((resolve) => {
            // 模拟网络延迟,使用扩展运算符
            setTimeout(() => {
                resolve([...students]);
            }, 800);
        });
    }

    // 公开的API
    return {
        getStudents: fetchStudents
    };
})();

// 导出模块
export const { getStudents } = studentModule;

代码中首先定义学生对象数组,其次模拟异步获取数据函数,该函数返回了一个Promise对象;最后通过模块导出getStudents 方法,体现面向对象的封装性

2 创建一个名为student.html的网页文件,展示学生信息。并将CSS和JavaScript代码集中存放Body元素底部。这种将不同类型的文件进行集中存放,便于代码的后期维护。代码如下:

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>
</head>
<body>
    <div class="container">
        <h1>学生信息管理系统</h1>
        <div id="student-container">
            <div class="loading">正在加载学生数据...</div>
        </div>
    </div>

    <script type="module">
        import { getStudents } from './studentModel.js';

        // 通过异步访问,获取要显示的数据,async代表函数内部包含了异步处理
        async function displayStudents() {
            try {
                const students = await getStudents();
								console.log("异步数据读取完成",students );
								// 以上代码获取的students可以想象为MVVM中的M,
								// 以下代码对获取的M加工,并将其渲染到页面(V)中
                const processedStudents = processStudentData(students);
                renderStudents(processedStudents);          
                console.log("数据已经渲染到页面",processedStudents)
                  } catch (error) {
                document.getElementById('student-container').innerHTML = 
                    `<div class="error">加载学生数据失败: ${error.message}</div>`;
            }
        }


        function processStudentData(students) {
            return students.map(student => {
                return {
									  // ...扩展运算,将student对象解析为单个属性,与下面加工属性合并为一个新的对象
                    ...student,  
                    fullName: `${student.lastName} ${student.firstName}`,
                    gradeLevel: getGradeLevel(student.grade),
                    gpaStatus: student.gpa >= 3.5 ? '优秀' : student.gpa >= 2.5 ? '良好' : '需提高'
                };
            });
        }

        function getGradeLevel(grade) {
            if (grade >= 90) return 'A';
            if (grade >= 80) return 'B';
            if (grade >= 70) return 'C';
            if (grade >= 60) return 'D';
            return 'F';
        }
        
				// 将数据渲染到页面
        function renderStudents(students) {
            const container = document.getElementById('student-container');
            container.innerHTML = '';

            if (students.length === 0) {
                container.innerHTML = '<div class="error">没有找到学生数据</div>';
                return;
            }

            students.forEach(student => {
                const card = document.createElement('div');
                card.className = 'student-card';
                card.innerHTML = `
                    <h3>${student.fullName}</h3>
                    <div class="student-info">
                        <div class="info-item">
                            <span class="info-label">学号:</span> ${student.id}
                        </div>
                        <div class="info-item">
                            <span class="info-label">年龄:</span> ${student.age}
                        </div>
                        <div class="info-item">
                            <span class="info-label">专业:</span> ${student.major}
                        </div>
                        <div class="info-item">
                            <span class="info-label">年级:</span> ${student.gradeLevel}
                        </div>
                        <div class="info-item">
                            <span class="info-label">GPA:</span> ${student.gpa} (${student.gpaStatus})
                        </div>
                        <div class="info-item">
                            <span class="info-label">邮箱:</span> ${student.email}
                        </div>
                    </div>
                `;
                container.appendChild(card);
            });
        }

        // 初始化加载数据
        displayStudents();
    </script>
		
		<style>
			  /* 标签选择器 */
		    body {
		        font-family: 'Arial', sans-serif;
		        line-height: 1.6;
		        margin: 0;
		        padding: 20px;
		        background-color: #f5f5f5;
		    }
				/* 类选择器 */
		    .container {
		        max-width: 1000px;
		        margin: 0 auto;
		        background: white;
		        padding: 20px;
		        border-radius: 8px;
		        box-shadow: 0 0 10px rgba(0,0,0,0.1);
		    }
		    h1 {
		        color: #2c3e50;
		        text-align: center;
		        margin-bottom: 30px;
		    }
		    .student-card {
		        border: 1px solid #ddd;
		        border-radius: 5px;
		        padding: 15px;
		        margin-bottom: 15px;
		        background-color: #f9f9f9;
		    }
				
				/* 后代选择器,其中.student-card是祖先元素,h3是后代元素 */
		    .student-card h3 {
		        margin-top: 0;
		        color: #3498db;
		    }
		    .student-info {
		        display: grid;
		        grid-template-columns: repeat(2, 1fr);
		        gap: 10px;
		    }
		    .info-item {
		        margin-bottom: 5px;
		    }
		    .info-label {
		        font-weight: bold;
		        color: #7f8c8d;
		    }
		    .loading {
		        text-align: center;
		        padding: 20px;
		        font-style: italic;
		        color: #7f8c8d;
		    }
		    .error {
		        color: #e74c3c;
		        text-align: center;
		        padding: 20px;
		    }
		</style>
</body>
</html>

代码中HTML是页面骨架,CSS是修饰器,JavaScript代码完成互动。由MVVM模式角度,可以认为HTML为V(视图),studentModel.js中的数据看做为M(模型),JavaScript代码为VM,V和M不发生直接耦合,VM将二者联系起来,当M发生变化时,仅变化VM中代码,当V发生变化时,也仅限于VM代码的变化。这种架构模式符合迪米特法则------不和陌生人讲话,即V和M是陌生人

  1. 浏览页面,由于使用浏览器访问文件时,会报跨域错误,因此需要安装Web服务器,再浏览页面。执行步骤如下:
    按win+R,输入CMD,打开命令行窗口,在命令行窗口输入:node -v,验证是否安装node.js,如果没有安装,先安装node.js
    NPM包含在node.js,在命令行窗口输入命名:npm install anywhere -g;安装anywhere静态服务器(类似tomcat)。
    在命令行窗口,进入上述html所在目录,输入命令:anywhere -p 10009;启动服务器,启动后弹出界面如下:

    点击student.html文件,显示页面如下:
  2. 页面调试
    按F12,打开调试页面。选中第一个选项卡,在此可以查看DOM元素,调整相关样式,界面如下:

    选中console可以查看控制台上输出,以便调试代码。界面如下:

点击网络选项卡(network),可以查看网络请求,界面如下:

相关推荐
洛卡卡了2 分钟前
Sentry 都不想接,这锅还让我背?这xx工作我不要了!
前端·架构
咖啡の猫5 分钟前
Vue 实例生命周期
前端·vue.js·okhttp
JNU freshman20 分钟前
vue 之 import 的语法
前端·javascript·vue.js
剑亦未配妥20 分钟前
Vue 2 响应式系统常见问题与解决方案(包含_demo以下划线开头命名的变量导致响应式丢失问题)
前端·javascript·vue.js
凉柚ˇ24 分钟前
Vue图片压缩方案
前端·javascript·vue.js
慧一居士24 分钟前
vue 中 directive 作用,使用场景和使用示例
前端
慧一居士26 分钟前
vue 中 file-saver 功能介绍,使用场景,使用示例
前端
文心快码BaiduComate1 小时前
文心快码3.5S实测插件开发,Architect模式令人惊艳
前端·后端·架构
Kimser1 小时前
基于 VxeTable 的高级表格选择组件
前端·vue.js
摸着石头过河的石头1 小时前
JavaScript 防抖与节流:提升应用性能的两大利器
前端·javascript