- 浏览: 148147 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
shlice:
你好,我在osx上测试,输入法没有成功切换到英文。你的&quo ...
让Mac版Sublime text3的Vintage插件切换命令模式时自动切换到英文输入法 -
q471989525:
很不错~ 多谢分享
仿Gmail中输入多个收件人的Autocomplete组件 -
leon.s.kennedy:
[flash=200,200][url][img][list] ...
javascript总结(三)js与FLASH的交互 -
hahaha168:
请问如果我没有使用数据库的话,可以使用这种关联关系吗?
rails关联学习笔记 -
j67065:
不好意思,这个确实挺有用的,后来发现,路径就在存放数据库文件下 ...
使用sqlite的文件导入导出功能
目录
(一)有关框架
(二)文件组织与代码组织
(三)JS与FLASH交互
(四)ajax局部刷新与RPC
(五)获取设置元素样式与监听元素事件
(六)页面元素的创建调整与关联
(七)浏览器兼容性问题
(八)WEB软件的前端架构实践
文章中的代码只为表达文章意义,非真正能执行的代码。
动态创建、调整element
一、你考虑清楚要直接操作element吗?
用这个疑问来表示对这种行为的慎重,操作element有哪些地方你可能需要考虑呢:
- 美工对设计作了更改后,引起HTML结构变化时和样式变化时,需要变更代码(而不是模板)
- 用代码来组织HTML结构,一点也不形象,维护起来也麻烦
- 数据变化后,要在JS逻辑中维护页面变化,逻辑复杂,同样设计更改后,这部分代码也得改
- 部分元素在不同浏览器下的操作方法不一致,导致你可能要针对不同浏览器来写代码
- 通过标准DOM接口直接操作element与使用innerHTML整块设置HTML来比较,速度稍慢
即使有以上考虑,有以下情形我还是选择直接操作element
- 如果业务逻辑足够简单,HTML结构也相对简单。比如更新用户名后更新页面上其他地方的用户名。
- 如果HTML比较复杂,但数据或者状态变化后,只需要变化一个地方。
- 在结构稳定的UI widget中,比如对话框。(以之相反的是grid,我会选择使用模板)
- HTML中输入控件比较多 ,大部分时候需要保持控件的当前值和光标聚焦位置
另外,刷新整个部分与只更新变化的地方,用户体验会更好,不会闪的那么厉害,而且要做动画表示这个变化也方便。
二、应用模板进行局部更新
应用整体模板
应用模板编程的优势及示例,我就不再重复。再次请大家参见金大为的雏凤清音 -- 面向数据的前端编程方法
应用局部模板
var groupManagerCmp = { body: "#userGroup", viewTemplete: new Template( "<tr><td>${name}</td><input type='button' value='编辑' /><td></td><td><input type='button' value='删除' /></td></tr>"), editTemplate: new Template( "<tr><td><input type='text' value='${name}'></td><td><input type='button' value='提交' /></td><td><input type='button' value='取消' /></td></tr>"), renderViewRow: function(id, name){ var tr = this.viewTemplete.bind(id,name); $("input[0]",tr).click(function(){ //编辑 groupManagerCmp.edit(tr, id, name); }) $("input[1]",tr).click(function(){ //删除 action.do("delete", {id: id}, function(){ groupManagerCmp.remove(tr); }) }) return tr; }, renderEditRow: function(id, name){ var tr = this.editTemplate.bind(id,name); $("input[0]",tr).click(function(){ //提交 action.do("put", {id: id, name: name}, function(group){ groupManagerCmp.update(tr, group.id, group.name); }) }); $("input[1]",tr).click(function(){ //取消 groupManagerCmp.update(tr, id, name); }) return tr; }, append: function(id, name){ $(this.body).appendChild(this.renderViewRow(id, name)); }, remove: function(trNode){ $(this.body).removeChild(trNode); }, edit: function(trNode, id, name){ $(this.body).replaceNode(trNode, this.renderEditRow(id, name)); }, update: function(trNode, id, name){ $(this.body).replaceNode(trNode, this.renderViewRow(id,name)); } } var action = { url: { post: "group/new", put: "group/update", delete: "group/destroy" } do: function(action, params, callback){ ajax(this.url[action], params, function(data){ callback(decode(data)) }); } }
三、应用状态模式应对复杂的界面变化
项目中有一个随机聊天的东西,系统从到达此页面的人中随机两两配对,进行聊天。
业务过程:
用户点击开始配对-----》系统开始找人与你聊天 <-------------------------------
| |
---------------------------- |
| | |
找到人,开始聊天 没找到,提示可重新配对 |
| | |
聊天中 点击重新配对-----------------------------
| |
| |
对方退出或中断,提示可重新配对 |
| |
--------------------------- |
| | |
关闭页面 点击重新配对--------------------------------
//某种状态变化后,都调用updateView更新界面 function updateView(state, args){ if(state == "connectSuccess"){//连接成功 chatWin.show(args); jQuery("connectWin").hide(); }else{ chatWin.hide(); if(state == "ready"){ //未连接,等待用户点击连接 //code }else if(state == "connecting"){ //正在连接 //code }else if(state == "connectFail"){ //连接失败 jQuery("#status").text("连接失败"); jQuery("#btnConnect").show(); }else if(state == "strangerLeft"){ //对方离开 //code }else if(state == "connectInterrupt"){ //连接中断 //code }else if(state == "timeout"){//连接超时 //code } } } function connect(currentUser){ chatProxy.connect(currentUser.userId, function(state, data){ if(state == "success"){ updateView("connectSuccess", data.stranger); }else{ updateView("connectFail"); } }) }
三、应用观察者模式应对多处界面变化
示例:当用户变更它的个人信息时,更新见面中显示用户个人信息的地方。用户的个人信息可能在多个页面的不同位置显示。
//用户类 User = function(uinfo){ for(var p in uinfo){ this[p]=uinfo[p]; } this._observers = []; }; User.prototype = { //更新属性 update: function(property, value){ if(this.hasOwnProperty(property)){ if(this[property] != value){ this[property] = value; this.notice(property); } } }, //增加属性变更监听者(函数) addListener: function(property, observer){ if(!this._observers[property])this._observers[property] = []; this._observers[property].push(observer); }, //通知变更 notice: function(property){ var observers = this._observers[property]; if(observers && observers.length){ var value = this[property]; $.each(observers, function(i, fn){ fn && fn(value); }) } } } //在页面初始化代码中添加监听函数 jQuery(document).ready(function(){ currentUser.addListener("name", function(name){ jQuery("#userName").text(name); }) currentUser.addLIstener("icon", function(icon){ jQuery("#userIcon").attr("src",icon); }) }) //在业务代码中,当用户更新个人信息,用户对象自动调用监听函数更新页面。 currentUser.update("name","lucy"); currentUser.update("icon","url");
三、给元素操作取一个名字
给逻辑相关的元素操作封装在一个方法里面,并取一个与业务相关的名字是一个好的做法。特别是当这个操作的代码重复出现在多个地方的时候,更有这个必要。
function updateUserHometown(province, city){ jQuery("#homeTown").html(provinece + "," + city); }
在JS对象中关联element
一、直接关联还是通过查找引用
var testDiv = document.createElement("div"); testDiv.id = "testDiv"; document.body.appendChild(testDiv); document.body.removeChild(testDiv); alert(testDiv.nodeName); //DIV alert(testDiv.paretNode); //undefined delete testDiv; 此时testDiv才被清除
通过以上代码可以看出,当你直接关联到元素时,就有可能造成元素被移除后,其对映DOM对象还在。基于这个原因,要小心因此可能造成内存泄露。
而通过ID或者其他选择器则不会有这个问题。但每次取不是很麻烦费时吗?其实你只要保证关联到元素的变量会被释放,还是应该直接引用的
function updateView(){ var con = document.getElementById("container"); //code ... } 因为con是一个局部变量,所以它在函数调用后被释放了。 (function(){ var con = document.getElementById("container"); updateView = function(){ alert(con); } })() document.getElementById("container").parentNode.removeChild(document.getElementById("container")); updateView(); //con还是存在。
二、避免引用散布到代码中
将元素CSS选择表达式散布的代码中,维护起来确实很麻烦,也使得我们的代码和页面结合得更加紧密,这是我们不希望看到的,考虑以下办法避免:
//方法一:通过参数传递元素选择表达式 function submitForm(){ document.getElementById("userInfoForm").submit(); } function submitForm(formId){ document.getElementById(formId).submit(); } //<a href="javascript:submitForm("userInfoForm")" >提交</a> //方法二:通过get方法把变化集中到一处 function getMainGrid(){ return document.getElementById("mainGrid"); } //方法三:尽量把引用放到一处,然后通过传递参数引用元素。 function initSidebar(){ var s1 = document.getElementById("s1"); var s2 = document.getElementById("s2"); new Sidebar(s1,"news") new SIdebar(s2, "videos"); }
三、考虑关联element被其他业务逻辑删除的情况
在实际项目中,我做了一个文字滚动,做好之后,我发现滚动部分在多种情况下会被替换掉,而文字滚动我是通过setInterval来做的,虽然滚动动画的类里有停止滚动的接口,但由于刷新页面的逻辑不是集中于一个函数内,并且局部刷新页面的动作很大可能还会在未来的代码里面出现,因此我考虑还是由滚动类自己监测容器元素是否存在,由此来决定是否停止滚动,并释放自己。
发表评论
-
amplifyjs--有关组件通讯与请求管理与本地存储的js库
2014-09-18 22:27 956简介: 本介绍只是方便英文不好的人快速对这个框架有个了解,当然 ... -
一个JavaScript的oo库
2012-07-20 16:49 1016此项目已更名为May.js,内容已过期,请参见http:/ ... -
KISSY之KISSY.JS速记
2010-12-15 14:11 2719https://github.com/kissyteam/ki ... -
面试题-做一个聊天原型
2010-05-17 16:27 1301解压,无须WEB服务器,直接运行chat.html即可. 含 ... -
javascript总结(七)浏览器兼容性
2010-04-01 14:30 0javascript语言本身的兼容性 IE不支持Array#i ... -
javascript总结(五)获取设置元素样式与监听元素事件
2010-03-30 15:11 4377目录 (一)有关框架 ... -
javascript总结(四)ajax局部刷新与RPC
2010-03-29 19:16 2189目录 (一)有关框架 (二)文件组织与代码组织 (三)JS与 ... -
javascript总结(三)js与FLASH的交互
2010-03-29 16:51 5815目录 (一)有关框架 (二)文件组织与代码组织 (三)JS与 ... -
javascript总结(二)文件组织与代码组织
2010-03-29 15:13 2388目录 (一)有关框架 (二)文件组织与代码组织 (三)JS与 ... -
javascript总结(一)有关框架
2010-03-26 18:38 1739做过.NET,ROR,现专职JS满两年了.就开发过程中遇到的问 ... -
HTML标记不匹配引起的问题
2010-01-25 10:48 776场景: ajax载入一个html片段,firefox下正常,i ... -
结合使用setTimeout和setInterval模拟QQ头像闪动
2010-01-19 18:07 1622注: $为jQuery方法,$(el).attr(name, ... -
使用 window.name 解决跨域问题
2010-01-06 17:59 1768内容来源怿飞的BLOG 比较适合获取跨域的HTML片段,获取J ... -
用EXT的CHECKBOX表示BOOL型字段
2010-01-05 16:46 1264在SUI模板中添加VALUE="1" ... -
javascript的namespace声明
2009-12-09 17:37 1276function namespace(ns){ ... -
分享一个VIM的JS代码格式化插件
2009-12-09 17:30 7082VIM是我最爱的编辑器,我是JS程序员,程序长了格式化就麻烦, ... -
Ext组件继承层次图
2009-10-14 16:20 1057... -
重构增强版通用滚动widget,鼠标移入可暂停滚动
2009-07-29 15:30 1175/** * 滚动HTML集合对象 * @param ... -
通用滚动widget
2009-07-28 17:49 1006/** * 滚动HTML集合对象 * @param ... -
安全的jQuery(selExp).html(content)
2009-05-21 10:18 905jQuery.prototype.html_scr ...
相关推荐
如果您的网站包含许多页面,并且您希望您的 jQuery 函数易于维护,那么请把您的 jQuery 函数放到独立的 .js 文件中。 当我们在教程中演示 jQuery 时,会将函数直接添加到 <head> 部分中。不过,把它们放到一个单独的...
2.4.1 代码隐藏文件如何与页面连接 2.4.2 控件标签如何与页面变量连接 2.4.3 事件如何与事件处理程序连接 2.5 Web项目 2.5.1 基于项目的开发 2.5.2 创建Web项目 2.5.3 迁移旧版Visual Studio创建的网站...
2.4.1 代码隐藏文件如何与页面连接 44 2.4.2 控件标签如何与页面变量连接 44 2.4.3 事件如何与事件处理程序连接 46 2.5 Web项目 47 2.5.1 基于项目的开发 47 2.5.2 创建Web项目 48 2.5.3 迁移旧版Visual...
KnockoutJS 提供两个重要的元素使用MVVM模式: • JavaScript 类observable 和observableArray,用于监视ViewModel 变量的变动。 • 当页面中变量改变时,和observables 关联的HTML 扩展标记会自动更新数据。HTML...
9、行内元素 与 块级元素 按照元素们的表现形式来分类,分为 行内元素 和 块级元素1、行内元素 在一行内允许显示多个元素的,称为 "行内元素" span,i,b,s,u,sup,sub 作用:包裹文本,并处理文本的表现形式 2、...
1.0初始版本1.1功能的命名空间1.2提高代码的效率和可读性,尤其是围绕元素创建和属性设置1.3更有效的选择器,更清晰的变量命名1.4删除了在标记内设置初始活动选项卡的必要性1.5消除了将标题和面板类手动添加到标记中...
使用cgi创建动态页面 guestbook.cgi脚本程序 定义表单以及处理表单数据 cgi.tcl软件包 接下去的几步 第4章 tcl中的字符串处理 string命令 append命令 format命令 scan命令 binary命令 相关章节 第5章...
实例038 动态输出JavaScript代码 69 实例039 当数字遇到了字符串 70 实例040 PHP程序员的基础——变量的应用 72 实例041 打印系统环境变量信息print_r($_ENV) 73 实例042 使用可变变量输出“I Like PHP!” 73 实例...
实例038 动态输出JavaScript代码 69 实例039 当数字遇到了字符串 70 实例040 PHP程序员的基础——变量的应用 72 实例041 打印系统环境变量信息print_r($_ENV) 73 实例042 使用可变变量输出“I Like PHP!” 73 实例...
文本搜索Google Places API ( ) 创建一个小型的单页 Web 应用程序,显示从该 API 检索到的所有地点的列表,并允许用户... 如果存在与给定过滤器相关联的服务,则在选择过滤器时可以触发相关服务并填充结果。 #Resize o
<br>2007/6/25 Version 3.1.5 beta <br>Updates: 1) 修正在VS2005设计模式中无法动态调整控件高度的BUG。 2) 修正height属性无效的BUG。 3) 修正CodeHighlighter外挂插件调用图片位置指向不正确...
关于这本书..............................................................................................................................................1 第一章 搜索引擎基础.............................
目录 关于这本书.............................................................................................................................................1 第一章 搜索引擎基础..........................