zoukankan      html  css  js  c++  java
  • 如何把js的代码写的更加容易维护(一)--面向对象编程

    总是头疼javascript的代码写起来不可维护,那么看看下面的代码:

     1 (function (w, $) {
     2   var app = {
     3     init: function () {
     4       var me = this;
     5       me.render();
     6       me.bind();
     7     },
     8     datas: {
     9       num: 1
    10     },
    11     render: function () {
    12       var me = this;
    13       me.test = $('#table td');
    14     },
    15     bind: function () {
    16       var me = this;
    17       me.test.on('click', $.proxy(me['_do'], this));
    18     },
    19     _do: function (e) {
    20       var m = $(e.target).text();
    21       var me = this;
    22       m = me.datas.num + m;
    23       var s = '<input type="text" value="' + m + '">';
    24       $(e.target).html(s);
    25     }
    26   };
    27 
    28   app.init();
    29   exports = app;
    30 })(window, jQuery);

    代码其实很简单,其基本思路就是,将数据、函数、事件监听和回调都封装在一个对象中,那么我们可以简单的把这个对象理解为一个组件。

    封装的难点:事件监听和回调

    封装的难点其实在于事件的监听和回调,先看一个简单的实现:

    1     bind: function () {
    2       var me = this;
    3       me.test.on('click', function(e) {
    4         // 操作
    5       });
    6     },

    就是以匿名函数的形式写回调函数,可以满足需求,但如果有大量的事件需要监听、绑定回调函数时,这种方式显然就不太合理了:bind方法会变得过长而不好维护,那么以传入具名函数函数名的方式就可以解决这个问题,但是会遇到回调函数中的this不是指向app对象而指向触发元素的问题:

     1     bind: function () {
     2       var me = this;
     3       me.test.on('click', me['_do']);
     4     },
     5     _do: function(e) {
     6         // 这里的this指向谁?
     7     var targetEle = $(e.target);
     8         // 这里的this显然指的是触发事件的元素,在这里是一个jQuery对象
     9         var me = this;
    10     // 下面这句就会报错
    11     m = me.datas.num + m;
    12     }

    那么如何解决上面的问题,答案就是$.proxy(fn, contenxt),这个方法可以改变函数执行时的上下文:

    1     bind: function () {
    2       var me = this;
    3       me.test.on('click', $.proxy(me['_do'], this));
    4     },

    上面的代码使me['_do']被调用时,this指向app,那么在me['_do']中就可以获取app中的数据,从而解决了上面this的指向问题。

    总结
    上面的js代码实现了一个简陋的可编辑表格的功能,这段代码是京程一灯袁志佳在腾讯视频公开课上讲的代码,我贴在这里来提醒自己:前端javascript的编写还有许多要学习和挖掘的地方。代码中主要用到了jQuery.proxy()这个强大的函数,另外就是这种对象封装的思想。

    存在的问题

    虽然$.proxy()解决了this的指向问题,但它也不是完美的。这里在使用事件委托时就要小心了:

     1     render: function () {
     2       var me = this;
     3       me.document= $(document);
     4     },
     5     bind: function() {
     6       document.on('click', 'ul li', $.proxy(me['_do2'], this));
     7     },
     8     _do2: function(e) {
     9         var eleTarget = $(e.target);
    10     }

    因为_do2中的this不再指向绑定事件的元素ul li,所以要想在_do2中获取ul li就有些麻烦,尤其是li中嵌套比较多的子元素时:

    1 <ul>
    2   <li>
    3     <div><span></span>...</div>
    4   </li>
    5 </ul>

    _do2中的eleTarget由于事件冒泡的原因可能是:span、div、li,那么该如何解决这个问题?很遗憾我没有想到好的解决方法,提供两个思路:1,如果li中嵌套了太多的子元素,那么事件委托在这里就不是一个好的解决方案了。2,如果嵌套的子元素不多,那么还可以通过查找的方法找到ul li,这个也是可行的。当然,如果抛开本文章,单纯使用事件委托还是可以的:

    1 $(document).on('click', 'ul li', function(e) {
    2   var this = $(this); 
    3 });

    因为这里的this始终指向ul li,即委托的元素ul li。

    这篇文章最初发表在我自己折腾的博客站点上:如何把js的代码写的更加容易维护(一)--面向对象编程,该博客用了一位前辈开源的源码,基于thinkjs和vuejs开发,欢迎大家来逛逛。

  • 相关阅读:
    COGNOS10启动服务报错 问题解决
    Linux 下 新增Oracle10g 实例 (转自http://www.cnblogs.com/lan0725/archive/2011/07/18/2109474.html)
    WIN7安装COGNOS8后配置IIS网站后,访问COGNOS站点网页一直显示空白,解决方法(转载)
    Gridview光棒效果 鼠标滑过
    11款实用的一句话网站设计代码
    自定义js方法 (格式化时间)
    测试一下
    UTF7转换GB2312编码的方法(中文)
    HTML注册页面验证注册信息
    android欢迎页
  • 原文地址:https://www.cnblogs.com/yangtoude/p/how-to-write-maintainable-javascript-code.html
Copyright © 2011-2022 走看看