谈谈组件开发

提高开发效率,主要途径有两点:加快开发速度,减少变更代价。怎样才能加快开发速度呢?如果我们的开发不是重新造轮子,而是每一次做新产品都可以利用已有的东西,那就会好很多。因此组件化开发就变得重要起来...... 《谈笑风生组件化》 

原文链接:http://www.cnblogs.com/dojo-lzz/p/5222895.html

组件的基本修养

  任何一个华丽的思想都有一套朴实的代码实现。上面我们从抽象的层次上谈了谈组件的概念,放到实际的代码世界,该如何去实现呢?众所周知,JavaScript是一门面向对象语言,面向对象语言最重要的特性就是——抽象。放到实际开发中就是定义一个基类,应用的我们现在的场景,我们需要一个组件基类——Component。由这个基类来提供组件的基础功能。具体都应该有什么方面的基础功能呢?别急,这个问题先放一放。

  组件的管理

  先看一下上面的这张图,我们会发现,整个页面都是由不同的功能的业务组件组成的。这就引出了另一个问题,当一个页面的组件非常多时,我们需要一套统一管理的仓库——CRepository。每一个组件都要将自身id向仓库注册,仓库提供管理功能,如增删改查。具体的方法由实际应用而异,但几个通用的方法可以参考:

复制代码
count: Number.//整个app中组件的数量

add: function(component){....} //将一个组件添加到仓库中

remove: function(id){....} //将一个组件从仓库中移除

byId: function(id){....} //根据id从仓库中查找组件
复制代码

  了解完仓库之后,我们便可以将主要精力放回到Component上了。

  组件的生命周期

  生命周期这个概念最早在软件工程中接触到,可惜我对那些枯燥的理论没有什么兴趣,上起课来云里雾里,早就还给教授了。那我就举一个大家都有体会的例子。组件如人,人的生命有尽头,组件的生命必然有。将组件的生命周期分割成不同的几个阶段来处理不同的逻辑,就如同人的一生不同阶段要面对不同的烦恼一样。

复制代码
constructor:function(){} //构造函数,处理外部参数

mixinProperties:function(){} //在这个阶段,混入必要的属性

parseTemplate:function(){}//在这个阶段解析模板,将模板由字符串转化成dom节点

postCreate:function(){}//在这个阶段,模板解析完毕,可以访问component的根节点cRoot。此时可以对组件的dom树进行访问或绑定事件。但此时组件还未加到页面dom树中。

startup:function(){}//此时组件以加入dom树中,这里可以在组件加入页面dom后做一些初始化工作。对于嵌套组件,需要处理子组件的startup

destroy:function(){}//组件生命结束,进入销毁阶段,从组件仓库中注销
复制代码

  凡是比喻就一定有失真的地方,组件的生命当然不可能与人相比,但我却发现上面的生命周期与婴儿从被怀孕与诞生的过程极其相似。

复制代码
constructor:function(){} //受精卵状态

mixinProperties:function(){} //染色体重组

parseTemplate:function(){}//婴儿在母体内的生长发育过程

postCreate:function(){}//婴儿在母体内生长发育完成,母亲即将临盆

startup:function(){}//婴儿出生,被社会认可

destroy:function(){}//个体消亡,取消社会户籍等等
复制代码

  

  组件的属性访问器

  对于组件内部数据的访问,应当对外提供统一的访问渠道,通常来讲这部分内容就是属性的取值器与赋值器(get和set)。

set(prop, value)//为组件的某个属性赋值

get(prop)//为从组件中取得某个属性值

  要明确的一点是,这里的set与get不仅仅像点语法一样单纯的赋值与取值,否则就是画蛇添足。使用过C#的兄台知道,C#中存在“属性的Get与Set”,它们能够避免直接对字段进行访问,这里提到组件的get与set应当具有同样的功能,具体的实现方式敬请关注后续文章。

  组件的模板解析

  遇到模板通常会遇到数据绑定的需求,可能是双向绑定也可能是单向绑定。双向绑定如众多的MVVM框架,模板解析过程中可能会读取组件内数据来渲染dom元素,亦或者组件dom树生成后,dom元素的变动即可作用于组件内部数据。单向绑定常出现在MVC框架中,如dojo,只是将dom元素与组件内部某个属性绑定,或者将交互事件与组件内部方法绑定。

    JavaScript中没有注解特性,所以众多绑定功能都是在template中添加自定义特性,并在解析过程中处理自定义特性。

  说到事件的绑定,事件带来的内存泄露问题不容忽视。这就要在组件销毁时,一并处理组件内部绑定的事件。包括在模板中绑定的事件与组件内部手动绑定的事件。

  组件关系

   当一个页面变得越来越复杂时,组件之间必然会出现嵌套。嵌套意味会出现父子关系、兄弟关系等。嵌套的管理可以参照DOM中的层级关系,提供相应的处理方法。但通常来讲,只需要管理好父子关系即可,兄弟关系的管理往往太复杂,而且通常情况下,一个getChildren,然后根据索引便能满足需求。所以大部分类库中组件关系的管理,往往只需要两个方法:

getParent:function(){}//获取组件的父组件

getChildren:function(){}//获取组件内部所有子组件

   组件通信

  组件变得复杂增多时,另组件之间如何通信的问题便被应当被提上议事日程。JavaScript本身便适用于消息驱动,处理组件间的通信当然要就地取材,事件机制便是最佳方案,所以前端组件应当在事件机制(往往是语义事件)的基础 提供通信功能。组件应当既可以接收事件也可以发送事件,于是应当分别提供方法:

on:function(component, eventName, handler) //用于绑定组件事件

emit:function(eventName, event) //组件对外发送事件

  组件的销毁

  组件的销毁属于组件生命周期的一部分,当组件功能变得复杂,组件正确合理的销毁就变得尤为重要。组件的销毁通常要考虑以下几个方面:

  • 组件内部事件的解绑
  • 组件dom的销毁
  • 组件内部属性的销毁
  • 子组件的销毁
  • 组件注销  

  组件的解析

  如果所有的组件都要通过new class的方式去手动初始化,这本无可厚非,然而在现今标签化语言盛行的时代,是否能够有一种更为方便的开发方式,将自定义组件也能够以标签化的方式来书写。答案是肯定的,主流的类库对此一般有两种做法:一种是完全的自定义标签方式,如angular2;一种是以自定义标签特性的方式,如dojo等。所有的这些都需要基础库能够提供组件解析的功能。

  通常的思路是以深度优先搜索的方式,扫描整个DOM树,解析自定义标签、自定义特性,将其实例化成自定义组件。有意思的是,因为组件嵌套关系的存在,自定义组件之间就像DOM树一样也是一个倒长的树形结构。

了解更多 前端内容

原文地址:https://www.cnblogs.com/zhengwenping/p/5243044.html