从Script到Code Blocks、Code Behind到MVC、MVP、MVVM
从Script到Code Blocks、Code Behind到MVC、MVP、MVVM引言前端架构的进化之路想象一下你正在搭建一个乐高城堡。最初你只是把积木随意堆在一起Script方式后来你把城堡分成底座、塔楼、城门等模块Code Blocks再后来你开始画设计图让不同人负责不同部分Code Behind。最后你甚至发明了一套积木标准让所有城堡的组件可以互换MVC/MVP/MVVM。这就是前端架构的进化史。## 第一阶段Script——混沌初开的时代在Web早期所有代码都混在HTML文件中。JavaScript像散落的乐高积木哪里需要就放哪里。html!-- 1995年的典型页面 --htmlbody h1我的第一个网页/h1 p iddemo点击按钮改变文本/p button onclickchangeText()点击我/button script // 直接写在HTML里的JavaScript function changeText() { document.getElementById(demo).innerHTML 文本被改变了; } /script/body/html这种方式的问题显而易见-难以维护代码混在一起就像把所有衣服塞进一个抽屉-重复代码同样功能要在不同页面重复写-全局污染所有变量都在全局作用域## 第二阶段Code Blocks——模块化的萌芽开发者开始把JavaScript拆分成独立文件就像把不同物品放进不同抽屉。javascript// utils.js - 工具函数模块function formatDate(date) { // 格式化日期 let year date.getFullYear(); let month date.getMonth() 1; let day date.getDate(); return ${year}-${month.toString().padStart(2, 0)}-${day.toString().padStart(2, 0)};}// 导出函数供其他模块使用window.formatDate formatDate;// calculator.js - 计算模块function add(a, b) { return a b;}function multiply(a, b) { return a * b;}window.add add;window.multiply multiply;html!-- 使用模块的页面 --htmlhead script srcutils.js/script script srccalculator.js/script/headbody script // 调用模块中的函数 let today new Date(); console.log(formatDate(today)); // 输出格式化的日期 console.log(add(3, 5)); // 输出8 /script/body/html这种方式的进步在于-逻辑分离不同功能放在不同文件-复用性提高可以在多个页面使用相同模块-命名空间通过对象减少全局污染## 第三阶段Code Behind——代码后置的革新Code Behind模式把业务逻辑从视图HTML中彻底分离。这种模式在ASP.NET中非常流行。python# views.py - 视图逻辑层from flask import Flask, render_template, requestapp Flask(__name__)# 业务逻辑计算商品总价def calculate_total_price(items): total 0 for item in items: total item[price] * item[quantity] return totalapp.route(/checkout, methods[POST])def checkout(): # 获取用户购物车数据 cart_items request.json.get(items, []) # 调用业务逻辑 total calculate_total_price(cart_items) # 返回计算结果 return render_template(checkout.html, total_pricetotal)html!-- checkout.html - 纯视图模板 --!DOCTYPE htmlhtmlbody h1购物车结算/h1 !-- 视图只负责展示不包含业务逻辑 -- p总金额{{ total_price }} 元/p !-- 所有交互逻辑交给Code Behind处理 -- button onclicksubmitOrder()提交订单/button script function submitOrder() { // 通过AJAX请求后端 fetch(/checkout, { method: POST, body: JSON.stringify({items: cartData}) }); } /script/body/htmlCode Behind的核心思想视图View只负责展示代码Code负责逻辑。## 第四阶段MVC——Model-View-ControllerMVC把应用分为三个核心组件-Model管理数据和业务逻辑-View负责数据显示-Controller处理用户输入协调Model和Viewpython# MVC示例简单的待办事项应用# Model - 数据层class TodoModel: def __init__(self): self.todos [] def add_todo(self, task): self.todos.append({task: task, completed: False}) def get_all(self): return self.todos# View - 视图层class TodoView: def display_todos(self, todos): print(\n 待办事项列表 ) for i, todo in enumerate(todos, 1): status ✓ if todo[completed] else print(f{i}. [{status}] {todo[task]}) def get_user_input(self): return input(\n输入新任务或输入q退出)# Controller - 控制层class TodoController: def __init__(self): self.model TodoModel() self.view TodoView() def run(self): while True: # 显示当前数据 self.view.display_todos(self.model.get_all()) # 获取用户输入 task self.view.get_user_input() if task.lower() q: break # 处理数据 self.model.add_todo(task)# 启动应用if __name__ __main__: app TodoController() app.run()MVC的优势-职责明确每个组件只做一件事-可测试性Model和Controller可以独立测试-可扩展性可以轻松替换View或Model## 第五阶段MVP——Model-View-PresenterMVP是MVC的变体主要区别在于View和Presenter的关系更紧密。javascript// MVP模式示例用户登录功能// Model - 数据层class LoginModel { constructor() { this.username ; this.password ; } validateCredentials(username, password) { // 模拟验证逻辑 if (username admin password 123456) { return { success: true, message: 登录成功 }; } return { success: false, message: 用户名或密码错误 }; }}// View - 视图层抽象接口class LoginView { constructor() { this.usernameInput document.getElementById(username); this.passwordInput document.getElementById(password); this.loginButton document.getElementById(loginBtn); this.messageElement document.getElementById(message); } getUsername() { return this.usernameInput.value; } getPassword() { return this.passwordInput.value; } showMessage(message, isSuccess) { this.messageElement.textContent message; this.messageElement.style.color isSuccess ? green : red; } clearInputs() { this.usernameInput.value ; this.passwordInput.value ; }}// Presenter - 控制器class LoginPresenter { constructor(view, model) { this.view view; this.model model; // 绑定事件 this.view.loginButton.addEventListener(click, () this.handleLogin()); } handleLogin() { const username this.view.getUsername(); const password this.view.getPassword(); // 调用Model进行验证 const result this.model.validateCredentials(username, password); // 更新View this.view.showMessage(result.message, result.success); if (result.success) { this.view.clearInputs(); } }}// 初始化const model new LoginModel();const view new LoginView();const presenter new LoginPresenter(view, model);MVP的特点-View完全被动所有逻辑由Presenter处理-测试友好可以Mock View进行测试-适合复杂UI特别适合需要精细控制视图的场景## 第六阶段MVVM——Model-View-ViewModelMVVM是当前最流行的模式通过数据绑定实现自动同步。python# 使用Tkinter实现MVVM示例import tkinter as tkfrom tkinter import ttk# Model - 数据层class UserModel: def __init__(self): self._name self._age 0 self._observers [] def add_observer(self, observer): self._observers.append(observer) def notify_observers(self, property_name, value): for observer in self._observers: observer.update(property_name, value) property def name(self): return self._name name.setter def name(self, value): self._name value self.notify_observers(name, value) property def age(self): return self._age age.setter def age(self, value): self._age value self.notify_observers(age, value)# ViewModel - 视图模型class UserViewModel: def __init__(self, model): self.model model self.name tk.StringVar() self.age tk.StringVar() self.greeting tk.StringVar() # 绑定模型变化 model.add_observer(self) def update(self, property_name, value): if property_name name: self.name.set(value) elif property_name age: self.age.set(str(value)) self._update_greeting() def on_name_changed(self, *args): self.model.name self.name.get() def on_age_changed(self, *args): try: age int(self.age.get()) self.model.age age except ValueError: pass def _update_greeting(self): self.greeting.set(f你好{self.model.name}你今年{self.model.age}岁。)# View - 视图层class UserView: def __init__(self, root, view_model): self.view_model view_model # 创建UI组件 frame ttk.Frame(root, padding10) frame.grid(row0, column0, sticky(tk.W, tk.E, tk.N, tk.S)) # 姓名输入 ttk.Label(frame, text姓名:).grid(row0, column0, stickytk.W) name_entry ttk.Entry(frame, textvariableview_model.name) name_entry.grid(row0, column1) view_model.name.trace(w, view_model.on_name_changed) # 年龄输入 ttk.Label(frame, text年龄:).grid(row1, column0, stickytk.W) age_entry ttk.Entry(frame, textvariableview_model.age) age_entry.grid(row1, column1) view_model.age.trace(w, view_model.on_age_changed) # 显示问候语 ttk.Label(frame, textvariableview_model.greeting).grid(row2, column0, columnspan2)# 运行应用if __name__ __main__: root tk.Tk() root.title(MVVM示例) model UserModel() view_model UserViewModel(model) view UserView(root, view_model) root.mainloop()MVVM的核心优势-双向绑定View和ViewModel自动同步-测试方便ViewModel可以独立于View测试-组件化适合大型应用的模块化开发## 总结架构进化给我们的启示从Script到MVVM这不仅是技术的演进更是思维方式的变革1.从混乱到有序代码组织方式越来越清晰2.从紧耦合到松耦合组件间依赖越来越弱3.从过程式到声明式关注点从如何做转向做什么4.从手动到自动数据同步从手动操作变为自动绑定选择哪种模式取决于项目需求-小项目Script或简单模块化就够了-中型项目Code Behind或MVC是不错的选择-复杂应用MVVM或MVP更适合记住没有银弹每种模式都有其适用场景。关键是要理解背后的设计思想而不是盲目追求最新的架构。架构的进化永远不会停止但分离关注点和降低耦合这两个原则将永远适用。

