JS控件的生命周期介绍


Posted in Javascript onOctober 22, 2012

JS控件的生命周期跟其他平台UI的生命周期类似,但是又有自己的特点,我们只有将控件的生命周期划分清晰,所有的控件编写、mixins的编写和plugin的编写才能遵循控件的生命周期做统一的管理。在这里我把JS的生命周期定义为4部分:

1.initializer: 初始化,做一些不牵扯DOM操作的初始化操作
2.createDom: 创建 DOM,在这个过程中我们创建控件需要的DOM结构
3.renderUI: 生成控件的内部元素,在这里调用子控件的渲染方法,开启子控件的生命周期
4.bindUI: 绑定事件,可以绑定子控件事件也可以绑定内部DOM的事件
5.synUI: DOM结构以及子控件生成完毕后,我们在配置项中传入的值或者默认的配置项要应用到DOM上,例如 width,height,focusable之类的属性
6.destructor: 析构函数,移除控件,清理控件上的事件,清理子控件,清理控件自己的DOM以及控件的一些对其他控件的引用。

JS控件的生命周期介绍
1

初始化:

控件初始化过程中做以下事情:
1.调用继承的父类的初始化函数,包括原型链上的父类和mixins
2.处理配置项,合并默认配置项和用户传入的配置项
3.处理绑定到改对象的事件
4.初始化插件(plugin)
初始化完成后,是否创建DOM看具体的策略,类似于ext的实现,可以延迟创建DOM

创建DOM

创建DOM的过程如下:
1.调用继承的父类的创建DOM的函数,包括原型链上的父类和mixins
2.创建控件的DOM
3.调用控件插件的创建DOM的函数

渲染子控件和内部DOM操作

执行过程如下:
1.调用父类的渲染函数,包括原型链上的父类和mixins
2.调用插件的渲染函数
我们可以在顶级的父类来初始化子控件。好处是,子类不需要做子控件初始化的操作此时:
1.如果子控件还未初始化则执行初始化
2.继续执行子控件的创建DOM、渲染子控件、绑定事件、同步配置项函数执行
绑定事件
由于此时控件的DOM和内部的子控件已经渲染完毕,则可以在子控件或者DOM上绑定事件。绑定事件的过程:
1.调用父类的绑定事件方法,包括原型链上的父类和mixins
2.调用插件(plugin)的绑定事件方式
注意:在子控件或者内部DOM上绑定事件时,使用委托,不要直接在子控件或者DOM上绑定事件,一旦子控件添加或者删除,内部DOM变化都会引起事件失效。

同步配置项

首先说明一下什么叫做同步配置项,前面我们在初始化控件时,已经对配置项做过一定的处理(至于如何处理,后面讲 JS控件属性 的时候会讲到),但是配置项并未作用到DOM上或者内部子控件上。
为什么在这时候处理同步,而不是在创建DOM和渲染子控件时,有2个原因:
1.在创建DOM和渲染子控件时,所有的DOM和子控件并未完整生成此时同步需要进行大量判断
2.我们需要把同步配置项的工作提取成方法,修改配置项时,内部DOM和子控件跟着变化。

例如:配置项里有 { width : 100 }
1.如果我们在渲染DOM时同步,则可能把“width=100px;”直接设置到DOM上,而到我们需要修改这个width时,我们还需要写一个函数来设置这个值。
2.反之,我们把同步配置项集中处理,将一个个的同步配置项的过程抽取成一个个函数,那么我们初始化 width的过程和修改width的过程完全一样,这样概念和逻辑就统一起来。
同步配置项的过程依然如其他步骤一样:
1.调用父类的同步方法,包括原型链上的父类和mixins
2.调用插件(plugin)的同步方法
注意:我们应该可以配置一个配置项是否在此时同步,原因有很多,比如多个配置项会产生同一操作,如果多个配置项同时同步,那么一个过程会反复执行多次。
移除控件
任何对象都有构造函数,必定也有析构函数,但是这个函数往往是大家最容易忽视的地方,但是也是非常重要的地方,暂且不说内存泄露之类的问题,就是如果一个控件的移除工作做得不够好,会对正常的使用带来很大的麻烦。
这个函数又是最不好写的一个函数,因为它需要处理以下工作:
1.清理使用的其他控件,是否也移除看具体情形。区分 关联和聚合
2.清理子控件
3.清理绑定到控件和DOM上的事件
4.移除DOM
5.清理变量的引用,这个比较麻烦和繁琐,所以我们需要对控件的引用做统一的管理
同样此函数也要执行:
1.调用父类的析构函数,包括原型链上的父类和mixins
2.调用插件的析构函数

问题

上面讲的全部是具体的步骤,但是在实现的时候遇到了一系列的问题:
1.调用父类的方法存在问题
1)调用原型链上的父类方法,只能使用 className.superclass.method.call(this)这类的方法,this.constructor.superclass.method.call(this)不能使用,原因在 js 控件继承 的extend一章中有讲到,这种调用方式繁琐而且维护不方便。
2)调用mixins上的方法,在JS 继承 mixins一章中我讲到过mixins的实现原理,覆盖同名方法,mixins的方法其实已经作为控件的prototype上的方法,所以最好不要使用同名方法,如果多个mixins都是用 renderUI,synUI之类的方法,而继承这些mixins的控件没有实现renderUI这类方法,那么就会被覆盖。
2.调用插件的方法也存在问题
1)我们需要获得当前控件的引用

