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 相关文章推荐
Jquery Ajax 学习实例2 向页面发出请求 返回JSon格式数据
Mar 15 Javascript
JQuery分屏指示器图片轮换效果实例
May 21 Javascript
详解Webwork中Action 调用的方法
Feb 02 Javascript
学习Angular中作用域需要注意的坑
Aug 17 Javascript
前端面试知识点锦集(JavaScript篇)
Dec 28 Javascript
angularjs实现下拉列表的选中事件示例
Mar 03 Javascript
vue项目中v-model父子组件通信的实现详解
Dec 10 Javascript
在 Angular-cli 中使用 simple-mock 实现前端开发 API Mock 接口数据模拟功能的方法
Nov 28 Javascript
js实现全选反选不选功能代码详解
Apr 24 Javascript
vue使用video.js进行视频播放功能
Jul 18 Javascript
基于layPage插件实现两种分页方式浅析
Jul 27 Javascript
layui 实现表单和文件上传一起传到后台的例子
Sep 16 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
fgetcvs在linux的问题
2012/01/15 PHP
php中设置index.php文件为只读的方法
2013/02/06 PHP
基于PHP实现等比压缩图片大小
2016/03/04 PHP
PHP判断是否是微信打开,浏览器打开的方法
2018/03/14 PHP
PHP去除空数组且数组键名重置的讲解
2019/02/28 PHP
IE 缓存策略的BUG的解决方法
2007/07/21 Javascript
js 图片轮播(5张图片)
2008/12/30 Javascript
JQUERY 浏览器判断实现函数
2009/08/20 Javascript
dojo随手记 gird组件引用
2011/02/24 Javascript
javascript中[]和{}对象使用介绍
2013/03/20 Javascript
运行Node.js的IIS扩展iisnode安装配置笔记
2015/03/02 Javascript
jQuery手动点击实现图片轮播特效
2020/04/20 Javascript
react实现antd线上主题动态切换功能
2019/08/12 Javascript
VUE UPLOAD 通过ACTION返回上传结果操作
2020/09/07 Javascript
如何在vue中使用kindeditor富文本编辑器
2020/12/19 Vue.js
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
[58:21]DOTA2亚洲邀请赛 4.3 突围赛 Liquid vs VGJ.T 第二场
2018/04/04 DOTA
下载官网python并安装的步骤详解
2019/10/12 Python
python实现差分隐私Laplace机制详解
2019/11/25 Python
python Tensor和Array对比分析
2020/01/08 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
python字符串下标与切片及使用方法
2020/02/13 Python
浅析pip安装第三方库及pycharm中导入第三方库的问题
2020/03/10 Python
python os.listdir()乱码解决方案
2021/01/31 Python
python 中 .py文件 转 .pyd文件的操作
2021/03/04 Python
中国旅游网站:同程旅游
2016/09/11 全球购物
宣传策划类求职信范文
2014/01/31 职场文书
岗位聘任书范文
2014/03/29 职场文书
演讲比赛策划方案
2014/06/11 职场文书
法英专业大学生职业生涯规划书范文
2014/09/22 职场文书
写景作文评语集锦
2014/12/25 职场文书
JavaScript数组reduce()方法的语法与实例解析
2021/07/07 Javascript
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript
搞笑Gif:这么白这么长的腿像极了一楼的女朋友
2022/03/21 杂记
Java 定时任务技术趋势简介
2022/05/04 Java/Android
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
2022/06/14 Golang