相关新闻

BP神经网络在车牌识别系统中的优化实践

BP神经网络在车牌识别系统中的优化实践

1. 项目背景与核心价值 车牌识别作为智能交通系统的核心技术之一,在停车场管理、违章抓拍、高速公路收费等场景中发挥着关键作用。传统基于图像处理的车牌识别方案在复杂光照、污损车牌等场景下识别率骤降,而BP神经网络凭借其强大的非线性映射能力&#…

2026/10/18 4:51:11 阅读更多 →
如何用REFramework实现游戏模组的零代码开发:终极可视化编程指南

如何用REFramework实现游戏模组的零代码开发:终极可视化编程指南

如何用REFramework实现游戏模组的零代码开发:终极可视化编程指南 【免费下载链接】REFramework Mod loader, scripting platform, and VR support for all RE Engine games 项目地址: https://gitcode.com/GitHub_Trending/re/REFramework 在游戏模组开发领域…

2026/10/22 8:36:20 阅读更多 →
如何在Windows上免费实现本地离线LaTeX公式识别:MixTeX完整指南

如何在Windows上免费实现本地离线LaTeX公式识别:MixTeX完整指南

如何在Windows上免费实现本地离线LaTeX公式识别:MixTeX完整指南 【免费下载链接】MixTeX-Latex-OCR MixTeX multimodal LaTeX, ZhEn, and, Table OCR. It performs efficient CPU-based inference in a local offline on Windows. 项目地址: https://gitcode.com/…

2026/10/21 7:47:02 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/22 10:18:38 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/22 11:01:53 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/22 9:44:47 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/22 10:42:00 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/22 10:40:08 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/22 10:56:37 阅读更多 →

日新闻

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/22 1:47:45 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/22 21:33:42 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/22 5:12:39 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/21 21:50:56 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/21 21:51:55 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/22 19:06:46 阅读更多 →