如何把js的代码写的更加容易维护(一)--面向对象编程
总是头疼javascript的代码写起来不可维护,那么看看下面的代码:
(function (w, $) {
var app = {
init: function () {
var me = this;
me.render();
me.bind();
},
datas: {
num: 1
},
render: function () {
var me = this;
me.test = $('#table td');
},
bind: function () {
var me = this;
me.test.on('click', $.proxy(me['_do'], this));
},
_do: function (e) {
var m = $(e.target).text();
var me = this;
m = me.datas.num + m;
var s = '<input type="text" value="' + m + '">';
$(e.target).html(s);
}
};
app.init();
exports = app;
})(window, jQuery);
代码其实很简单,其基本思路就是,将数据、函数、事件监听和回调都封装在一个对象中,那么我们可以简单的把这个对象理解为一个组件。
封装的难点:事件监听和回调
封装的难点其实在于事件的监听和回调,先看一个简单的实现:
bind: function () {
var me = this;
me.test.on('click', function(e) {
// 操作
});
},
就是以匿名函数的形式写回调函数,可以满足需求,但如果有大量的事件需要监听、绑定回调函数时,这种方式显然就不太合理了:bind方法会变得过长而不好维护,那么以传入具名函数函数名的方式就可以解决这个问题,但是会遇到回调函数中的this不是指向app对象而指向触发元素的问题:
bind: function () {
var me = this;
me.test.on('click', me['_do']);
},
_do: function(e) {
// 这里的this指向谁?
var targetEle = $(e.target);
// 这里的this显然指的是触发事件的元素,在这里是一个jQuery对象
var me = this;
// 下面这句就会报错
m = me.datas.num + m;
}
那么如何解决上面的问题,答案就是$.proxy(fn, contenxt),这个方法可以改变函数执行时的上下文:
bind: function () {
var me = this;
me.test.on('click', $.proxy(me['_do'], this));
},
上面的代码使me['_do']被调用时,this指向app,那么在me['_do']中就可以获取app中的数据,从而解决了上面this的指向问题。
总结
上面的js代码实现了一个简陋的可编辑表格的功能,这段代码是京程一灯袁志佳在腾讯视频公开课上讲的代码,我贴在这里来提醒自己:前端javascript的编写还有许多要学习和挖掘的地方。代码中主要用到了jQuery.proxy()这个强大的函数,另外就是这种对象封装的思想。
存在的问题
虽然$.proxy()解决了this的指向问题,但它也不是完美的。这里在使用事件委托时就要小心了:
render: function () {
var me = this;
me.document= $(document);
},
bind: function() {
document.on('click', 'ul li', $.proxy(me['_do2'], this));
},
_do2: function(e) {
var eleTarget = $(e.target);
}
因为_do2中的this不再指向绑定事件的元素ul li,所以要想在_do2中获取ul li就有些麻烦,尤其是li中嵌套比较多的子元素时:
<ul>
<li>
<div><span></span>...</div>
</li>
</ul>
_do2中的eleTarget由于事件冒泡的原因可能是:span、div、li,那么该如何解决这个问题?很遗憾我没有想到好的解决方法,提供两个思路:1,如果li中嵌套了太多的子元素,那么事件委托在这里就不是一个好的解决方案了。2,如果嵌套的子元素不多,那么还可以通过查找的方法找到ul li,这个也是可行的。当然,如果抛开本文章,单纯使用事件委托还是可以的:
$(document).on('click', 'ul li', function(e) {
var this = $(this);
});
因为这里的this始终指向ul li,即委托的元素ul li。
这篇文章最初发表在我自己折腾的博客站点上:如何把js的代码写的更加容易维护(一)--面向对象编程,该博客用了一位前辈开源的源码,基于thinkjs和vuejs开发,欢迎大家来逛逛。
如何把js的代码写的更加容易维护(一)--面向对象编程的更多相关文章
- 自写脚本实现上线前本地批量压缩混淆 js , css 代码。
最近做项目遇到一个要求,就是把本地的 js 和 css 进行压缩后再上线,由于之前项目并没有使用 webpack 之类的库,项目上也因为一些机密不能在线上压缩,这无疑给代码打包压缩带来了很大麻烦,于是 ...
- CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅
首页 登录注册 CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅 阅读 8113 收藏 927 2017-09-26 原文链接:github.com 腾讯云容器服务CSS,立 ...
- 2019前端面试系列——JS高频手写代码题
实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...
- 如何让你的JS代码写的更漂亮
感觉这篇文章总结的js的规范写法不错,拿来收藏.转自:https://mp.weixin.qq.com/s/AtR94IL9BW9EXOTnKOilmA 1. 按强类型风格写代码 JS是弱类型的,但是 ...
- 引擎渲染速度测试--我js代码写得少你不要骗我
上一张图,很多人都看过的 地址:http://aui.github.io/artTemplate/test/test-speed.html 这个地址是在看artTemplate的时候看到的,很早都看过 ...
- JS函数 编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数。
编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数. 任务 第一步: 编写代码完成一个函数的定义吧. 第二步: 我们来补充函数体中的控制语句,完成函数功能吧. 提示: ...
- 网络问卷调查js实现代码
昨天一个同行妹纸写了一个网络问卷调查的效果,但是有bug,于是就来问我该如何解决这个bug.经过我的分析,bug主要还是出在复选框的那部分,经过修改,bug问题解决,现在贴出如下代码,仅供大家参考: ...
- js原生代码实现轮播图案例
一.轮播图是现在网站网页上最常见的效果之一,对于轮播图的功能,要求不同,效果也不同! 我们见过很多通过不同的方式,实现这一效果,但是有很多比较麻烦,而且不容易理解,兼容性也不好. 在这里分享一下,用j ...
- 原生JS实战:写了个斗牛游戏,分享给大家一起玩!
本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5869953.html 该程序是本人的个人作品,写的不好,未经本人允许,请 ...
随机推荐
- python小练习:用户三次登陆, 购物车
2018.12.1 周末练习: 1.用户三次登陆 from random import randint i = 1 while i < 4: num = 0 verify_code = '' w ...
- Tars --- Hello World
服务端开发 1,创建一个 webapp maven 项目,pom.xml 导入依赖 <dependency> <groupId>com.tencent.tars</gro ...
- linux上部署engineercms、docker和onlyoffice实现文档协作
等了好久,这次终于下决心在局域网部署了linux系统,并安装docker和load了onlyoffice,利用engineercms进行资料管理和文档协作. 我整理了完整文档,见我的网盘. engin ...
- Python使用map,reduce高阶函数模拟实现Spark的reduceByKey算子功能
# 使用默认的高阶函数map和reduce import randomdef map_function(arg): # 生成测试数据 return (arg,1) list_map = list(m ...
- [20170705]diff比较执行结果的内容.txt
[20170705]diff比较执行结果的内容.txt --//有时候需要比较2个命令输出的结果进行比较,比较笨的方法如下,例子: $ lsnrctl status LISTENER_SCAN2 & ...
- 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之@classmethod,@staticmethod
定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...
- linux上文件内容去重的问题uniq/awk
1.uniq:只会对相邻的行进行判断是否重复,不能全文本进行搜索是否重复,所以往往跟sort结合使用. 例子1: [root@aaa01 ~]# cat a.txt 12 34 56 12 [root ...
- MySQL--eq_range_index_dive_limit参数学习,MYSQL 5.6 5.7处理数据分布不均的问题
官方文档如下描述:This variable indicates the number of equality ranges in an equality comparison condition w ...
- 转:更改SQLServer实例默认字符集
需求 安装数据库时,将字符集安装成了“SQL_Latin1_General_CP1_CI_AS”,现在需要将其更改为“Chinese_PRC_CI_AS”. 方法 重新生成系统数据库 ,然后还原配 ...
- C#项目实践之一——WPF多媒体通讯录
1.Window.Resources 是一种Window级的资源定义. Window.Resources它的作用范围就是在Window容器里的所有子控件,也只有这些子控件才能引用/调用这些资源 Gr ...