浅谈使用MVC模式进行JavaScript程序开发

yizhihongxing

让我们来讲一下如何使用MVC模式进行JavaScript程序开发的完整攻略。先来了解一下什么是MVC模式吧。

什么是MVC模式

MVC模式拆分JavaScript应用程序为Model、View和Controller三个部分。M表示数据模型(model),V表示用户界面(view),C表示控制逻辑(controller)。这种将应用程序分解成三个独立的部分的方式可以提高代码组织的质量和可维护性。下面简单介绍一下MVC的三个部分:

Model(数据模型)

Model是应用程序中处理数据逻辑的部分,通过这个模型对象的定义,我们可以操作从数据库获取的数据,同时我们还可以定义对这个数据的操作,如增加数据、修改数据、查询数据等等。其中这些操作大多数是异步的,会因数据量的增大而变得越来越复杂。但也没什么可担心的,我们只需要让Model角色处理这些细节就行了。

View(用户界面)

View是应用程序中的用户界面,从用户角度来看,视图层是看到和感受到的部分。这个层级决定了视图会是什么样子,由哪些参与之才令其成为视图。另外,这个层级还得掌管绑定到页面上的事件处理应用程序中的处理逻辑。值得一提的是,用户可以与视图交互,甚至改变其样子而不影响应用程序的其他部分。

Controller(控制器)

Controller是应用程序中的控制逻辑,负责处理用户事件、更新数据模型和更新视图UI。Controller层级承接了Model层级和View层级之间的通信,实现了应用程序流程的控制。很多时候,Controller层级只需要很简单的驱动力就可以操纵其他两个层级。与View类似,Controller也会处理用户请求。

如何进行MVC模式的JavaScript程序开发

下面我们来介绍一下如何进行MVC模式的JavaScript程序开发流程。

分离代码

把Javascript代码拆分成3部分,分别是Model、View、Controller,把相关的代码一一对应放到相应的js文件中,做到模块化。这样既方便后期维护,也便于代码重用。

|-- js/
|   |-- models/
|   |   |-- user.js
|   |   |-- product.js
|   |-- views/
|   |   |-- userView.js
|   |   |-- productView.js
|   |-- controllers/
|   |   |-- userController.js
|   |   |-- productController.js
|   |-- main.js

数据模型(Model)

在Model层中,我们定义了一种数据结构来存储数据状态,封装了操作数据的一些方法。在Model层中通常会有以下几个方法:

  • add: 新增数据
  • edit: 修改数据
  • delete: 删除数据
  • fetch: 获取数据

以下面一个User的Model对象为例:

// js/models/user.js

(function() {
  var User = function(firstName, lastName, email) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.email = email;
  };

  User.prototype.getFullName = function() {
    return this.firstName + ' ' + this.lastName;
  };

  window.User = User;
}());

代码中使用了IIFE将User对象的定义包装起来,以防止污染全局命名空间。User对象有三个属性(firstName、lastName、email)和一个方法(getFullName),方法用来获取用户的全名。该User对象将被保存到window对象的User属性中,以便其他模块可以使用它。

视图(View)

视图是根据数据创建动态UI的逻辑集合。在视图层中,我们要重新创建页面上的元素,然后绑定一些事件,当用户触发这些事件时,将会执行Controller层中的一些行为并反映到页面上。在View层中通常会有以下几个方法:

  • render: 渲染模板并更新视图中的元素
  • bind: 绑定事件到元素

以下是一个UserView的代码:

// js/views/userView.js

(function() {
  window.UserView = function(userModel) {
    this.userModel = userModel;
    this.$el = $('<div>');
  };

  UserView.prototype.render = function() {
    this.$el.html(this.userModel.getFullName());
    return this;
  };

  UserView.prototype.bind = function(eventName, handler) {
    this.$el.on(eventName, handler);
  };
}());

代码中,我们定义了一个UserView对象,该对象接受一个UserModel对象作为其构造器的参数并将其保存到userModel属性上。UserView对象有两个方法,render方法用来渲染模板并更新页面中的元素,bind方法用来绑定事件到元素。这样我们就将数据模型和视图分开了。

控制器(Controller)

在Controller层中,我们会实现一些响应用户事件并控制Model和View进行更新的方法。在Controller层中通常会有以下几个方法:

  • add: 新增数据,并更新页面视图
  • edit: 修改数据,并更新页面视图
  • delete: 删除数据,并更新页面视图

