Home  >  Article  >  Web Front-end  >  JavaScript component journey (1) analysis and design_javascript skills

JavaScript component journey (1) analysis and design_javascript skills

WBOY
WBOYOriginal
2016-05-16 18:43:071017browse

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

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

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

Queue

Queue

图片来自 Wikipedia.

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

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

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

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

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

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

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

aaa

设计初期的对象图

Notice that <font face="新宋体">Dependency</font> actually doesn’t do anything, and the two methods of <font face="新宋体">Queue</font> can be left to <font face="新宋体">TaskManager</font> & <font face="新宋体">Task</font> respectively. Which object is responsible for a method is a topic that can easily cause controversy and is beyond the scope of our discussion. This time, our focus is on using JavaScript to implement this component. Combining the unique language features of JavaScript, we envision implementing the above four objects:

  • <font face="新宋体">TaskManager</font> is implemented directly through Object. In the JavaScript world, objects can be used as natural static classes - you can directly define attribute methods <font face="新宋体">ClassObject</font> in the "class" <font face="新宋体">property</font> and reference <font face="新宋体">CassObject.property</font> as a static class.
  • <font face="新宋体">Queue</font> is reflected in the form of an array (Array), and <font face="新宋体">Task</font> is each item stored in the array. To operate <font face="新宋体">Queue</font>, you must define some instance methods in its prototype. Since each Queue instance is a native array, in order to reduce the intrusion into <font face="新宋体">Array.prototype</font>, we can consider defining these methods on <font face="新宋体">Task.prototype</font>— —Shift responsibilities to tasks.
    Gather three <font face="新宋体">Queue</font> arrays together to form a "big array" to represent three queues with different priorities. This large array can be used as an attribute of <font face="新宋体">TaskManager</font>.
  • The core of a task is a function. You can directly use function to represent a task, but considering that it has its own unique attributes (priority, dependencies, etc.) and is the most frequently operated object, it may be used in the future. will be extended, so we decided to define it as an object separately.
  • The dependency exists directly in the form of an array as an attribute of <font face="新宋体">Task</font> - <font face="新宋体">Task</font> puts the other multiple <font face="新宋体">Task</font> identifiers of the dependency in this array, and no longer defines this object separately.

After analysis, the situation gradually became clear - we need to simplify the four objects into two: <font face="新宋体">TaskManager</font> & <font face="新宋体">Task</font>, and use native arrays for the other two objects To achieve:

refactored-object-diagram

Simplified object model

I also noticed that this is implemented with arrays many times, and the coding process must involve array traversal, search and other operations. JavaScript 1.6 has already implemented these array operations for us. In order to take full advantage of the native methods built into arrays and still run in older browsers, we used Eric's code. In this way, we can directly use methods such as <font face="新宋体">forEach<code><font face="新宋体">forEach</font>/<font face="新宋体">indexOf<code><font face="新宋体">indexOf</font> and pay more attention to the components Functional implementation and better performance in modern browsers.

~~~~~~~~~~~~~ Bagua Dividing Line ~~~~~~~~~~~~~

Well, after seriously analyzing the component design, it’s time to embark on a happy journey of coding implementation. Don't worry, <font face="新宋体">TaskManager</font> seems a bit tacky: it is not enough to express a task queue with priority and dependency management, and using it as a namespace may conflict with other code. Well, let’s call this component <font face="新宋体">Smart Queue<code><font face="新宋体">Smart Queue</font>, loud and unique.^^

The analysis and design are done, and the name is also given. If you want to know the specific implementation process, please listen to the next chapter for breakdown.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn