`
bellstar
  • 浏览: 150606 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

javascript总结(六)页面元素的创建调整与关联

阅读更多

目录
(一)有关框架
(二)文件组织与代码组织
(三)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来做的,虽然滚动动画的类里有停止滚动的接口,但由于刷新页面的逻辑不是集中于一个函数内,并且局部刷新页面的动作很大可能还会在未来的代码里面出现,因此我考虑还是由滚动类自己监测容器元素是否存在,由此来决定是否停止滚动,并释放自己。
分享到:
评论

相关推荐

    html教案、javascript

    4. 块级元素与内联元素:了解块级元素(如`&lt;div&gt;`、`&lt;p&gt;`)和内联元素(如`&lt;span&gt;`、`&lt;a&gt;`)的区别,以及如何通过CSS调整布局。 5. 表单元素:`&lt;form&gt;`、`&lt;input&gt;`、`&lt;select&gt;`、`&lt;textarea&gt;`等用于用户交互,学习...

    DIV页面元素增加删除例子

    这篇博客"DIV页面元素增加删除例子"可能是关于如何在网页中使用`DIV`来创建、编辑和删除页面结构的教程。 首先,我们需要理解`DIV`的基本概念和用法。`&lt;div&gt;`标签通常与CSS(Cascading Style Sheets)结合使用,以...

    博客创建一个登录页面(HTML,CSS)的源码

    3. **登录页面元素设计**: - **头部**:通常包含网站标识和辅助导航链接,可以使用CSS设置背景图片、颜色、字体等。 - **主体**:登录表单通常在此部分,包括用户名和密码输入框、记住我选项、登录按钮,以及可能...

    javascript表单事件汇总

    与`onclick`类似,但`ondblclick`是在用户双击页面元素时触发。这通常用于需要更快速响应或特定动作的场景,如放大图片、打开编辑模式等。 ### 六、onerror `onerror`事件在页面加载过程中遇到错误(如图片加载...

    HTML元素标签.doc(开发总结实用)

    - `label`: 与`for`属性一起使用,关联输入元素,便于用户操作。 - `q`: 用于表示短引号。 - `span`: 通用内联容器,用于组合文本或应用样式。 - `sub`: 用于表示下标文本,如化学公式中的指数。 - `sup`: 用于表示...

    一个简单的基于javascript的个人网页

    例如,可以创建一个JavaScript对象与`&lt;audio&gt;`元素关联,并通过该对象的API来操作播放器,如`play()`, `pause()`, `currentTime`等。 最后,过滤镜效果通常指的是图像的视觉处理,这通常通过CSS滤镜或JavaScript...

    js特效 javascript特效

    2. **事件处理**:JavaScript特效往往与用户交互紧密关联,通过监听用户的点击、滚动、悬停等行为,触发相应的特效。例如,鼠标悬停在某个元素上时,该元素可以放大或改变颜色。 3. **动画框架**:为了简化动画的...

    JavaScript-texiao.rar_javascript

    1. DOM操作:JavaScript与HTML文档对象模型(DOM)紧密关联,通过DOM可以动态地改变网页内容、样式或结构。常见的DOM操作包括获取元素、添加删除元素、修改元素属性等。 2. 事件处理:事件是JavaScript中的关键概念...

    JavaScript万年历.rar

    关于描述中提到的Java代码工具包,虽然与JavaScript万年历直接关联不大,但它们可能包含了一些通用的Java工具类,比如日期处理工具类,这在Java开发中非常常见。这些工具类可以简化日期和时间的计算,避免重复编写...

    javascript日历

    9. **AJAX和异步更新**:如果日历与服务器数据关联,例如用于预订系统,那么可能需要使用AJAX(Asynchronous JavaScript and XML)技术来异步获取或提交日期信息,保持页面的流畅体验。 10. **测试与调试**:确保...

    Javascript应用实例汇总

    根据给定的信息,我们可以归纳总结出一系列与JavaScript相关的知识点,主要围绕HTML元素事件处理、页面样式动态更改等方面展开。下面将详细阐述各个知识点。 ### 1. HTML元素事件处理 在网页开发中,事件处理是...

    javascript特效代码

    还可以利用鼠标位置来改变页面元素的状态,如导航栏的下拉菜单或提示信息的显示。 4. **JSLibrary特效生成器**: "publish_JSLibrary特效生成器"可能是一个工具或库,它帮助开发者快速生成JavaScript特效代码,...

    JavaScript---仿chinaz站长站首页的导航菜单

    在JavaScript编程领域,创建动态和交互式的网页元素是常见的需求之一,其中导航菜单是一个至关重要的组成部分。本项目“JavaScript---仿chinaz站长站首页的导航菜单”旨在利用JavaScript技术实现与知名网站ChinaZ...

    javascript广告动态切换效果

    2. 通过`getElementById`定位到指定的图片元素和关联的导航链接,调整`style.display`和`style.color`属性,以显示当前图片并高亮对应的导航项。 3. 最后,重新设置定时器,指向下一个图片的显示函数,例如`id = ...

    利用JAVASCRIPT点击按钮播放音乐

    在这个例子中,`&lt;button&gt;`元素的`id`为"playButton",用于与JavaScript中的事件处理函数关联。`&lt;audio&gt;`标签是HTML5引入的新特性,用于嵌入音频资源,其`id`为"music",`src`属性指向音乐文件的URL,`preload="auto...

    javascript经典特效---不同CSS效果的调用.rar

    7. **悬浮菜单**:当鼠标悬浮在元素上时,JavaScript可以改变关联菜单的CSS显示状态,如显示隐藏的下拉菜单。 8. **图片懒加载**:通过JavaScript监听滚动事件,当图片进入视口时再加载,可以提高网页的加载速度。...

    javascript调色板

    使用XMLHttpRequest或Fetch API进行异步数据交换,能够在不刷新页面的情况下与服务器进行交互。在调色板应用中,这可能是用来保存用户的颜色选择或者上传自定义调色板文件。 6. **前端框架和库**: 如Vue.js、...

    简单通用登录页面模板 bootstrap登录页面 html页面

    这个模板可能包含`&lt;form&gt;`标签来定义登录表单,`&lt;input&gt;`标签用于创建输入字段,`&lt;button&gt;`标签用于提交表单,以及其他辅助的HTML5语义元素,如`&lt;label&gt;`用于关联输入字段和其对应的文本。 5. **响应式设计** 响应...

Global site tag (gtag.js) - Google Analytics