1. 项目中在绑定事件的时候总想在触发前,或者触发后做一些统一的判断或逻辑,在c#后端代码里,可以用Attribute, filter等标签特性实现AOP的效果,可是js中没有这种用法,归根到本质还是不支持类型的拦截和判断,所以没法实现,但是js的灵活就在于可以通过原型链, 高阶函数,闭包等特性来实现类似的效果,这里记录一下便于复习

    //AOP: after
Function.prototype.after = function (afterFn) {
var _self = this;
return function () {
var ret = _self.apply(this, arguments);
if (ret === false) {
return false;
}
afterFn.apply(this, arguments);
return ret;
}
} //AOP: before
Function.prototype.before = function (beforeFn) {
var _self = this;
return function () {
var ret = beforeFn.apply(this, arguments);
if (ret === false) {
return false;
}
return _self.apply(this, arguments);
}
}

2. 用法下面的例子是工程中实用, 在tab点击的时候,一般情况没打开一个tab要绑定一个或多个事件做点击,关闭等处理,这里实现的方法就是在父元素统一只绑定一个事件,都通过冒泡来触发,这种好处就是新加tab不用绑定事件,不好的就是可能tab层级复杂,需要做很多元素的判断来决定触发什么事件,比如说下面的关闭事件里面先判断后,要是没有触发,在判断触发点击事件,这样写的逻辑清晰,功能模块可以分开,利于解耦,效果也能很好实现!!!

                _bindEvents: function () {
var g = this,
p = this.options,
container = g.tab.bar.container; // 标签点击事件, 统一只绑定父元素一次
container.nav.bind("click.tab.nav", function (e) {
if (e.target === e.currentTarget) {
e.stopPropagation();
return;
}
g._tabCloseClick.after(g._tabBarClick).call(g, e);
}); }

3. 当然还有函数的防抖和节流的实现:

函数防抖就是为了让一个函数在一定的时间只执行一次,即使被多次触发,典型应用就是tab标签打开很多的时候,不停的拖动窗体大小或者改变位置,这样标签会有一些动画效果用来自适应窗体大小,但是要是频发的拖动窗体,这些动画效果就会被触发多次,导致拖完了后一段时间内,这种效果不停在重复,延迟严重,所以用debounce就可以在一定时间后触发一次效果就可以了,性能提升的同时,体验也很好

函数节流 就是规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效,在项目中应用的例子就是在手风琴点击展开层级的时候,如果用户在短时间内重复快速点击多次,这样这个层级就会不停的触发多次,展开收起又展开,感觉发疯一样,所以这时候用throttle节流一下, 比如在300ms内就触发一次,不管你点了多少次,这样体验大大提高

    /**
* 函数防抖, 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 延迟时间,也就是阈值,单位是毫秒(ms)
* @return {Function} 返回一个防抖了的函数
*/
vango.utils.debounce = function (fn, delay) {
var timer;
return function () {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
} /**
* 函数节流,规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效
* @param fn {Function} 实际要执行的函数
* @param wait {Number} 延迟时间,也就是阈值,单位是毫秒(ms)
* @return {Function} 返回一个节流了的函数
*/
vango.utils.throttle = function (func, wait, options) {
/* options的默认值
* 表示首次调用返回值方法时,会马上调用func;否则仅会记录当前时刻,当第二次调用的时间间隔超过wait时,才调用func。
* options.leading = true;
* 表示当调用方法时,未到达wait指定的时间间隔,则启动计时器延迟调用func函数,若后续在既未达到wait指定的时间间隔和func函数又未被调用的情况下调用返回值方法,则被调用请求将被丢弃。
* options.trailing = true;
* 注意:当options.trailing = false时,效果与上面的简单实现效果相同
*/
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function () {
previous = options.leading === false ? 0 : new Date();;
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
var now = new Date();;
if (!previous && options.leading === false) previous = now;
// 计算剩余时间
var remaining = wait - (now - previous);
context = this;
args = arguments;
// 当到达wait指定的时间间隔,则调用func函数
// 精彩之处:按理来说remaining <= 0已经足够证明已经到达wait的时间间隔,但这里还考虑到假如客户端修改了系统时间则马上执行func函数。
if (remaining <= 0 || remaining > wait) {
// 由于setTimeout存在最小时间精度问题,因此会存在到达wait的时间间隔,但之前设置的setTimeout操作还没被执行,因此为保险起见,这里先清理setTimeout操作
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
// options.trailing=true时,延时执行func函数
timeout = setTimeout(later, remaining);
}
return result;
};
};

5. 对于一个系统来说事件的设计当然必不可少,平台中简单的实现了一下事件总线的机制,记录一下

    vango.event = (function () {

        var _callbacks = {};

        var on = function (eventName, callback) {
if (!_callbacks[eventName]) {
_callbacks[eventName] = [];
} _callbacks[eventName].push(callback);
}; var off = function (eventName, callback) {
var callbacks = _callbacks[eventName];
if (!callbacks) {
return;
} var index = -1;
for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i] === callback) {
index = i;
break;
}
} if (index < 0) {
return;
} _callbacks[eventName].splice(index, 1);
}; var trigger = function (eventName) {
var callbacks = _callbacks[eventName];
if (!callbacks || !callbacks.length) {
return;
} var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < callbacks.length; i++) {
callbacks[i].apply(this, args);
}
}; return {
on: on,
off: off,
trigger: trigger
};
})();

JS在项目中用到的AOP, 以及函数节流, 防抖, 事件总线的更多相关文章

  1. 我在一个前端项目中用js整理的一些通用方法,其中使用到的思想,主要就是约定了。

    把名称和后台来的json数据约定起来,可以达到的效果就是可以将东西统一化,减少差异,提升模块等的通用性,此后就可以实现具体不同模块内容可以自动或拷贝赋值的方式 2016.7.18 refactor s ...

  2. 项目中用到的input 遇到的问题的归类

    input 前几天 为了这个词 用在搜索框被我们总监喷,为了加强印象,我把它记录下来 最原始的造型 <input type="text" value="搜索&quo ...

  3. iKcamp团队制作|基于Koa2搭建Node.js实战项目教学(含视频)☞ 环境准备

    安装搭建项目的开发环境 视频地址:https://www.cctalk.com/v/15114357764004 文章 Koa 起手 - 环境准备 由于 koa2 已经开始使用 async/await ...

  4. 在项目中用过Spring的哪些方面?及用过哪些Ajax框架?

    在项目中用过Spring的哪些方面?及用过哪些Ajax框架? 解答:在项目使用过Spring IOC ,AOP,DAO,ORM,还有上下文环境. 在项目使用过Ext,Juery等Ajax框架.

  5. JS/TS项目里的Module都是什么?

    摘要:在日常进行JS/TS项目开发的时候,经常会遇到require某个依赖和module.exports来定义某个函数的情况.就很好奇Modules都代表什么和有什么作用呢. 本文分享自华为云社区&l ...

  6. 项目中用到RouteTable,发布到IIS7中无法访问

    项目中用到RouteTable,发布到IIS7中,访问之后没有任何反应,google半天终于找到了解决方法,就是要把iis的“HTTP重定向”功能打开

  7. 8 步搭建 Node.js + MongoDB 项目的自动化持续集成

    任何事情超过 90 秒就应该自动化,这是程序员的终极打开方式.Automating shapes smarter future. 这篇文章中,我们通过创建一个 Node.js + MongoDB 项目 ...

  8. iOS 项目中用到的一些开源库和第三方组件

    iOS 项目中用到的一些 iOS 开源库和第三方组件 分享一下我目前所在公司 iOS 项目中用到的一些 iOS 开源库和第三方组件, 感谢开源, 减少了我们的劳动力, 节约了我们大量的时间, 让我们有 ...

  9. iOS:项目中用到的Cookie

    1.介绍: 做了这么长时间开发,Cookie真是用的不多,可是现在不一样了,这次的项目我用到了Cookie.其实,Cookie的使用在项目中愈加的频繁,一般情况下,提供的接口是用Cookie来识别用户 ...

随机推荐

  1. centos LAMP第三部分php,mysql配置 php配置文件 配置php的error_log 配置php的open_basedir 安装php的扩展模块 phpize mysql配置第二十一节课

    centos   LAMP第三部分php,mysql配置 php配置文件   配置php的error_log  配置php的open_basedir 安装php的扩展模块 phpize  mysql配 ...

  2. 【转】Deep Learning(深度学习)学习笔记整理系列之(七)

    9.5.Convolutional Neural Networks卷积神经网络 卷积神经网络是人工神经网络的一种,已成为当前语音分析和图像识别领域的研究热点.它的权值共享网络结构使之更类似于生物神经网 ...

  3. git相关使用技巧和问题

    本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERGE_HEAD exists). ...

  4. java基础语法 List

    List:元素是有序的(怎么存的就怎么取出来,顺序不会乱),元素可以重复(角标1上有个3,角标2上也可以有个3)因为该集合体系有索引, ArrayList:底层的数据结构使用的是数组结构(数组长度是可 ...

  5. 获取用户真实Ip地址

    REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP.如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP.HTTP_CLIENT_IP 是代理服务器发送的HTTP头.如 ...

  6. zwPython,字王集成式python开发平台,比pythonXY更强大、更方便。

    zwPython,字王集成式python开发平台,比pythonXY更强大.更方便. 更强大,内置opencv.cuda/opencl.NLTK自然语言.pygame游戏设计等多个重量级模块库. 更方 ...

  7. Android开发--取消AsyncTask

    在Android应用开发过程中,为了防止UI线程堵塞,耗时的工作都应该另起一个后台线程来完成,其中AsyncTask就是其中的一种方式.最近在案子中需要“停止/取消”某个AsyncTask,在网上查了 ...

  8. [置顶] SNMP协议详解<三>

    在上篇文章中,说到了SNMPv3主要在安全性方面进行了增强,采用USM(基于用户的安全模型)和VACM(基于视图的访问控制模型)技术.下面我们就主要讲解SNMPv3的报文格式以及基于USM的认证和加密 ...

  9. 学习Zookeeper之第3章Zookeeper内部原理

    第 3 章 Zookeeper 内部原理 3.1 选举机制 3.2 节点类型 3.3 stat 结构体 3.4 监听器原理   1)监听原理详解   2)常见的监听 3.5 写数据流程 第 3 章 Z ...

  10. UVa 11806 拉拉队(容斥原理)

    https://vjudge.net/problem/UVA-11806 题意: 在一个m行n列的矩形网格里放k个相同的石子,有多少种方法?每个格子最多放一个石子,所有石子都要用完,并且第一行.最后一 ...