以下是UserController的代码:

// js/controllers/userController.js

(function() {
  window.UserController = function(userModel, userView) {
    this.userModel = userModel;
    this.userView = userView;
  };

  UserController.prototype.init = function() {
    this.userView.bind('click', function() {
      alert('Clicked!');
    });

    this.userModel.on('change', this.render, this);
    this.render();
  };

  UserController.prototype.render = function() {
    this.userView.render();
  };
}());

代码中实现了一个UserController,该对象接受一个UserModel对象和一个UserView对象作为其构造函数的参数,并将两个模块保存在userModel和userView属性中。UserController对象有两个方法,init方法用来绑定事件并在用户模型发生更改时控制视图进行更新,render方法用来更新视图。

示例说明

下面我们来使用一个这样一个示例来说明MVC模式的使用。

用户列表的展示

我们使用一个简单的例子,我们在网页上展示一个用户列表,要求能够实现以下功能:

  • 渲染用户列表
  • 添加新的用户
  • 修改用户信息
  • 删除用户信息

端口代码分离成3部分:

  • Model:该部分处理数据存储逻辑,等价于数据库操作
  • View:该部分负责界面展示,与用户有交互,等价于HTML页面呈现
  • Controller:该部分负责逻辑处理,等价于JavaScript代码块

以下是实现代码:

// js/models/user.js

(function() {
  var User = function(firstName, lastName, email) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.email = email;
  };

  User.prototype.getFullName = function() {
    return this.firstName + ' ' + this.lastName;
  };

  window.User = User;

  // 数据存储逻辑
  var users = [], listeners = [];

  function addUser(user) {
    users.push(user);
    notifyListeners();
  }

  function editUser(user, index) {
    users[index] = user;
    notifyListeners();
  }

  function deleteUser(index) {
    users.splice(index, 1);
    notifyListeners();
  }

  function fetchUsers() {
    return users;
  }

  function notifyListeners() {
    listeners.forEach(function(listener) {
      listener(users);
    });
  }

  function registerListener(listener) {
    listeners.push(listener);
  }

  window.userModel = {
    User: User,
    addUser: addUser,
    editUser: editUser,
    deleteUser: deleteUser,
    fetchUsers: fetchUsers,
    registerListener: registerListener
  };
}());

// js/views/userView.js

(function() {
  window.UserView = function(userModel) {
    var that = Object.create(UserView.prototype);
    that.userModel = userModel;
    that.$el = $('<div>');
    that.$el.html(that.renderList());

    userModel.registerListener(function(users) {
      that.$el.html(that.renderList());
    });

    return that;
  };

  UserView.prototype = {
    renderList: function() {
      var userList = $('<ul>');
      this.userModel.fetchUsers().forEach(function(user) {
        var userView = $('<li>');
        userView.text(user.getFullName());
        userList.append(userView);
      });

      return userList;
    }
  };
}());

// js/controllers/userController.js

(function() {
  window.UserController = function(userModel, userView) {
    var that = Object.create(UserController.prototype);
    that.userModel = userModel;
    that.userView = userView;

    userView.$el.on('click', '#addUser', function() {
      var firstName = $('#firstName').val(),
          lastName = $('#lastName').val(),
          email = $('#email').val();
      var newUser = new userModel.User(firstName, lastName, email);
      userModel.addUser(newUser);

      $('#firstName').val('');
      $('#lastName').val('');
      $('#email').val('');
    });

    userView.$el.on('click', '.editUser', function() {
      var firstName = $(this).parents('li').find('.firstName').val(),
          lastName = $(this).parents('li').find('.lastName').val(),
          email = $(this).parents('li').find('.email').val(),
          index = $(this).data('id');
      var user = new userModel.User(firstName, lastName, email);
      userModel.editUser(user, index);
    });

    userView.$el.on('click', '.deleteUser', function() {
      var index = $(this).data('id');
      userModel.deleteUser(index);
    });

    return that;
  };

  UserController.prototype = {
    init: function() {
      this.userView.render();
    }
  };
}());

// js/main.js

$(function() {
  var userModel = window.userModel,
      userView = window.UserView(userModel),
      userController = window.UserController(userModel, userView);

  userController.init();
  $('body').append(userView.$el);
});

代码中,数据模型是User对象,具有获取用户全名、添加用户、修改用户、删除用户、获取用户列表等方法。视图层是UserView对象,用来渲染、呈现User对象列表的信息。控制器层是UserController对象,监听视图用户交互后的事件并控制相关事件的执行。

