Open Lucifier129 opened 9 years ago
确实,有时候并不一定流行的框架才是符合自己业务需求的.而且我也是个懒人,懒到什么程度呢?有时候宁愿自己造个自行车,也不愿花时间去学驾照Orz...
@margox 我也处于相似阶段,并认为这是必要的。自己造轮子,才知道别人的轮子怎么造的,以及为什么比我的造得好,或者哪里没我造的好。
controller逻辑 有点重,需要细分
@steelli 用 react 来管理 view ,用 flux 来管理 model/store,应该可以显著降低 controller 的逻辑厚度。
只有自己造过轮子,才能更好的看到别人轮子的优劣
我做业务组件的时候就是懒得用框架了,直接发布订阅事件搞定,哈哈
用MVC模式组织代码
前言
MVC
这个名词,在前端领域还处于意义不明确的阶段。打着MV*
名号的框架层出不穷,概括MVC
的文章也让人应接不暇。然而究竟什么是MVC
,那些作者各执一词。winter 做了下
正本清源
的工作:既然
经典MVC模式
与前端的view.onclick
天然的互斥,不再适用;既然大家都在打扮MVC
,本文也尝试重新演绎。介绍一种以Model
、View
与Controller
为命名的代码组织方案。这个方案给我带来了良好的编程体验,并且几乎立即可以应用在所有项目中,不管历史遗留的代码多么庞杂,新增的业务需求都能按照新方案进行组织。
Talk is cheap, show me the code
Github的todomvc项目,提供了各种以
MV*
为名号的框架的实现,帮助前端工程师选择合适的框架或库。其中的vanillajs版本,是一个无框架无库的原生JavaScript
实现;它也是按照MVC
的理念来组织代码。框架或库不是MVC
模式的必需品,只是说有了相应的框架与库,写起来更为便利。本文也准备了一个原生实现todos-vanillajs,可作MVC模式参考案例。
在线体验地址:http://lucifier129.github.io/todos-vanillajs/index.html
MVC模式
一个模块是一个文件夹
在一些
nodejs
与前端模块化编程
的介绍中,常常能看到一个文件就是一个模块
的说法,用module.exports
的值作为模块输出。暂且把这类模块叫做nodejs模块
或AMD/CMD模块
。我们真正关注的模块,其实是
业务模块
,它是指与DOM相关的视图模型、数据模型与事件交互模型
的总和。比如一个页面的header
模块,它包含html模板
、填充的数据
以及随着滚动高度而固定在顶部的事件交互
等结构。业务模块
不等价于AMD/CMD模块
!如果产生这个误解,可能将所有东西塞一个js文件
。只把html模板
提取出来,也不足够。一个
业务模块
应该是好几个AMD/CMD模块
的组合,它是一个文件夹,包含好几个AMD/CMD模块文件
,其中:view.js
文件对应视图模型
,存储html模板
,并提供根据数据输入渲染视图的方法、从视图中获取并输出数据的方法model.js
文件对应数据模型
,提供数据存储与数据处理的所有方法controller.js
文件对应事件交互模型
,提供事件绑定与组织视图模型和数据模型的所有方法app.js
对应业务模块出口文件
README.md
是一个描述业务逻辑
的markdown
文件,随业务逻辑变更而更新package.json
、data_mock.json
根据实际需求决定是否添加并且:
view
也应该变成文件夹,里面包含类似template.js
、todo-list.js
,filter.js
以及出口文件view.js
。view
跟model
绝不知道事件何时绑定,何时触发,一切事件逻辑都放在controller.js
中view
只对html模板
进行get/set
数据model
处理数据输入,数据转换、数据储存与数据输出ajax
行为,属于controller
,不属于model
;在success
回调函数里调用model
提供的方法处理数据controller.js
的一般形式如下:controller.js
拿到了视图模型与数据模型,也就掌握了如何处理数据、如何渲染视图的所有方法;关于数据处理与视图渲染的时机问题,则由设计事件绑定来完成。所以它是事件交互控制器
。定义和调用分离
todomvc
是一个功能简单的页面,因此用一个js文件夹
足以。其中的view.js
、model.js
以及controller.js
都只是定义了一些方法接口
,app.js
这个出口文件才产生了调用。视图只有7个信息渲染点,用6个
类
定义了渲染方法。没有产生调用。数据模型
Model
提供了所有跟数据处理相关的方法。没有产生调用。事件交互控制器
虽然写了与业务逻辑耦合严重的硬编码,比如事件代理的各个特定的selector
;但是它仍然封装在实例方法中,不形成调用。真正的调用,发生在出口模块中,并且也是因为此app.js是整个页面的出口模块。假设它只是其中一个
业务模块
,很多时候也不应调用init
方法,而是放到页面出口模块
中,择时机初始化。定义与调用分离的好处:
业务模块
可以无副作用的复用你的view/model/controller
提供的方法尾声
以上所谓的
MVC模式
,算不上最佳实践
,只是一个经验分享
。如果你有好的建议,或者更好的方案,欢迎指出与分享。