前端之旅:原生JS实现单页GTD应用

从时间跨度上来说,几乎是两个月的时间,因为是在过年期间,所以会精力比较分散。
在1月下旬就完成了界面布局的工作,但是一直在思考尝试如何组织代码结构和数据结构。虽然说说网上有这方面的文章和书籍,但是我认为最开始还是要脱离别人的思维限制,先自己尝试更好,锻炼了自己的架构和思考能力,也会更清楚在无从下手到从0开发一个完整的项目的流程和遇到的问题,等完成后再对比成熟的方案也不失为一个好方案。在多次思考分析利弊之后,整个todo应用数据存储有了一个比较理想的方案,当然,数据都是存储在localStorage中,而整个软件采用模块模式来开发,但是被我分成了几个小模块。

模块

模块模式可以避免全局变量污染,并且可以很好的解耦。可能是我对模式的理解有偏差,我理想中应该是这样的架构,如下图,要涉及到发布/订阅模式以及MVC,但是不知道是否合适,因为js事件从本质来说就是发布/订阅模式(也可以说观察者)模式。毕竟是第一次实践设计模式的知识,只有慢慢试探了。

但是我最终完成的架构却是这样的,整个app分为4个模块,分类列表主要负责分类的列表数据和模板,todo列表负责分类的数据和模板,todo详情部分负责单条todo的详情和展示模板等,一个app部分负责协调上述几个部分的工作。这并不是很好的设计,最主要的问题是其中的模板对数据的依赖导致耦合严重,在后面的重构过程中将改变整个软件架构。

该应用的代码架构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//分类
categoryModule = (function(){
//操作 model & template
//返回接口
});
//todo列表
todoModule = (function(){
//操作 model & template
//返回接口
});
//todo详情
todoDetail = (function(){
//操作 model & template
//返回接口
});
//app controller
appModule = (function(){
//code
return {
init: function() {
//初始化分类列表
//初始化todo列表
//初始化todo详情界面
//初始化事件绑定
//等待用户交互触发事件并分发事件
}
};
});

数据存储

  • 所有分类数据汇总存储到一个对象,每个分类就是该对象中一个用id作为键值的对象,这样做是为了方便按id索引单条分类数据,每条分类数据都是独立的,没有嵌套关系。
  • 整个对象中有一个在程序初始化时创建的分类对象作为顶级分类用于保存一级二级以及更多子分类,类似于DOM中的根节点。
  • 每个分类对象保存了父分类id和子分类id映射表和,熟悉DOM的同学一下就能get到这是借鉴了DOM的思想,不同的是这里不是保存引用。
  • 每个分类也保存了该分类下的todo列表映射,添加删除todo时要维护此表。
  • todo数据是按照id单独存放的,也就是说,要获取todo,知道它的id后直接从localStorage中取出来,这样做也是因为方便对单条todo进行操作。

以下是具体数据结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//分类列表
{
"cid_1": {},
"cid_2": {},
}

//单条分类
{
"addTime":1487710962417, //添加时间
"cid":"cid_1487710962417", //分类id
"pid":"cid_0000000000001", //父分类id
"title":"未命名分类1", //分类名
"childCatList":[ //保存直接子分类
"cid_1487883840564",
"cid_1487980933649"
],
"childTodoList":[ //保存直接子todo
"tid_1487776376694",
"tid_1487776391312",
]
}

//单条todo
{
"addTime":1487776376694, //添加时间
"tid":"tid_1487776376694", //todo id
"cid":"cid_1487710962417", //分类id
"emergency":0, //紧急程度,暂时没用上
"title":"未命名任务", //todo标题
"content":"出门交电费", //todo内容
"status":1, //状态1和-1
"expireTime":1487721600000 //失效时间
}

完成

在2月25号完成了该任务,翻看了一下IFE2015 task3的初级班和中级班的提交列表,发现自己实现得算是非常好的了,不过也花了好长时间。下面上图:

遇到的问题:

  • 高度自适应布局,最开始我使用了float来布局,但是高度不能自适应
    解决:最后在网上找到了高度自适应布局方案,使用了绝对定位技术,设置top和bottom为0或者你需要撑开的上下间隔即可。
  • 分类列表和todo列表设置了overflow:scroll,但是不管内容有没有超出滚动条都始终显示在那里很碍眼。
    解决:设置overflow为auto而不是scroll
  • 待解决:如何架构这个程序?

接下来的计划就是看完《设计模式》剩下的几章,以及刷一遍CSS3,ES6,然后开始学习React或者Vue就找工作了。

这篇文章不是一笔写成,而是在完成任务三的过程中多次更新,所以不以发布时间为准。

avatar

神无

舍悟离迷,六尘不改。