怎么写一份好的政协提案怎么写让上司接受,关于软件公司运作系统模块化,研发人员模块化工作

以下试题来自:
名词解释模块化 参考答案是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足...
您可能感兴趣的试卷
你可能感兴趣试题
1.问答题 参考答案1.设想供选择的方案2.选取合理的方案3.推荐最佳方案4.功能分解5.设计软件结构6.设计数据库7.制定测试计划8.书写文档9.审查和复审2.问答题 参考答案
系统设计阶段,确定系统的具体实现方案;
结构设计阶段,确定软件结构。
3.问答题 参考答案总体设计又称为概要设计或初步设计。确定系统功能是实现。基本任务是:建立软件系统结构(划分模块、定义模块功能、模块间的调用...如何开始一个模块化可扩展的Web App
本帖最后由 AlloVince 于
18:31 编辑
虽然从没有认为自己是一个前端开发者,但不知不觉中也积累下了一些前端开发的经验。正巧之前碰到一道面试题,于是就顺便梳理了一下自己关于Web App的一些思路并整理为本文。
对于很多简单的网站或Web应用来说,引入jQuery以及一些插件,在当前页面内写入简单逻辑已经可以满足大部分需要。但是如果一旦多人开发,应用的复杂程度上升,就会有很多问题开始暴露出来:
数据源一般都与页面分离,那么App启动一般都需要等待数据源读入。UI交互复杂时,需要将逻辑通过面向对象抽象后才能更好的复用。功能间一般都存在依赖关系,需要引入支持依赖关系的模块加载器。
那么如何解决这些问题,就以一个简单的订餐App为例,从零开始一个。
这个简单的App基于HTML5 Boilerplate、requireJS、jQuery Mobile、Underscore.js,后端逻辑用模拟实现。完成后的成品。所有代码可以。下文将逐一介绍实现的思路与方法。
从选择一个好模板开始
开始一个Web项目,HTML的书写总是重中之重,一个好的HTML能从根源上规避大量潜在问题,所以Web App应该全部应用一个标准化的高质量HTML模板,而不是将所有页面交由开发人员自由发挥。
这里推荐使用作为App的默认模板以及文件路径规范,无论是网站或者富UI的App,都可以采用这个模板作为起步。
git clone git:///h5bp/html5-boilerplate.git
或者直接下载。HTML5 Boilerplate的文件结构如下,
&pre&&code&.
├── css
│& &├── main.css
│& &└── normalize.css
├── doc
├── img
├── js
│& &├── main.js
│& &├── plugins.js
│& &└── vendor
│& && & ├── jquery.min.js
│& && & └── modernizr.min.js
├── .htaccess
├── 404.html
├── index.html
├── humans.txt
├── robots.txt
├── crossdomain.xml
├── favicon.ico
└── [apple-touch-icons]&/code&&/pre&复制代码从上向下看
css 用于存放css文件,并内置了作为默认CSS重置手段(其实Normalize.css不能算是CSS reset)。doc 存放项目文档img 存放项目图片js 存放javascript文件,其中第三方类库推荐放在vendor下.htaccess 内置了很多对于静态文件在Apache下的优化策略,如果Web服务器不是Apache则可以参考。404.html 默认的404页面,index.html 项目模板humans.txt 相对于面向机器人的robots.txt,humans.txt更像是小幽默,这在里可以写关于项目/团队的介绍,或者放置一些彩蛋给那些喜欢对你的应用刨根问底的用户们。robots.txt 用于告诉搜索引擎蜘蛛爬行规则crossdomain.xml 用于配置favicon.ico apple-touch-icon.png等小图标。
如果是一个主要面向移动设备,还有更具针对性的可供参考。
制定统一的编码规范
在正式开始编码之前,无论是多大规模的应用,多少人的团队,一定要有一个统一的规范,才能保证后续的开发不会乱套。
前端规范其实又要分为三部分:HTML、CSS、Javascript应该分别由自己的规范。HTML/CSS主要约定id/class的命名规则、属性的书写顺序。JavaScript可能需要细化到缩进、编码风格、面向对象写法等等。
最省事的方法当然还是参考已有的规范,比如、等等。
HTML5 Boilerplate的模板核心部分不过30行,但是每一行都可谓千锤百炼,可以用最小的消耗解决一些前端的顽固问题:
使用条件注释区分IE浏览器
&pre&&code&&!DOCTYPE html&
&!--[if lt IE 7]&& && &&html class=&no-js lt-ie9 lt-ie8 lt-ie7&& &![endif]--&
&!--[if IE 7]&& && && &&html class=&no-js lt-ie9 lt-ie8&& &![endif]--&
&!--[if IE 8]&& && && &&html class=&no-js lt-ie9&& &![endif]--&
&!--[if gt IE 8]&&!--& &html class=&no-js&& &!--&![endif]--&&/code&&/pre&复制代码之所以要这样写
可以使用class作为全局条件区分低版本的IE浏览器并进行调整,这显然要优于使用CSS Hack。可以避免,原文的解决方法是在前面加一个空白的条件注释,但是这里显然将原本无用空白的条件注释变得有意义了。仍然可以通过HTML验证。与Modernizr等特征检测类库使用相同的class,更具备通用性。
no-js标签是需要与Modernizr等类库配合使用的,如果你不想在项目中引入Modernizr,需要在Head部分加入一行使no-js标签变为js,代码来自:&script&(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)&/script&复制代码通过上面的条件注释,就可以在CSS中针对不同情况分别处理.lt-ie7 {} /* IE6等版本时 */
.no-js {} /* JavaScript没有启用时 */复制代码meta标签的书写顺序
为了让浏览器识别正确的编码,meta charset标签应该先于title标签出现。
meta X-UA-Compatible标签可以指定IE8以上版本浏览器以最高级模式渲染文档,同时如果已经安装则直接使用Chrome Frame渲染。而指定渲染模式的
&meta charset=&utf-8&&&meta http-equiv=&X-UA-Compatible& content=&IE=edge,chrome=1&&&title&&/title&
设置移动设备显示窗口宽度
&meta name=&viewport& content=&width=device-width&&
这是移动设备专属的标签,具体设置需要根据项目实际情况调整。
使用Modernizr做浏览器差异检测
常做前端的应该都不陌生。引入Modernizr后,html标签的no-js将会被自动替换为js,同时Modernizr会向html标签添加代表版本检测结果的class。
对于低版本浏览器的向上兼容需要根据项目实际需求处理,Modernizr也非常周到的给出的。
CSS篇CSS重置及增强功能
HTML5 Boilerplate选择重置CSS。如果项目计划引入Twitter Bootstrap、YUI 3这些前端框架的话则可以移除,因为这些框架已经内置了Normalize.css。
同时HTML5 Boilerplate又引入了一个main.css,内置了一些基本的排版样式以及打印样式。
使用LESS或Sass生成CSS
在复杂应用中,如果还手写CSS的话将是一件痛苦的事情,大量的class前缀,复用样式需要来回copy等等。为了更好的扩展性,这里建议在项目中引入或。这代表着:
支持变量与简单运算支持CSS片段复用class/id样式嵌套
等一些更像是编程语言的特性。这对于提高开发效率是效果非常明显的。
以LESS为例,简单介绍一下LESS在Windows下如何应用到这个项目中:
下载并安装,nodejs会自动将自己加入系统路径。在cmd运行npm install -g less然后就可以通过lessc指令将less源文件编译为csslessc avnpc.less avnpc.css如果不使用nodeJs作为后端,最好在写LESS时采用watch模式,每次保存自动编译为css。这里需要安装一个辅助模块recess:npm install -g recess然后运行watchrecess avnpc.less:avnpc.css --watch
Javascript篇
使用requireJS按需加载
模块加载器的概念可能稍微接触过前端开发的童鞋都不会陌生,通过模块加载器可以有效的解决这些问题:
JS文件的依赖关系。通过异步加载优化script标签引起的阻塞问题可以简单的以文件为单位将功能模块化并实现复用
主流的JS模块加载器有,等,加载器之间可能会因为遵循的规范不同有微妙的差别,从纯用户的角度出发,之所以选requireJS而不是SeaJS主要是因为:
功能实现上两者相差无几,没有明显的性能差异或重大问题。文档丰富程度上,requireJS远远好于SeaJS,就拿最简单的加载jQuery和jQuery插件这回事,虽然两者的实现方法相差无几,但requireJS就有可以直接拿来用的Demo,SeaJS还要读文档自己慢慢折腾。一些问题的解决上,requireJS为关键词也更容易找到答案。
requireJS 加载jQuery + jQuery插件
可能对于一般Web App来说,引入jQuery及相关插件的概率是最大的,requireJS也亲切的给出了相应的解决方案及的文档及。
在最新的jQuery1.9.X中,jQuery已经在最后直接将自己注册为一个,即是说可以直接被requireJS作为模块加载。如果是加载旧版的jQuery有两种方法:
1. 让jQuery先于requireJS加载2. 对jQuery代码稍做一点处理,在jQuery代码包裹一句:define([&jquery&], function($) {& & // $ is guaranteed to be jQuery now */});复制代码requireJS的示例中,直接将requireJS与jQuery合并为一个文件,如果是采用jQuery作为核心库的话推荐这种做法。
同样对于jQuery插件来说也有两种方法
1. 在插件外包裹代码define([&jquery&], function($){& &&&// Put here the plugin code. });复制代码2. 在使用reuqireJS代码加载前注册插件(比如在main.js)中
requirejs.config({& & &shim&: {& && &&&&jquery-cookie&&&: [&jquery&]& & }});复制代码requireJS加载第三方类库
在实例的App中还用到了jQuery以外的第三方类库,如果类库不是一个标准的AMD模块而又不想更改这些类库的代码,同样需要提前进行定义:
&pre&&code&require.config({
& && &paths: {
& && && && &'underscore': 'vendor/underscore'
& && &},
& && &shim: {
& && && & underscore: {
& && && && &&&exports: '_'
& && && & }
& && &}
});&/code&&/pre&复制代码CSS文件的模块化处理
在requireJS中,模块的概念仅限于JS文件,如果需要加载图片、JSON等非JS文件,requireJS实现了一系列。
但是遗憾的是requireJS官方没有对CSS进行模块化处理,而我们在实际项目中却往往能遇到一些场景,比如一个轮播的图片展示栏,比如高级编辑器等等。几乎所有的富UI组件都会由JS与CSS两部分构成,而CSS之间也存在着模块的概念以及依赖关系。
为了更好的与requireJS整合,这里采用来解决CSS的模块化与依赖问题。
require-css是一个requireJS插件,下载后将css.js与normalize.js放于main.js同级即可默认被加载,比如在我们的项目中需要加载jQuery Mobile的css文件,那么可以直接这样调用:require(['jquery', 'css!../css/jquery.mobile-1.3.0.min.css'], function($) {});复制代码不过由于这个CSS本质上是属于jQuery Mobile模块的一部分,更好的做法是将这个CSS文件的定义放在jQuery Mobile的依赖关系中,最终我们的requireJS定义部分为:require.config({
& && &paths: {
& && && && &'jquerymobile': 'vendor/jquery.mobile-1.3.0',
& && && && &'jstorage' : 'vendor/jstorage',
& && && && &'underscore': 'vendor/underscore'
& && &},
& && &shim: {
& && && & jquerymobile : {
& && && && &deps: [
& && && && && & 'css!../css/jquery.mobile-1.3.0.min.css'
& && && && &]
& && && & },
& && && & underscore: {
& && && && &&&exports: '_'
& && && & }
& && &}
});复制代码在使用模块时,只需要:require(['jquery', 'underscore', 'jquerymobile', 'jstorage'], function($, _) {});复制代码jQuery Mobile的CSS文件就会被自动加载,这样CSS与JS就被整合为一个模块了。同理其他有复杂依赖关系的模块也可以做类似处理,requireJS会解决依赖关系的逻辑。
数据源的加载与等待
Web App一般都会动态加载后端的数据,数据格式一般可以是JSON、JSONP也可以直接是一个JS变量。这里以JS变量为例var restaurants = [
& & {
& && &&&&name&: &KFC&
& & },
& & {
& && &&&&name&: &7-11&
& & },
& & {
& && &&&&name&: &成都小吃&
& & }
]复制代码载入这段数据:$.getScript('data/restaurants.json', function(e){
& & var data = window.
& & alert(data[0].name); //KFC
});复制代码单一的数据源确实很简单,但是往往一个应用中会有多个数据源,比如在这个实例App中UI就需要载入用户信息、餐厅信息、订餐信息三种数据后才能工作。如果仅仅靠多层嵌套回调函数的话,可能代码的耦合就非常重了。
为了解决多个数据加载的问题,我习惯的解决方法是构造一个dataReady事件响应机制。var foodOrder = {
& & //数据载入后要执行的函数暂存在这里
& & dataReadyFunc : []
& & //数据源URL及载入状态
& & , dataSource : [
& && &&&{ url : 'data/restaurants.json', ready : false, data : null },
& && &&&{ url : 'data/users.json', ready : false, data : null },
& && &&&{ url : 'data/foods.json', ready : false, data : null }
& & ]
& & //检查数据源是否全部载入完毕
& & , isReady : function(){
& && &&&var isReady =
& && &&&for(var key in this.dataSource){
& && && && &if(this.dataSource[key].ready !== true){
& && && && && & isReady =
& && && && &}
& && &&&}
& && &&&return isR
& & }
& & //数据源全部加载完毕,则逐一运行dataReadyFunc中存放的函数
& & , callReady : function(){
& && &&&if(true === this.isReady()){
& && && && &for(var key in this.dataReadyFunc){
& && && && && & this.dataReadyFunc[key]();
& && && && &}
& && &&&}
& & }
& & //供外部调用,会将外部输入的函数暂存在dataReadyFunc中
& & , dataReady : function(func){
& && &&&if (typeof func !== 'function') {
& && && && &
& && &&&}
& && &&&this.dataReadyFunc.push(func);
& & }
& & , init : function(){
& && &&&var self =
& && &&&var _initElement = function(key, url){
& && && && &$.getScript(url, function(e){
& && && && && & //每次载入数据后,将数据存放于dataSource中,将ready状态置为true,并调用callReady
& && && && && & self.dataSource[key].data = window[key];
& && && && && & self.dataSource[key].ready =
& && && && && & self.callReady();
& && && && &});
& && &&&}
& && &&&for(var key in this.dataSource){
& && && && &_initElement(key, this.dataSource[key].url);
& && &&&}
& & }
}复制代码用法为foodOrder.dataReady(function(){
& &alert(1);& &&&
});
foodOrder.init();复制代码dataReady内的alert将会在所有数据载入完毕后开始执行。
这段处理的逻辑并不复杂,将所有要执行的方法通过dataReady暂存起来,等待数据全部加载完毕后再执行,更加复杂的场景此方法仍然通用。
使用JS模板引擎
数据载入后,最终都会以某种形式显示在页面上。简单情况,我们可能会这样做:$('body').append('&div&' + data.name + '&/div&');复制代码如果页面逻辑一旦复杂,比如需要有if判断或者多层循环时,这种连接字符串的方式就相形见绌了,而这也就催生出了JS模板引擎。
主流的JS模板引擎有,,等等,可以。
对于相对简单的页面逻辑(只需要支持if和for/each)来说,我更倾向选用轻巧的underscore.js或者。
在当前例子中,使用underscore.js生成列表就非常简单了,页面模板为:&ul data-role=&listview& data-inset=&true&&
&script id=&tmpl-restaurants& type=&text/template&&
& & &% _.each(data, function(restaurant) { %&
& && &&&&li&
& && && && &&a href=&#& data-rel=&back& data-value=&&%- restaurant.name%&&&&%- restaurant.name%&&/a&
& && &&&&/li&
& & &% }); %&
&/script&
&/ul&复制代码调用引擎$(&#tmpl-restaurants&).replaceWith(
& & _.template($(&#tmpl-restaurants&).html(), {
& && &&&data : restaurants
& & })
);复制代码面向对象与模块化
通过上面这些工具的组合,我们有了模块的概念,有了模板引擎,有数据的加载。最终还是要通过javascript将这一切组织在一起并加入应用所需要的逻辑。为了能最大限度的复用代码,用面向对象的方式去组织内容是比较好的选择。
JavaScript虽然原生并不支持面向对象,但是依然可以通过很多方式模拟出面向对象的特性。例子中采用了我个人比较喜欢的一种方式是:var foodOrder = function(ui, options){
& & //构造函数
& & this.init(ui, options);
}
foodOrder.prototype = {
& &defaultUI :&&{
& && & form : '#form-order'
& &}
& &, defaultOptions : {
& && & debug : false
& &}
& &, init : function(ui, options){
& && & this.ui = $.extend({}, this.defaultUI, ui);
& && & this.options = $.extend({}, this.defaultOptions, options);
& &}
}
var order = new foodOrder({
& & form : '#real-form'
}, {
& & debug : true
});复制代码将页面的UI元素以及配置项目抽象出来,在实际构造对象时则可以通过入口参数复写,可以分离整个项目的逻辑与UI,使处理的方式更加灵活。
挺好的,收藏了
爱点击互动(北京)广告有限公司薪金:面议职位:Web前端开发工程师
北京西瓜藤网络科技有限公司薪金:面议职位:Web开发工程师
网易薪金:144000(元/年)职位:实习前端开发工程师(页面重构)近日,央行首次注销了国内第三方支付公司浙江易士企业管理服务有限公司的支付牌照,彰...
IBM发现了一种新型的数据窃取恶意软件,叫做Corebot。它是一个高度模块化的恶意软件,...
安全公司Rapid7的安全研究人员发现,婴儿监视器中存在大量安全漏洞,这些漏洞包括:硬...
Malwarebytes的安全研究人员发现了一个广告软件安装程序正在访问MAC OS X的密码管理系...
UPnP中曝安全漏洞Filet-O-Firewall,将数百万家庭网络设备置于网络攻击风险之中。导致...医疗系统中模块化UPS应用方案
> 医疗系统中模块化UPS应用方案
医疗系统中模块化UPS应用方案
1 前言本文引用地址:近几年的集中化管理已成为一种发展趋势。对于数据中心、关键设备的保护更是重中之重,尤其是那些生命攸关的场所,如:洁净手术室pICU重症监护室pCCU心脏监护室、产房等场所重要电力负荷区,必须配备后备电源,其目的就是保证为该场所内的电气设备提供一个安全、可靠的电源保障,用以确保病人的生命安全、提高服务质量。我国日发布,12月1日开始实施的《医疗洁净手术部建筑技术规范》,其中8.3 配电要求:由于手术室的重要性,手述室内用电设备配电盘须加隔离变压器。某三甲综合医院,重要关键性典型负载的统计如下:洁净手术室 5个 房间(床位);ICU重症监护室20个房间(床位);产房5个房间(床位)。负载总容量预计为:100kVA 。2 配置2.1 台达配置用于医疗的台达电源配置列于表1。表1 UPS电源配置方案2.2 HIFT UPS供电方案说明为提高供电的安全、可靠性,传统供电方案是采用两台UPS单机并联冗余方式运行,虽然这在一定程度上提高了可靠性,但是它不便于在线维护、扩容,同时对设备的利用不充分、效率低、缺乏灵活性扩充,更重要的,系统的冗余数仅为1。而HIFT UPS采用设计的结构极具弹性,可实现模块N+X自动弹性组合冗余,供电系统拥有最高的可靠性。同时,客户还可通过定购额外的模块,来增加HIFT的备用冗余能力。HIFT UPS具有随需扩容的性能优势,可以按照现在的负载先进行配置,当机房负载扩容容量增加时,直接热插入模块,扩容灵活、方便,以20kVA一个模块为单位最大可扩充至480kVA的冗余供电系统。根据用户负载需求,台达提供一种更经济的HIFT UPS供电系统冗余配置方案,采用HIFT 120kVA UPS 1台,由6个20kVA模块组成总功率120kVA,模块5+1并联冗余系统。根据医疗系统规范标准对配电系统的要求,UPS输出端配置隔离变压器,输出侧采用TN-S配电系统,确保供电系统更安全可靠、提供更佳的保护效果。图1为HIFT 120kVA UPS模块冗余供电系统图。图13 方案优势3.1 安全可靠⑴ HIFT 120K模块5+1并联冗余可靠性分析采用普通UPS单机100kVA 1+1并联冗余系统的可靠性计算公式为式(1)。( 1)式中:R(t)表示单机可靠性;RN+X(t)表示系统可靠性; 表示并联冗余系统中X+1个子系统故障时的组合数。如果单机可靠性为R(t)=0.99,代入式(1)得到1+1并联系统的可靠性为:R1+1(t)=1-[1-R(t)]2=0.9999普通UPS单机100kVA 1+1并联冗余方案中,无论实际运行负载是多少,冗余数始终都为1不变,UPS供电系统的可靠性始终为0.9999。采用台达HIFT 120K UPS模块5+1冗余的方案中,当实际负载为设计容量的60%时(实际负载:100kVA&60%=60kVA),实际负载占3个模块,此时供电系统冗余数为3个模块,实际运行时是模块3+3的并联冗余系统。也就只有4个功率模块同时故障的时候,UPS才会转旁路工作,才会在无保护的状态下运行。
分享给小伙伴们:
我来说两句……
微信公众号二
微信公众号一IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
通过本文,了解使用拖放功能移动 Web 页面的不同部分的技巧。分别实现交互性的不同方面,然后再将它们组合在一起,这样便于灵活定制页面,也让您的 Web 用户非常满意。
, 软件工程师
Greg Travis 是 Google 的软件工程师。他做过 Web 程序员、独立承包商和游戏开发人员。可以通过
与 Greg 联系。
JavaScript 是一种功能强大的语言,可用于创建基于 Web 的应用程序。它已经足够稳定和成熟,完全可以创建与传统桌面应用程序相抗衡的程序,因为后者在稳定性和特性丰富性方面都要胜出一筹。但 JavaScript 最初只是用来向静态 Web 页面添加某些交互性,使它不再是静态页面,它现在还用于此目的。我将要展示的这个技巧的关键之处是如何恰当地构建页面,使它能与 JavaScript 代码交互。通常,页面都是通过头脑里固有的 JavaScript 代码构造的。但是,尽管如此,很多时候您都需要向现有页面内添加新的交互特性。而这往往需要一些技巧,因为 JavaScript 代码必须遍历文档结构并在合适的位置添加代码,而且通常还要求不影响现有的结构 — 和页面上已有的 JavaScript 代码。总之,要将对系统的影响最小化。可切换系统本文介绍了一种方法,它通过移动页面的不同部分来激活 页面。具体来讲,就是通过将一个部分拖放到另一个部分之上从而实现可切换 部分的切换。
要激活这些部分,只需向其添加 class 参数并加载一个 JavaScript 文件。可以通过向 &body& 标记添加 onload 方法来激活代码,此方法会在页面加载之后立即启动代码。代码会处理随后的事情。
注意:本文示例所对应的源代码可以从
部分获得。
此外,可以尽量多地使用抽象来构造代码。程序的不同元素通常都不必要地相互缠结,UI 代码更是这样。可切换系统由不同的块构建而成,每个块实现交互性的不同部分。这些块结合起来就能实现简单无缝的界面,该界面对于 UI 的试验和调优都很关键。
可切换界面可切换系统很容易使用。先由 Web 页面设计人员将某些部分标志为可切换的。然后就可以在任何一个可切换元素上单击并将该元素拖放到另一个可切换元素。放开鼠标按钮后,这两个元素就完成了交换。
为了能清楚展示所发生的事情,可以使用一些标准的 GUI 操作。突出显示被拖动的元素当第一次单击可切换元素时,在光标下面会出现一个透明的矩形。这个矩形由 coveringDiv() 函数创建,它刚好能覆盖这个可切换元素。实际上是将这个矩形拖放到另一个元素。当拖放时,只有这个透明的矩形会移动 — 初始的元素保持不动直到鼠标按钮被松开为止。
突出显示拖动到的目标另一个重要的操作是清晰标识出要拖动到的目标元素。当拖动透明的矩形四处移动时,光标可以经过多个可切换元素。当光标悬浮于某个可切换元素之上时,该元素就会通过另一个透明矩形突出显示。这种突出显示就能清楚地标示出此元素就是拖放到的目标。当松开鼠标按钮时,被拖动的元素和拖放到的目标元素就会互换位置,而且所有透明矩形也会消失,直到下一次切换。
激活系统正如先前提到的,必须要使代码对已有系统影响最小。这就意味着页面设计人员 —工作于 HTML 或 XML— 无需涉及可切换系统。这不是他们的工作。
此页面只需具有如下三项内容:JavaScript 标记&body& 标记内的 onload 方法
标记为 swappable 的可切换区域 必须将以下标记置于页面文件的顶部:&script src="rearrange-your-page.js"&&/script&此标记在加载过程的早期加载,但它在 body 内的 onload 函数调用之后才会执行。
body 标记内的 Onload 方法该方法在整个页面加载时调用这个可切换系统。这一点很重要,因为此代码的第一项功能就是在整个页面内搜索可切换的元素。因而,需要确保这些元素已加载。body 内的 onload 方法应该如清单 1 所示。
清单 1. body 内的 onload 处理程序&body onload="swappable_start();"&
... rest of page
&/body&已标记为 swappable 的可切换区域必须通过 class 参数这样标记每个想要切换的区域。这是页面作者和设计人员需要多加考虑的事情,因为他们需要将此参数添加给每个部分。参见清单 2。
清单 2. 用可切换类注释 div&div class='swappable'&
lorem ipsum lorem ipsum
&/div&寻找可切换的部分代码所需做的首要事情是寻找页面将被激活的部分。正如之前提到的,这只要求包围这个部分的标记具有 class 参数。要寻找这些部分,需要找到所有具有可切换 class 的标记。此函数不是标准 DOM 库的一部分,但它很容易实现。清单 3 展示了一个示例实现。
清单 3. getElementsByClass() 的实现// By Dustin Diaz
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.
var pattern = new RegExp("(^|\\\\s)"+searchClass+"(\\\\s|$)");
for (i = 0, j = 0; i & elsL i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
return classE
}交互性的元素程序一般是通过将各功能块结合在一起而构建起来的。不同的程序员会有不同的实现方式,但作为一种规律,最好是采用多个小的功能块而不是少数几个大的功能块。每个小功能块应该实现一种功能并具有清楚的语义。
不过,在进行 GUI 编程时,这样的构建不太容易。好的 GUI 必须调整很多界面元素并将它们的行为结合起来形成一个能直观工作的整体行为。基于事件的系统通常都是由复杂的交换行为联合起来的回调集合。模块化的交互元素很难创建。
模块化的交互元素可切换代码就使用了模块化的交互元素。前面,我提到过在可切换系统内有两种主要的交互元素:拖动元素的突出显示和拖动到的目标的突出显示。在代码中,这两个元素的实现是分开的。
本例很好地展示了模块化处理交互性的技巧。正如可切换界面的描述中所提到的,这两个交互性元素常常缠结在一起。突出显示和突出显示的消失都是在一个鼠标操作中发生的,而且它们的发生都对应鼠标输入的不同方面。如果这两个元素是在一个代码片段中实现的,那么代码可能不太容易读懂,因为同时发生的事情很多。
拖动处理程序为了使 GUI 的实现模块化,我使用了拖动处理程序。这类似于内置在 GUI 系统的事件处理程序。虽然事件处理程序只处理某种单一事件,拖动处理程序却可以处理整个拖放过程。一个拖动处理程序可处理一系列事件而不只一个单一事件。下面是拖动处理程序的示例骨架,如清单 4 所示。
清单 4. 拖动处理程序的骨架{
function( x, y ) {
function( x, y ) {
function() {
}这个拖动处理程序是一个对象,具有三个方法:start、move 和 done。当初始化一个拖放动作时,调用 start 方法并传递给这次单击的对应坐标。当四处移动光标时,会反复调用 move 方法,然后同样被传递给光标当前对应的坐标。最后,当鼠标按钮释放后,就会调用 done 方法。
可切换系统同时使用了两个不同的拖动处理程序,这也让您能够干净地处理交互的两个不同方面,即便这两个方面具有复杂的关系。让其中的一个交互成为另一个交互的一部分并不合适。相反,应该能同时无缝地使用这两个交互。
rectangle_drag_handler这两个拖放处理程序的其中是 rectangle_drag_handler。此处理程序负责移动代表被拖动元素的透明矩形。清单 5 给出了这个 start 方法。
清单 5. rectangle_drag_handler 处理程序function rectangle_drag_handler( target )
this.start = function( x, y ) {
this.cover = coveringDiv( target );
make_translucent( this.cover, .6 );
this.cover.style.backgroundColor = "#777";
dea( this.cover );
this.dragger = new dragger( this.cover, x, y );
}start 方法创建这个透明矩形并将其传递给另一个称为 dragger 的对象。一个 dragger 就是一个对象,它能对应移动的光标移动 DOM 元素。可以将当前的光标的坐标传递给这个 dragger,它会更新所拖动的对象使其跟随光标的移动。
move 方法更新这个 dragger,如清单 6 所示。
清单 6. 更新 draggerthis.move = function( x, y ) {
this.dragger.update( x, y );
};最后,done 方法(参见清单 7)删除这个透明矩形,因为拖放过程现在已经结束。
清单 7. rectangle_drag_handler 的 done 方法this.move = function( x, y ) {
this.done = function() {
this.cover.parentNode.removeChild( this.cover );
}组合拖动处理程序现在必须找到一种方法来同时使用这两个拖动处理程序。这可以通过 compose_drag_handlers() 函数轻松实现,该函数接受这两个拖动处理程序并将其结合成一个综合的拖动处理程序。这个综合拖动处理程序的使用与一般的拖动处理程序一样。这样,这两个原始的拖动处理程序的行为就实现了无缝结合。
compose_drag_handlers() 函数很容易编写。它看上去很像是一个拖动处理程序,但每个方法都会调用这两个原始拖动处理程序中相应的方法。这个函数如清单 8 所示。
清单 8. compose_drag_handlers()function compose_drag_handlers( a, b )
function( x, y ) {
a.start( x, y );
b.start( x, y );
function( x, y ) {
a.move( x, y );
b.move( x, y );
function() {
}正如您所见,拖动处理程序 a 和 b 被组合到一个综合的拖动处理程序内。如果要调用这个综合处理程序的 start() 方法,实际上就是先后调用 a.start() 和 b.start()。
您需要在名为 prepare_swappable() 的设置函数内调用 compose_drag_handlers,如清单 9 所示。
清单 9. prepare_swappable() 函数function prepare_swappable( o )
swappables.push( o );
var sdp = new rectangle_drag_handler( o );
var hdp = new highlighting_drag_handler( o );
var both = compose_drag_handlers( sdp, hdp );
install_drag_handler( o, both );
}除了其他功能之外,此函数最主要的功能是为可切换元素创建 rectangle_drag_handler 和 highlighting_drag_handler,然后再将它们组合成一个综合的拖动处理程序。最后,这个综合拖动处理程序再通过调用 install_drag_handler() 来激活,这将在接下来的两个小节中详细介绍。
安全安装鼠标处理程序与常规的事件处理程序不同,一个拖动处理程序可以处理多个事件。尽管如此,它还是需要附加到对象,这与常规的事件处理程序相同。
安装任何一种事件处理程序都是需要技巧的,因为正在修改的元素很可能已经在其内安装了事件处理程序。如果要替换这些事件处理程序,就需要更改页面的行为方式。
为了避免这一问题,可以使用一个名为 install_mouse_handlers() 的实用函数,如清单 10 所示。
清单 10. install_mouse_handlers() 函数function install_mouse_handlers( target, onmouseup, onmousedown, onmousemove )
var original_handlers = {
onmouseup: target.onmouseup,
onmousedown: target.onmousedown,
onmousemove: target.onmousemove
target.onmouseup =
target.onmousedown =
target.onmousemove =
restore: function() {
target.onmouseup = original_handlers.
target.onmousedown = original_handlers.
target.onmousemove = original_handlers.
}install_mouse_handlers() 函数负责向特定的对象添加特定的鼠标处理程序。它返回的是一个对象,可使用该对象恢复原始的处理程序。这样一来,当拖放过程结束后,就可以调用 restore() 函数,恢复到拖放过程开始之前的状态。
激活拖动处理程序针对拖放操作的拖动处理程序使用了这三个鼠标处理程序:onmousedown、onmouseup 和 onmousemove。不过,开始时,只需安装 mousedown 处理程序,因为此时您尚在等待激发初始化拖放过程的单击。
当单击发生时,就需要安装 mousemove 和 mouseup 处理程序。而且,在此时,不再需要 mousedown 处理程序,因为已经进行单击。该处理程序将被删除,在拖放过程完成后再恢复它。最初的 mousedown 处理程序如清单 11 所示。
清单 11. 最初的 mousedown 处理程序var onmousedown = function( e ) {
var x = e.clientX;
var y = e.clientY;
p.start( x, y );
var target_handler_restorer =
var document_handler_restorer =
var onmousemove = function( e ) {
var x = e.clientX;
var y = e.clientY;
p.move( x, y );
var onmouseup = function( e ) {
target_handler_restorer.restore();
document_handler_restorer.restore();
target_handler_restorer =
install_mouse_handlers( target, onmouseup, null, onmousemove );
document_handler_restorer =
install_mouse_handlers( document, onmouseup, null, onmousemove );
e.stopPropagation();
};在初始化拖放序列并调用此处理程序时,它会创建 onmousemove 和 onmouseup 处理程序并能在目标元素内安装它们。当然,它还会使用一个 install_mouse_handlers(),以便以后的卸载。
还有一点需要注意:是在 document 对象内安装这些处理程序的。这一点十分关键,因为在拖放过程中用户可能会将光标拖过整个页面。如果鼠标超出可切换元素的范围 — 您很可能还想收到这些事件。同样地,可以使用 install_mouse_handlers() 以便以后恢复它们。
将它们组合起来至此,我已经介绍了很多不同的类和函数。其中的每一个类或函数本身都十分简单,因此更重要的是要了解它们是如何协同工作的。
下面是对整个拖放过程的一个总结:单击一个可切换元素。此元素的 onmousedown 处理程序将被调用,它安装 onmousemove 和 onmouseup 处理程序。
移动鼠标,这些处理程序将被调用。这些处理程序反过来调用前面安装的拖动处理程序。这个拖动处理程序实际上是一个复合拖动处理程序,综合了两个不同的拖动处理程序的效果。
其中的一个拖动处理程序 rectangle_drag_handler 负责向光标附加一个代表被拖动元素的透明矩形。
另一个拖动处理程序 highlighting_drag_handler 负责突出显示鼠标移过的那些可切换元素,以显示可以进行元素拖动的地方。
当在目标元素之上释放鼠标按钮时,highlighting_drag_handler 的 done() 方法就会切换这两个元素。这个拖动处理程序将被卸载,只留下最初的 onmousedown 处理程序,准备好开始下一轮的拖放过程。
结束语拖放操作相对简单,但它涉及了几个交互过程,用来跟踪整个过程的用户输入和提供即时反馈。本文展示如何将模块化的交互元素组合成统一整体来构建完整的 GUI。
这种做法有很多好处。由于代码是模块化的,因此更容易编写和维护。所需的函数和类的代码没有一个是超过 40 行的,并且它们通常更短。
每一个交互元素都会实现一个典型的 GUI 过程或效果,所以可在其他上下文中重用它们。可以开发这些交互元素的丰富的库,从而通过组合各个部分构建更复杂的 UI。
下载描述名字大小带示例的源代码1181KB其中包含了可切换库的源代码和使用了该库的一个示例页面。
参考资料 您可以参阅本文在 developerWorks 全球网站上的 。
“” 是一个关于闭包的优秀文章。闭包是本文所讨论的代码的核心。
“” 是用 JavaScript 代码实现拖放功能的另一个例子。
:developerWorks 上所有有关 Ajax 的问题都可以在这里找到解答。
在 developerWorks 的
专区获得提升您在架构方面的技能所需的资源。
获得关于这些主题和其他技术主题的书籍。
:随时关注 developerWorks 技术活动和网络广播。
是一个很有用函数,很多人都编写过它的不同版本。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
文章、教程、演示,帮助您构建、部署和管理云应用。
立即加入来自 IBM 的专业 IT 社交网络。
为灾难恢复构建应用,赢取现金大奖。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Web developmentArticleID=348268ArticleTitle=用 JavaScript 创建模块化的交互用户界面publish-date=

我要回帖

更多关于 政协提案怎么写 的文章

 

随机推荐