JavaScript 组件之旅(一)分析和设计

另一方面,由于 JavaScript 通常会和宿主环境(比如浏览器)紧密结合,因此缺乏功能强大而简单易用的开发工具。在这样的环境中,开发组件或框架成为一项具有挑战的工作。
这次,我们将以一个简易的 JavaScript 组件开发为契机,逐步展开组件的分析、设计、实现、构建和测试等任务,探讨组件开发过程涉及的方方面面。这些探讨将分 4 篇陆续张贴出来(链接将在张贴后更新):

  1. 分析和设计组件
  2. 编码实现和算法
  3. 用 Ant 构建组件
  4. 测试 JavaScript 组件

现在,假设我们要从头开始设计并实现一个队列管理组件,先让我们来认识一下队列:

Queue

图片来自 Wikipedia.

队列是一个“先进先出”(FIFO) 的数据结构,只能向它的尾巴追加项,项从头部取出使用,这个规则将应用到我们所探讨的组件中去。对于队列,相信学过 C 或是数据结构课程的同学已有所了解,如果你已经把它还给了老师,请使用搜索引擎简单了解一下队列的知识。

这个队列管理组件具体要实现的功能是:它是个任务管理器,按高、中、低优先级维护着三个任务队列,客户(使用者)可以在任何时候把想要执行的任务添加到某个队列,可以指定任务运行的上下文,并传给它必要的数据。客户也可以随时运行这个队列,队列里的任务按照指定的依赖关系以合理的方式依次运行。

为了不至于使组件过于简单而缺乏实用性,我们特意给它添加了一些“糖”:分优先级、传入上下文和数据、处理依赖关系。如果把上面这段理解为需求的话,那么首先,我们要从中提取出最重要的关键词,它们直接决定了这个组件应该如何设计:

  • 队列
  • 优先级
  • 依赖关系

然后,我们从中提炼出涉及的对象:

  • 任务管理器 (TaskManager): 从目前需求来看,它只需要一个实例。
  • 队列 (Queue): 每个优先级对应一个队列,由 TaskManager 管理这三个 Queue 实例。
  • 任务 (Task): 描述添加的任务,放在相应优先级的 Queue 里面。
  • 依赖 (Dependency): 描述单一的依赖,即 Task1 依赖 Task2, 显然某个 Task 可能具有多个依赖。

它的对象模型可以大概表示如下:

设计初期的对象图

注意到 Dependency 实际上并没有做什么事,而 Queue 的两个方法可以分别交给 TaskManager & Task 来负责。一个方法到底由哪个对象负责,是很容易引起争论的话题,不在我们的讨论范围内。这次,我们的重点是,采用 JavaScript 实现这个组件,结合 JavaScript 独特的语言特性,我们设想实现上述四个对象:

  • TaskManager 直接通过对象 (Object) 实现。在 JavaScript 的世界,对象可以作为天然的静态类来使用——你可以直接在“类” ClassObject 里面定义属性方法 property,并以静态类的方式来引用 CassObject.property.
  • Queue 以数组 (Array) 的形式体现出来,Task 则是数组中存放的每一项。对 Queue 进行操作必然要在其 prototype 中定义一些实例方法,由于每个 Queue 实例都是原生的数组,为了减少对 Array.prototype 的侵入,我们可以考虑将这些方法定义到 Task.prototype 上——将职责转移到任务上。
    将三个 Queue 数组集结在一起,形成一个“大数组”以表示三个不同优先级的队列,这个大数组可以作为 TaskManager 的属性。
  • 任务的核心是一个 function, 本来可以直接用 function 来表示一个任务,但考虑到它具有自身独特的属性(优先级、依赖等等),而且是最经常被操作的对象,以后可能还会进行扩展,所以我们决定单独将其定义成对象。
  • 依赖直接以数组的形式作为 Task 的一个属性存在——Task 将依赖的其他多个 Task 标识符放在这个数组中,不再单独定义这个对象。

分析下来,局势逐渐明朗——我们需要将四个对象简化成两个:TaskManager & Task, 另外两个对象用原生的数组来实现:

简化后的对象模型

又注意到这里多次以数组来实现,而编码过程中必然涉及到数组的遍历、查找等操作,JavaScript 1.6 已经为我们实现了这些数组操作。为了充分利用数组内置的原生方法,又能在较老的浏览器中运行,我们使用了 Eric 的代码。这样,我们可以直接使用诸如 forEach/indexOf 等方法,更关注组件的功能实现,而且在现代浏览器中获得较好的性能。

~~~~~~~~~~~~~ 八卦分割线 ~~~~~~~~~~~~~

嗯,在严肃地分析了组件设计之后,就要踏上快乐的编码实现之旅了。别急,TaskManager 似乎俗气了一点:不足以表达具有优先级、依赖管理的任务队列,而且用它做命名空间有跟其他代码冲突的可能性。好吧,这个组件就叫 Smart Queue 吧,响亮而又独特.^^

分析设计好了,名字也有了,欲知具体实现过程,且听下回分解。

(0)