解决方式:

1. 针对调用父类的方法我们可以在控件渲染时,按照原型链的顺序,先调用父类的方法再调用子类的方法直到当前控件:
JS控件的生命周期介绍

如上面的继承关系,我们执行C.renderUI()时,按照继承原型链的顶层向下执行。
2. 执行minxins的方法,我们执行renderUI时,去依次执行 mixin 的__renderUI方法。
3. 执行父类的renderUI 时,如果也存在mixins那么执行mixin的 __renderUI方法。

JS控件的生命周期介绍

图3

如上图所示: inherits表示原型链继承,extends表示 mixin扩展
那么c.renderUI的执行过程如下:

A.renderUI ->D.__renderUI->B.renderUI->E.__renderUI->C.renderUI
3. 调用插件方法时需要传递控件本身的引用即可,如:
plugin1.render(this)
4. 析构函数 destructor比较特使,执行的顺序跟上面2中讲的顺序有所不同:
子类 destructor -> 子类扩展 destructor -> 父类 destructor -> 父类扩展 destructor
按照图3的继承结构其析构函数执行的顺序是:
C. destructor ->E.__destructor->B.destructor->E.__destructor->a.destructor
原因是,子类的一些引用依赖于父类或者扩展类,如果父类和扩展类先执行析构函数,那么子类在使用某些变量/属性时会报错。
JS控件的生命周期介绍
这一节我把控件的生命周期讲了一遍,所有的着一些都是来自于 KISSY框架的UIBase,感兴趣的可以去看一下,非常精彩的实现http://docs.kissyui.com/kissy/docs/#!/api/KISSY.Component.UIBase的

Javascript 相关文章推荐
超级24小时弹窗代码 24小时退出弹窗代码 100%弹窗代码(IE only)
Jun 11 Javascript
UserData用法总结 lanyu出品
Jul 01 Javascript
javascript实时显示北京时间的方法
Mar 12 Javascript
以JavaScript来实现WordPress中的二级导航菜单的方法
Dec 14 Javascript
基于jquery实现三级下拉菜单
May 10 Javascript
Bootstrap开关(switch)控件学习笔记分享
May 30 Javascript
Javascript基础_简单比较undefined和null 值
Jun 14 Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 jQuery
JavaScript箭头函数中的this详解
Jun 19 Javascript
vue-router跳转时打开新页面的两种方法
Jul 29 Javascript
vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作
Aug 06 Javascript
在HTML中使用JavaScript的两种方法
Dec 24 Javascript
重写javascript中window.confirm的行为
Oct 21 #Javascript
js indexOf()定义和用法
Oct 21 #Javascript
javascript window.confirm确认 取消对话框实现代码小结
Oct 21 #Javascript
基于jquery DOM写的类似微博发布的效果
Oct 20 #Javascript
JS的replace方法介绍
Oct 20 #Javascript
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 #Javascript
JavaScript 用cloneNode方法克隆节点的代码
Oct 15 #Javascript
You might like
PHP查询数据库中满足条件的记录条数(两种实现方法)
2013/01/29 PHP
如何在smarty中增加类似foreach的功能自动加载数据
2013/06/26 PHP
在Ubuntu 14.04上部署 PHP 环境及 WordPress
2014/09/02 PHP
如何修改Laravel中url()函数生成URL的根地址
2017/08/11 PHP
基于JQuery的数字改变的动画效果--可用来做计数器
2010/08/11 Javascript
javascript 45种缓动效果 非常酷
2011/06/28 Javascript
通过正则格式化url查询字符串实现代码
2012/12/28 Javascript
jquery验证手机号码、邮箱格式是否正确示例代码
2013/07/28 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
2014/01/10 Javascript
jQuery+jRange实现滑动选取数值范围特效
2015/03/14 Javascript
深入分析jsonp协议原理
2015/09/26 Javascript
基于jQuery实现表格内容的筛选功能
2016/08/21 Javascript
js获取指定字符前/后的字符串简单实例
2016/10/27 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
详解Angular5路由传值方式及其相关问题
2018/04/28 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
在Vue中使用this.$store或者是$route一直报错的解决
2019/11/08 Javascript
解决vue-cli 打包后自定义动画未执行的问题
2019/11/12 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
在Python中使用PIL模块对图片进行高斯模糊处理的教程
2015/05/05 Python
Python3多进程 multiprocessing 模块实例详解
2018/06/11 Python
python3.6、opencv安装环境搭建过程(图文教程)
2019/11/05 Python
在python tkinter界面中添加按钮的实例
2020/03/04 Python
Django:使用filter的pk进行多值查询操作
2020/07/15 Python
python使用smtplib模块发送邮件
2020/12/17 Python
我们没有写servlet的构造方法,那么容器是怎么创建servlet的实例呢
2013/04/24 面试题
大学生水果店创业计划书
2014/01/28 职场文书
委托公证书
2014/04/08 职场文书
2014乡镇党政班子四风问题思想汇报
2014/09/14 职场文书
群众路线教育实践活动对照检查材料
2014/09/22 职场文书
单位实习工作证明怎么写
2014/11/02 职场文书
安全隐患整改报告
2014/11/06 职场文书
会计岗位工作总结
2015/08/12 职场文书
如何才能写好调研报告?
2019/07/03 职场文书
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers
全新239军机修复记
2022/04/05 无线电