1 JQ实现待办任务列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TodoList Jquery</title>
<script src='jquery.js'></script>
</head>
<body>
<div>
<input id="input" type="text"/>
<button id="btn">提交</button>
<ul id="list"></ul>
</div>
<script>
// 构造函数
function Page() {
}
$.extend(Page.prototype, {
init: function () {
this.bindEvents()
},
bindEvents: function () {
var btn = $('#btn');
// 将点击事件绑定到提交按钮上
// 并使用$.proxy函数确保函数在Page对象的上下文中执行
btn.on('click', $.proxy(this.handleBtnClick, this))
},
// 在点击提交按钮时被调用。
handleBtnClick: function () {
var inputElem = $("#input");
// 获取输入框中的值
var inputValue = inputElem.val();
var ulElem = $("#list");
// 将其添加到列表中
ulElem.append('<li>' + inputValue + '</li>');
// 并清空输入框
inputElem.val('');
}
})
// 创建一个名为page的Page对象
var page = new Page();
// 并调用其init函数
page.init();
</script>
</body>
</html>
整个编程模式其实就符合 MVP。
2 MVP
2.1 案例
古时候写前端:一个请求,一次接收。
随业务复杂,很多页面,就得多次请求更新了吗?还需要多页面交互的话,咋办?
又要处理业务逻辑,又要处理显示逻辑,产品需求一遍在编,咋办呢?
将显示逻辑委托给框架实现,工作流程就变成了:
因为显示逻辑都有框架处理了:
Model-View-Presenter,一种前端架构模式,用于解决复杂应用程序的设计问题,主要目标是将应用程序的业务逻辑与用户界面分离,使代码更易于维护和扩展。View 和 Presenter 之间通过接口进行通信,从而实现了彻底解耦。
MVP应用程序被分为三个主要组成部分:
2.2 Model:数据层(被边缘化)
负责处理数据的读取、存储和操作
该案例的Model层很弱,因为没有使用 AJAX 去获取数据,可理解为没有 Model 层。
2.3 View:视图层
负责呈现数据和与用户交互
即 DOM,HTML部分定义了页面的布局和元素。handleBtnClick函数是作为点击提交按钮响应事件的处理函数,负责处理用户的交互行为,并将结果展示在页面上
2.4 Presenter:逻辑层(核心)
作为 Model 和 View 之间的中介,负责处理业务逻辑和控制视图的行为。代码量的大头,基本都在操作 DOM。
该段代码的 MVP 模式的Presenter逻辑层体现在Page对象及其方法中:
- Page对象是Presenter的角色,它的方法实现了将视图层(HTML和CSS)与模型层(数据)进行互动并控制应用程序的行为。具体来说,Page对象的init方法启动了整个应用程序,bindEvents方法添加了事件处理程序
- handleBtnClick方法定义了处理点击提交按钮的逻辑
通过分离Presenter层和View层,Presenter可以独立于具体的视图实现,可以更好地实现应用程序的模块化和可维护性。
3 MVVM
3.1 组件
模型、视图和视图模型。每个服务于不同的目的。
组件之间的关系
组件交互
高层次上,View“知道”ViewModel,ViewModel“知道”Model,但Model不知道ViewModel,ViewModel不知道View。
因此,ViewModel将View与Model隔离,并允许Model独立于View而发展。
3.2 好处
- 如果现有Model实现封装了现有业务逻辑,则更改它可能很困难或存在风险。在这种情况下,ViewModel充当Model类的适配器,并防止对Model代码进行重大更改
- 开发人员可以在不使用View的情况下为ViewModel和Model创建UT。ViewModel的UT可执行与View使用的完全相同的功能
- 如果View完全在 XAML 或 C# 中实现,则可以在不触及视图模型和模型代码的情况下重新设计应用程序 UI。因此,新版本的视图应该与现有的视图模型一起工作
- 设计人员和开发人员可以在开发过程中独立并同时处理他们的组件。设计人员可以专注于View,而开发人员可以专注于ViewModel和Model组件
有效使用 MVVM 的关键在于了解如何将应用程序代码分解为正确的类以及这些类如何交互。以下部分讨论了 MVVM 模式中每个类的职责。
3.3 View
负责View的绘制以及与用户交互。View层不做任何业务逻辑、不涉及操作数据、不处理数据,UI和数据严格的分开。
3.4 ViewModel
负责完成View与Model间的交互,负责业务逻辑。
ViewModel层做的事情刚好和View层相反,ViewModel只做和业务逻辑和业务数据相关的事,不做任何和UI相关的事情,ViewModel 层不会持有任何控件的引用,更不会在ViewModel中通过UI控件的引用去做更新UI的事情。ViewModel就是专注于业务的逻辑处理,做的事情也都只是对数据的操作(这些数据绑定在相应的控件上会自动去更改UI)。同时DataBinding框架已经支持双向绑定,让我们可以通过双向绑定获取View层反馈给ViewModel层的数据,并对这些数据上进行操作。关于对UI控件事件的处理,我们也希望能把这些事件处理绑定到控件上,并把这些事件的处理统一化,为此我们通过BindingAdapter对一些常用的事件做了封装,把一个个事件封装成一个个Command,对于每个事件我们用一个ReplyCommand去处理就行了,ReplyCommand会把你可能需要的数据带给你,这使得我们在ViewModel层处理事件的时候只需要关心处理数据就行了,具体见MVVM Light Toolkit 使用指南的Command部分。再强调一遍:ViewModel 不做和UI相关的事。
Vue 自带,无需开发关心。
3.5 模型
实体模型。Model层最大的特点是被赋予了数据获取的职责,与我们平常Model层只定义实体对象的行为截然不同。实例中,数据的获取、存储、数据状态变化都是Model层的任务。Model包括实体模型(Bean)、Retrofit的Service ,获取网络数据接口,本地存储(增删改查)接口,数据变化监听等。Model提供数据获取接口供ViewModel调用,经数据转换和操作并最终映射绑定到View层某个UI元素的属性上。
3.6 Vue 实现
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>TodoList</title>
<script src='vue.js'></script>
</head>
<body>
<!-- MVVM的 View 层-->
<div id="app">
<input type="text" v-model="inputValue"/>
<button v-on:click="handleBtnClick">提交</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
// MVVM的 Model 层我们都是在开发 M 层,修改之后,V 层自动就会变化这背后就是VM 层做的(Vue自带实现)
// 这就让我们只需关注 M 层开发
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function () {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
</body>
</html>
4 总结
JQ属于 MVP 开发模式,大量操作 DOM,而 Vue 属于 MVVM 开发模式,让我们能专注 Model 数据,因此使用 Vue 开发至少节约 30% 代码量。
参考