相关推荐

  • JavaScript 组件之旅(一)分析和设计

    另一方面,由于 JavaScript 通常会和宿主环境(比如浏览器)紧密结合,因此缺乏功能强大而简单易用的开发工具.在这样的环境中,开发组件或框架成为一项具有挑战的工作.这次,我们将以一个简易的 JavaScript 组件开发为契机,逐步展开组件的分析.设计.实现.构建和测试等任务,探讨组件开发过程涉及的方方面面.这些探讨将分 4 篇陆续张贴出来(链接将在张贴后更新): 分析和设计组件 编码实现和算法 用 Ant 构建组件 测试 JavaScript 组件 现在,假设我们要从头开始设计并实现一个

  • JavaScript 组件之旅(三):用 Ant 构建组件

    听起来是不是很惬意?Let's go! 我们出发啦- 这期,我们会使用 Ant 将上期编写.整理的代码文件按指定的先后顺序合并成单一的源文件,然后压缩这个文件.这是构建 JavaScript 项目的基本步骤.Ant 是 Apache 的一个顶级开源项目,网上对它的介绍和安装,已经有很多文章,这里就不再赘述了.在构建之前,我们先来看看已有的文件布局: smart-queue // 组件的根目录 +--- src // JavaScript源文件目录 +--- lang.js // 前文提到的"外部

  • JavaScript 组件之旅(四):测试 JavaScript 组件

    本期,我们要讨论的话题是 JavaScript 的测试,以检查组件的状态和工作方式是否符合预期,还会介绍一个可以方便编写测试用例的测试方法.这里说的测试当然是使用自动化的测试手段,这是软件质量保证(QA)的重要环节.就本系列文章介绍的 Smart Queue 来说,我们的测试目标包括: Task 对象的创建:第二期的代码提供了多种创建方式,需要测试对象创建后的状态. Queue 内的任务运行次序:我们提供了两种改变运行次序的方式:优先级和依赖配置,同样也要测试各种配置对次序的影响. 对于第一个目

  • JavaScript 组件之旅(二)编码实现和算法

    首先,我们要考虑一下它的源文件布局,也就是决定代码如何拆分到独立的文件中去.为什么要这么做呢?还记得上期结尾处我提到这个组件会使用"外部代码"吗?为了区分代码的用途,决定将代码至少分成两部分:外部代码文件和 Smart Queue 文件.区分用途只是其一,其二,分散到独立文件有利于代码的维护.试想,以后的某一天你决定要在现有的队列管理基本功能之上,添加一些新的扩展功能,或是把它包装成某个实现特定任务的组件,而又希望保持现有功能(内部实现)和调用方式(对外接口)不变,那么将新的代码写到单

  • JavaScript组件焦点与页内锚点间传值的方法

    本文实例讲述了JavaScript组件焦点与页内锚点间传值的方法.分享给大家供大家参考.具体分析如下: 上述的这两个小功能在一些新式的手机页面是很有用的. 如何光标放上输入框就触发事件,离开输入框就触发另一个事件呢?即使用户不输入任何东西-- 页间传值很简单,但在页内的锚点之间是如何传值呢? 一.基本目标 有一个页面,上面有一个输入框,一个超级链接,这两个东西是没有任何关联的, 只是因为功能不大,所以把两个功能合起来写 1.输入框功能 一旦把光标放上对话框背景就变成红色,一旦用户的鼠标点击其他地

  • SpringMVC五大组件与执行原理分析总结

    目录 1.DispatcherServlet(前端(核心)控制器) 2.HandlerMapping(处理器映射器) 3.Controller(处理请求的控制器) 4.ModelAndView(封装数据和视图信息) 5.ViewResolver(视图解析器) SpringMVC执行原理 总结 Spring MVC是包含在spring中的一个基于MVC设计思想的Web应用程序框架,目的是简化开发工作,提高开发效率. 优点 和Spring框架无缝集成,能直接使用Spring的IoC容器.AOP支持:

  • JavaScript组件开发完整示例

    本文实例讲述了JavaScript组件开发的技巧.分享给大家供大家参考,具体如下: 使用JavaScript,按照面向对象的思想来构建组件. 现以构建一个TAB组件为例. 从功能上讲,组件包括可视部分和逻辑控制部分:从代码结构上讲,组件包括代码部分和资源部分(样式.图片等). 组件的特点:高内聚,低耦合(不与其他代码逻辑交叉,可以继承,包含):封装性(隐藏私有方法和变量):可重用性(可反复多次使用,用来组装更复杂的应用). <html> <head> <meta http-e

  • 基于Vue3.0开发轻量级手机端弹框组件V3Popup的场景分析

    之前有分享一个vue2.x移动端弹框组件,今天给大家带来的是Vue3实现自定义弹框组件. V3Popup 基于vue3.x实现的移动端弹出框组件,集合msg.alert.dialog.modal.actionSheet.toast等多种效果.支持20+种自定义参数配置,旨在通过极简的布局.精简的调用方式解决多样化的弹框场景. v3popup 在开发之初参考借鉴了Vant3.ElementPlus等组件化思想.并且功能效果和之前vue2.0保持一致. ◆ 快速引入 在main.js中全局引入v3p

  • php并发加锁问题分析与设计代码实例讲解

    在工作项目中,会遇到一些php并发访问去修改一个数据问题,如果这个数据不加锁,就会造成数据的错误.下面我将分析一个财务支付锁的问题.希望对大家有所帮助. 1 没有应用锁机制 1.1 财务支付简化版本代码 <!--?php /** * pay.php * * 支付没有应用锁 * * Copy right (c) 2016 * * modification history: * -------------------- * 2018/9/10, by CleverCode, Create * */

  • Vue组件层级关系详细分析

    目录 前言 一.全局组件的层级关系 二.局部组件的层级关系 前言 在这之前,我们已经了解到了vue的组件有哪一些以及这些组件有什么作用,关于组件的博客,大家可以看本博主的往期文章:传送门 可以关注更多的博文进行学习了解.好的,我们进入今天的主题,我们知道组件可以进行调用,网页也可以通过分割的方式在页面中进行嵌套,并且可以在组件层级形成父级和子级.兄弟级别的关系,使得网页开发更加的富有层次感. 一.全局组件的层级关系 全局组件之间的层级关系是在vue进行代码程序执行调用的时候才确定的.我们可以通过

随机推荐