时间: 2015-11-15 00:00 栏目: JavaScript 浏览: 8017 赞: 67 踩: 3 字体: 大 中 小
以下为本篇文章全部内容:
我叶子,现在我来讲讲JavaScript哪些事。
在web开发中 我们或多或少会用到好多JS脚本,在组织这些脚本时总没有一些比较规范的做法,可以说也是因为JS在web中的可以任意地方使用 任意插入到我们代码中,而我们没有系统的了解过JS在web中的工作机制,对我们认识JS来说 它仅仅是实现一些小互动的脚本语言。
接下来 我要来讲讲如果让我们在之前杂乱无章 乱堆脚本的习惯 慢慢转变成为高效组织代码,并且避免在很多情况下JS的冲突 已经梳理我门web中使用JS的工作。
首先我要先讲几个需要了解的知识点。
注意:这里只针对已经熟悉JS语法的程序员进行提高,如果你对JS一窍不通 你可以先绕行去看看w3cschool 的JS教程。
1 代码放在哪了比较合适。
在开发中,我们很多人对自己的js 在哪书写没有明确的要求,代码到处都是,有些嵌套在html标签中 有些 甚至在代码顶部 html之前 等等。
那么 现在一般主流的要求都是怎么样的情况呢?
第1种情况 应该放在 <head></head> 中间。 在body 渲染之前。
第2种情况 放在 </body> 结束只后 </html> 结束之前 在body渲染之后。
在这两种都是比较普遍的做法。
那么 这两种做法 的好处和不好之处是怎么样的呢?
在第1种 情况下 我们的js脚本 可能会先运行比如 jq 等框架 在<body> 中如果有使用$等 是不会报错的!在一些比如 由编辑器或者其他加入的代码 执行时是不会报错的! 但是如果是第2种情况 那么 可能中间插入的代码会导致执行错误! 但是 我们一般不应该在body中直接使用 $ 标记,而这种方式的缺点 是 每次打开页面 需要先全部加载完成JS代码才能渲染BODY 对浏览者的体验上是有一定影响的。 这个时候 我们考虑 把 JS 放入底部。并且不应该在<body>中还有任何要执行的Js代码 一切要执行的互动操作需在最后加载时执行。
有些朋友可能会把CSS放在最后 这个是错误的CSS是对body渲染 必须前提加载的。如放在最后 就会形成2次渲染对浏览器效率或者 浏览者体验来讲都是不合适的。
2 请注意你的变量被污染
很多朋友在书写JS的时候,总会出现由于变量被重新定义造成很多奇怪的错误,而且无法察觉。
比如 在做模板时 里面嵌套一段代码 如
var url="http://www.aa.com";
然后 中间包含了另外一个JS 而这个Js文件中也有一个 url
到最后的时候 有一个地方调用了 url
但是 好多人都不清楚 这个url到底是哪一个url 在很多代码中 就会出现问题了~~
那么我给出的建议是! 不要在你的代码中使用全局变量,也不要使用全局的 函数 不要入文件开头就直接 var xxx
如
a.js
var a=$("#id"); function func(){}
这样是不合适的写法。
应该改成如下
a.js
(funciton($){ var a=$("#id"); function func(){} })(jQurey);
即使 你没有用到jq 你的代码 也应该这样写
a.js
(function(){ var a="11"; function func(){} //做你的事情... })();
可能有些朋友就会问 如果这样写那么 我们在标签中 onclick="func()" 不就不能访问了?
恩 确实是不能访问了。
但是我们可以 用很多办法 绑定这个onclick
比如 最直接的做法
(function(){ var a="11"; function func(){} ddocument.getElementById().onclick=function(){ func()}; //做你的事情... })();
或者用 JQ的 on
还有很多其他的 比如 addEventListener 等等.
何况 上面我们也说到,要养成JS书写习惯,请不要在你的代码中直接嵌入JS代码,哪怕是 标签中的 onXxxx 事件
为啥要扩起来呢? 是因为 你不应该写一个全局的变量,这样你不知道在哪会出现这个变量被覆盖了!导致后面的逻辑全部错误!不能保证别人的代码会和你的代码有冲突而得到一些莫名其妙的错误!
你应该把自己的代码 保护起来 独立出来 不受外界干扰。
如果 你实在要用到全局变量 你也不应该
var a="111";
而应该用 window.a='111'; 在替代你的全局变量。
这样在你的代码看起来 你也知道这个a是全局的 不是局部的。
3 熟悉事件驱动和异步执行机制
在JS中,我们经常用到的很多异步或者事件驱动,但是我们也不知道它们的执行机制过程,而我们只是用了。
js 的执行都是以事件 触发 这样完成我们的工作的。
比如 页面完成后 会触发 加载完成事件,页面改动会触发改动事件 点击一个按钮 触发点击事件 再比如我们AJAX回返回来会触发页面到达的事件等等。
在我看来 JS何时执行我们的代码,就需要我们了解 这些事件什么时候触发,而JS在触发事件后是异步完成的。他们之间存在着一些微妙的关联但又独立。
那么 我们可以理解为 js 除了引入文件顺序执行完后 其他要做的事情就是等着触发事件 并异步执行相应的事件程序。
我们认为 你不应该在代码顺序执行代码中做任何事情。比如 直接处理一些代码等。而我们正确的做法应该让JS加载完成后,准备好我们要监听的事件 等待浏览器去触发。
例如:Jq 中的 ready 或者 原生的 onload 或者 监听 addEventListener("load") 等等。
页面加载完成后 开始干活了,我们可能会在上面监听更多的事件,但是 我要说明的一点 就是 当页面触发后 并不会按照我们监听的顺序去处理代码!
比如 如下代码:
window.addEventListener('load',function(){ window.test='abc';}); window.addEventListener('load',function(){ alert(window.test);});
在我们看来 似乎 会提示 abc 但是 其实不然,在页面加载完成后 它可能会先执行后面的 alert(window.test); 再去执行 window.test;
为了解决这个问题
JQ 给我们的 ready 中做了顺序安排!!
如上代码换成JQ
$(function(){ window.test='abc';}); $(function(){ alert(window.test);});
那么 我们会得到 提示 abc 这个结果!
接下来 问题来了!那么我们如何用原生实现自己的顺序呢?答案是做队列如
(function(){ var loadfuncs=[]; function addLoad(func){ loadfuncs.push(func); } window.addEventListener('load',function(ev){ for(var i in loadfuncs){ loadfuncs[i].call(this,ev); } }); })();
然而 比如 load click mouseover 。。。。 等等这些事件都是系统为我们准备好的~~
而有一些事件 其实我们是可以自己定义的!
比如 我们做一个 事件 名称叫做 test 事件
在这里我用JQ来演示,具体原生如何实现 我希望大家可以自行研究!!
(function($){ $(window).on('test',function(ev){ alert('testEvent'); }); //3秒后触发 window.setTimeout(function(){ $(window).triggerHandler('test'); },3000); })(jQuery);
$('#id').triggerHandler('#id');和 $(window).trigger('click'); 的区别在于 前者是执行 click 所绑定的函数不影响显示效果 ,后者除了执行其绑定的函数外还会影响html的显示效果。比如 checkbox 前者并不会打上勾 后者会打上勾.
那么 自定义事件对于我们写代码来讲有什么帮助呢?
主要是为外界提供有效的接口或者准备的服务
比方说 我们现在 做一个封装 可是我们还不知道上传完成后要做什么事情,因为要做的事情交给其他人来完成!
(function($){ function Upload(jqelem){ jqelem.triggerHandler('init');//初始化时通知节点已经初始化了 //这里做了个iframe上传的提交 后 $('iframe').on('load',funciton(ev){ var data=获得上传的数据后; jqelem.triggerHandler('upload',[data]); //上传结束后通知已经结束了 }); } var input=$('#id'); input.on('init',function(){ //当初始化后做啥事情 }); input.on('upload',function(ev,data){ //当上传完成后做啥事情 }); Upload(input); })(jQuery);
这样做的好处是提供两个外部事件 在程序处理中 可以触发执行外部程序、而外部程序要做什么或者没有监听都是可以的!
当然 你也可以这样写
(function($){ function Upload(jqelem,init,upload){ if(init){ init(); } //这里做了个iframe上传的提交 后 $('iframe').on('load',funciton(ev){ var data=获得上传的数据后; if(upload){ upload(data); } //上传结束后通知已经结束了 }); } var input=$('#id'); var a= Upload(input,function(){ //当初始化后做啥事情 },function(data){ //当上传完成后做啥事情 }); })(jQuery);
这种也是异步通知,但是需要提前去制定穿入的 方法,以参数形式传入回调函数。这种方式 和 上面的使用事件方式来讲,前面的更直接一些。我本人是推荐以事件驱动机制来实现回调的。
未完待续。。。
总赞数量:18274
总踩数量:128087
文章数量:29