我们将代码按照MVC模式分成了3部分,并且每一部分都有相应的职责,从而使代码具有更好的可维护性和复用性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈使用MVC模式进行JavaScript程序开发 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • C#从前面或后面按指定数量删除字符串

    让我为您详细讲解 “C#从前面或后面按指定数量删除字符串” 的完整攻略吧。 方法一:Substring()方法 C#的字符串类型中有一个名为Substring()的方法,可以截取子字符串,从而实现删除指定数量的字符。 从前面删除字符串 从前面删除字符串,需要保留剩余字符串的后面部分,可以使用Substring()方法的起始位置参数startIndex和需要保…

    C# 2023年6月8日
    00
  • c#泛型学习详解 创建线性链表

    C#泛型学习详解-创建线性链表 什么是泛型 在C#中,泛型是一种基于类型参数化的编程技术,它允许我们编写一个可以与任何类型一起工作的代码。使用泛型代码可以提高代码重用性和类型安全性。 什么是线性链表 线性链表是一种基本数据结构,由若干个数据节点构成,每个节点包含自己的数据或指向其他节点的引用。节点之间的关系是通过引用来体现的。具体的,我们可以用下列代码来表示…

    C# 2023年6月7日
    00
  • C#中把FastReport.Net报表控件的数据保存到数据库

    C#中把FastReport.Net报表控件的数据保存到数据库的完整攻略如下: 1.准备工作 在开始保存FastReport报表控件的数据之前,需要先做一些准备工作,包括: 安装FastReport.Net报表控件; 在你的项目中引用FastReport.Net的dll文件; 在你的项目中引用数据库连接的相关dll文件; 创建一个数据库表,用来存储报表数据;…

    C# 2023年5月31日
    00
  • c# 进程和线程的区别与联系

    下面是关于“c# 进程和线程的区别与联系”的完整攻略: 1. 进程和线程的基本概念 1.1 进程 进程是操作系统资源分配的最小单位,它是程序在操作系统中的一个执行实例。进程拥有独立的内存空间、系统资源和文件句柄等,进程之间相互独立,互不干扰。每一个进程都有唯一的进程ID(PID),可以通过该ID来识别和管理进程。 1.2 线程 线程是进程中的执行单元,一个进…

    C# 2023年6月7日
    00
  • 记一次 .NET 某车零件MES系统 登录异常分析

    一:背景 1. 讲故事 这个案例有点特殊,以前dump分析都是和软件工程师打交道,这次和非业内人士交流,隔行如隔山,从指导dump怎么抓到问题解决,需要一个强大的耐心。 前几天有位朋友在微信上找到我,说他们公司采购的MES系统登录的时候出现了异常,让我帮忙看一下,我在想解铃还须系铃人,怎么的也不应该找到我呀,据朋友反馈项目已经验收,那边给了回馈是网络的问题,…

    C# 2023年5月8日
    00
  • 使用.NET命令行编译器编译项目(如ASP.NET、C#等)

    使用.NET命令行编译器(通常是csc.exe)可以编译各种.NET项目,包括ASP.NET和C#等。下面是完整的攻略过程。 安装.NET Core SDK 首先,你需要安装.NET Core SDK,因为.NET命令行编译器是其中的一部分。你可以在官方网站上下载适用于你的操作系统的版本。安装完成后,你可以使用以下命令来检查.NET命令行编译器是否已经安装成…

    C# 2023年5月14日
    00
  • ajax跨域调用webservice的实现代码

    要实现ajax跨域调用webservice,我们需要使用JSONP或CORS技术。JSONP是一种通过动态创建script标签来实现跨域请求的技术,而CORS是一种通过在服务器端设置响应头来实现跨域请求的技术。本文将提供详解“ajax跨域调用webservice的实现代码”的完整攻略,包括如何使用JSONP和CORS技术实现跨域请求。 使用JSONP实现跨域…

    C# 2023年5月15日
    00
  • Asp.net TreeView来构建用户选择输入的方法 推荐

    Asp.net TreeView来构建用户选择输入的方法,主要是通过构建TreeView控件来显示一个树形结构,以便用户可以通过勾选不同的节点来完成相应的选择。 下面是具体的实现步骤: 1. 创建TreeView控件 在Asp.net页面中,首先需要在WebForm中创建TreeView控件,在页面的标签内添加如下代码: <asp:TreeView I…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部