浅谈JS和jQuery优劣
现在各种类库满天飞,说jQuery有多快多快,可是对前端大牛来说,更定不会止步于jQuery,因而常常听到高级的前端工程师追求原生js,为何?答案是原生JS要更快,原因是JQuery这样的库必须要兼容各种浏览器和低版本和许多其他的东西,考虑通用性必然会导致性能的损耗。
当然,我不是提倡写代码纯用原生JS实现,请记住:“框架能够让我们走的更快,但只有了解原生的JS才能让我们走的更远”。
下面直接用代码示例:流行的常用的JQuery功能用原生JS实现。
选择器
JQuery选择器的强大无需赘言,然而在大多数的情况下,我们可以使用相同的代码量用原生JS轻易实现。
1.获取页面所有的div
/* jQuery */ $(\”div\”) /* native equivalent */ document.getElementsByTagName(\”div\”)
2.获取某类名相同的一群元素
/* jQuery */ $(\”.my-class\”) /* native equivalent */ document.querySelectorAll(\”.my-class\”) /* FASTER native equivalent */ document.getElementsByClassName(\”my-class\”)
3.更复杂的一些选择器
/* jQuery */ $(\”.my-class li:first-child\”) /* native equivalent */ document.querySelectorAll(\”.my-class li:first-child\”) /* jQuery */ $(\”.my-class\”).get(0) /* native equivalent */ document.querySelector(\”.my-class\”)
DOM操作JQuery频繁功能就是操作DOM元素,诸如插入或删除一个元素。当然,如果使用原生JS实现这些功能,代码量肯定是会有所增加的,不过我们也可以将这些功能封装成函数,下面是一些常用的DOM操作的原生JS实现。
1.插入HTML元素
/* jQuery */ $(document.body).append(\”<div id=\’myDiv\’><img src=\’im.gif\’/></div>\”); /* CRAPPY native equivalent */ document.body.innerHTML += \”<div id=\’myDiv\’><img src=\’im.gif\’/></div>\”; /* MUCH BETTER native equivalent */ var frag = document.createDocumentFragment(); var myDiv = document.createElement(\”div\”); myDiv.id = \”myDiv\”; var im = document.createElement(\”img\”); im.src = \”im.gif\”; myDiv.appendChild(im); frag.appendChild(myDiv); document.body.appendChild(frag);
CSS操作
在JQuery中可以轻松实现对css的操作,增加属性、删除属性或是检测是否存在某个类。那么你是否觉得使用原生JS实现会很麻烦呢?其实不然,因为有classList。下面是一些关于JQuery css操作的JS原生实现。
// get reference to DOM element var el = document.querySelector(\”.main-content\”); //—-Adding a class—— /* jQuery */ $(el).addClass(\”someClass\”); /* native equivalent */ el.classList.add(\”someClass\”); //—-Removing a class—– /* jQuery */ $(el).removeClass(\”someClass\”); /* native equivalent */ el.classList.remove(\”someClass\”); //—-Does it have class— /* jQuery */ if($(el).hasClass(\”someClass\”)) /* native equivalent */ if(el.classList.contains(\”someClass\”))
当我们简单地逐个设置Css的属性,而并非将它们全部传递给JQuery的Css函数时,性能明显会快很多。而且,真的不会添加什么额外的代码。
// get reference to a DOM element var el = document.querySelector(\”.main-content\”); //—-Setting multiple CSS properties—- /* jQuery */ $(el).css({ background: \”#FF0000\”, \”box-shadow\”: \”1px 1px 5px 5px red\”, width: \”100px\”, height: \”100px\”, display: \”block\” }); /* native equivalent */ el.style.background = \”#FF0000\”; el.style.width = \”100px\”; el.style.height = \”100px\”; el.style.display = \”block\”; el.style.boxShadow = \”1px 1px 5px 5px red\”;
show与hideshow()与hide()应该也是JQuery中十分常用的方法,原生JS实现同样轻松。
// get reference to a DOM element var el = document.querySelector(\”.main-content\”); //—-show() or hide()—- /* jQuery */ $(el).show(); $(el).hide(); /* native equivalent */ el.style.display = \’\’; el.style.display = \’none\’;
事件绑定
// get reference to a DOM element var el = document.querySelector(\”.main-content\”); //—-Event Listener off—- /* jQuery */ $(el).off(eventName, eventHandler); /* native equivalent */ el.removeEventListener(eventName, eventHandler); //—-Event Listener on—- /* jQuery */ $(el).on(eventName, eventHandler); /* native equivalent */ el.addEventListener(eventName, eventHandler);
jQuery的确是个了不起的库,如果同样轻松的使用JS实现jQuery,尽量使用JS。即使优化有点吹毛求疵,由于html5游戏的迅速崛起,这点优化就显得格外的宝贵。
文/丁向明
做一个有博客的web前端自媒体人,专注web前端开发,关注用户体验,加我qq/微信交流:6135833
http://dingxiangming.com
深圳嘉华学校:什么是JQuery?
什么是JQuery?这里将由北大青鸟深圳嘉华来介绍下关于JQuery部分知识,希望能让大家对JQuery有初步的映象。
JQuery是继prototype之后又一个优秀的Javascript库。它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器,能很便利的处理HTML、events、实现动画效果,并且方便地为网站提供AJAX交互。jQuery 库可以通过一行简单的标记被添加到网页中。
您需要具备的基础知识
在您开始学习 jQuery 之前,您应该对以下知识有基本的了解:
HTML
CSS
JavaScript
什么是 jQuery ?
jQuery是一个JavaScript函数库。
jQuery是一个轻量级的\”写的少,做的多\”的JavaScript库。
jQuery库包含以下功能:
HTML 元素选取
HTML 元素操作
CSS 操作
HTML 事件函数
JavaScript 特效和动画
HTML DOM 遍历和修改
AJAX
Utilities
提示: 除此之外,Jquery还提供了大量的插件。
为什么使用 jQuery ?
目前网络上有大量开源的 JS 框架, 但是 jQuery 是目前最流行的 JS 框架,而且提供了大量的扩展。
很多大公司都在使用 jQuery, 例如:
Microsoft
IBM
Netflix
jQuery是否适用于所有浏览器?
jQuery 团体知道JS在不同浏览器中存在着大量的兼容性问题,目前jQuery兼容于所有主流浏览器, 包括Internet Explorer 6!
用心办好学,深圳嘉华邀您加入互联网队伍!
微信号:jhzyjy(长按复制)
我们专注IT教育,欢迎你前来咨询!
js大佬不愿意告诉你jq背后的那些事
JQuery
什么是
第三方的极简化的DOM操作函数库
为什么
1. DOM操作的终极简化
核心DOM: 万能, 但繁琐
HTML DOM: 简单,但不是万能
jQuery: 对DOM操作的终极简化
1. DOM操作
增,删,改,查
2. 事件
3. 动画效果
4. Ajax
2. 屏蔽了浏览器兼容性问题
凡是jQuery允许使用的,都屏蔽了兼容性问题
如何:
版本
1.x
兼容旧浏览器
.js
未压缩过的代码
可读性好
学习用
大
.min.js
压缩版本
小
毫无可读性
删除注释
去掉换行和空字符
极简化变量名
2.x 和 3.x
不再兼容旧浏览器
小
先引入jquery.js, 再编写自定义脚本
2种方法
1. 将jquery.js下载到服务器本地,在script中使用服务器路径
2. 使用CDN网络上共享的jquery.js
内容分发网络
可根据客户端到服务器的网络状况和访问量智能选择最优的服务器下载资源
生产环境中用的最多
原理
向全局添加了一种jQuery新类型
jQuery构造/工厂函数
创建jQuery类型的子对象
1. 查找,并封装jQuery对象
2. 将DOM元素封装为jQuery对象
其实可简写为:$(\”selector\”|DOM)
window.jQuery=window.$=jQuery
jQuery.fn原型对象
是所有jQuery对象的父对象
封装了所有简化版API
jQuery对象
封装DOM对象的类数组对象,并提供对DOM对象执行操作的简化版API
为什么
DOM对象不包含,也不能使用jQuery简化版API
因为不是jQuery类型的子对象
只有将DOM对象封装进jQuery对象后,才能使用简化版API
如何
2种
1. 用$(\”selector\”)直接查找
返回包含找到的DOM对象的集合
jQuery对象
2. 如果已经获得一个DOM对象
先用$(DOM对象)封装DOM对象为jQuery对象
比如:
this, e.target
DOM对象
$(this), $(e.target)
jQuery对象
强调:
1. 尽量减少使用$(…)的次数
每$(…)一次就新创建一个jQuery对象
2. 尽量减少查找的次数
所有查找都是遍历,反复查找,效率低
解决
1. 如果一个jQuery结果对象可能被反复使用,就临时保存在变量中
2. 使用链式操作
查找
按选择器查找
基本选择器
同CSS
#id .class element * 选择器1,选择器2
层次选择器
同CSS
父级 后代 > + ~
过滤选择器
子元素过滤
同CSS
在父元素内编号
:first-child
:last-child
:nth-child(i/odd/even/2n/2n+1)
强调:
下标从1开始,且仅限于当前父元素内
:only-child
基本过滤(位置过滤)
先将符合条件的所有元素保存在一个集合中再统一编号
和元素在其父元素下的位置无关
:first/last
选择结果集合中第一个/最后一个元素
:even/odd
选择结果集合中下标为偶数或奇数的元素
强调:
下标从0开始
:eq/gt/lt(i)
选择结果集合中下标等于/大于/小于i位置的元素
否定选择器:
:not(任意selector)
属性过滤
同CSS
[属性名]
[属性名=值]
[属性名!=值]
:not([属性名=值])
[属性名^=开头]
[属性名$=结尾]
[属性名*=值]
selector1selector2…
而且
内容过滤
:contains(文本)
按元素的内容文本
:has(\’selector\’)
按子元素的特征来选择父元素
:empty
:parent
:not(:empty)
可见性过滤
:visible
:hidden
display:none
input type=\”hidden\”
表单过滤
:input
input, select, textarea, button
如果只想查找一种表单元素
可用元素选择器
:type属性
:text :password :checkbox :radio :button :submit :reset :image :file :hidden
状态过滤
同CSS
:disabled :enabled :checked :selected
节点间关系
父子关系
$(\”…\”).parent()
获得当前元素的父元素
$(\”…\”).children([\”selector\”])
仅找*直接*子元素中符合selector条件的
$(\”…\”).find(\”selector\”)
在*所有后代*中查找符合selector条件的
$(…).children().first()
:first-child
$(…).children().last()
:last-child
兄弟关系
$(\”…\”).next/prev([\”selector\”])
紧邻的前一个或后一个兄弟元素
必须紧邻
$(\”…\”).nextAll/prevAll([\”selector\”])
之后/之前所有符合条件的兄弟
$(\”…\”).siblings([\”selector\”])
除自己之外的所有兄弟
API通用特点
1. 自带forEach的效果
对$(\”…\”)结果对象执行的操作,相当于自动应用到结果中每个元素上
2. API两用
没给新值,就读取属性值;给了新值,就是修改属性值
3. 每个API都再次返回结果对象本身
$(\”…\”)之后可使用链式操作反复调动多个API
为什么链式操作
1. 避免重复创建jq对象
每次调用$都会创建新的jq对象
2. 减少查询次数
3. 节省变量的使用
修改
内容
html内容
$(\”…\”).html([\”html代码片段\”])
两用
文本内容
$(\”…\”).text([\”文本内容\”])
两用
表单元素内容
$(\”…\”).val([\”值\”])
两用
清除内容
$(\”…\”).empty()
属性
访问标准属性
获取
var value=$(\”…\”).attr(\”属性名\”)
修改
只修改一个属性
$(\”…\”).attr(\”属性名\”,值)
同时修改多个属性
$(\”…\”).attr({ 属性名:值, 属性名:值, })
访问三大状态
包括: disabled checked selected
$(\”…\”).prop(…)
用法同attr()
另见:
移除属性
$(\”…\”).removeAttr/removeProp(\”属性名\”)
自定义扩展属性
$(…).data()
样式
直接修改css属性
获取css样式(计算后的样式)
$(\”…\”).css(\”css属性名\”)
相当于getComputedStyle
修改css样式
只修改一个css样式:
$(\”…\”).css(\”css属性名\”,值)
相当于elem.style
为每个元素的css属性动态生成不同的值
$(\”…\”).css(\”css属性名\”, function(i){return 值})
i会依次获得每个元素的下标
返回值会被依次设置到每个元素的指定css属性
同时修改多个css样式:
$(\”…\”).css({ css属性名:值, css属性名:值, … })
强调:
所有CSS属性名都要去横线变驼峰
纯数字的属性值不必加单位
通过修改class批量修改样式
判断是否包含指定class
$(\”…\”).hasClass(\”类名\”)
添加class
$(\”…\”).addClass(\”类名\”)
移除class
$(\”…\”).removeClass(\”类名\”)
切换class
$(\”…\”).toggleClass(\”类名\”)
if(.hasClass(…)) .removeClass(…) else .addClass(…)
添加,删除,替换和复制
添加
1. 创建新元素
var $newElem=$(\”html代码片段\”)
2. 将新元素添加到DOM树
结尾/开头插入
$(parent).append/prepend($newElem)
在某个child前后插入
$(child).before/after($newElem)
简写:
$(parent).append(\”html代码片段\”)
删除
$(\”…\”).remove()
替换
$(\”现有元素\”).replaceWith(\”新元素html代码\”)
用右替换左
$(\”新元素html代码\”).replaceAll(\”现有元素\”)
用左替换右
克隆
$(\”…\”).clone()
浅克隆
仅复制属性,不复制行为
$(\”…\”).clone(true)
深克隆
即复制属性,又复制行为
事件
鄙视
jQuery有几种事件绑定方式
.bind/unbind(\”事件名\”,fn)
.unbind(\’事件名\’,fn)
.unbind(\’事件名\’)
.unbind()
.one(\”事件名\”,fn)
废弃
$(\”selector\”).live/die(\”事件名\”,fn)
利用冒泡
$(\”parent\”).delegate(\”selector\”,\”事件名\”,fn)
简化了利用冒泡中:
1. 用参数selector代替了if判断
2. this->e.target
$(…).undelegate(…)
鄙视题:
bind vs delegate
1. bind直接帮在触发事件的目标元素(子元素)上
delegate绑定在触发事件的元素的父元素上
2. 事件监听个数不一样
bind是每个子元素都添加事件监听
delegate只为父元素添加一个事件监听
3. 动态添加的元素
bind绑定时,要求触发事件的元素必须已经存在
delegate可为父元素下动态添加的子元素提供事件监听
简化
仅为一个元素绑定事件
$(\”…\”).on(\”事件名\”,fn)
bind
利用冒泡/事件委托
$(\”parent\”).on(\”事件名\”,\”selector\”,fn)
delegate
$(…).off(…)
同unbind/undelegate
终极简化版
$(\”…\”).事件名(function(e){…})
this
普通事件绑定
this->触发事件的当前元素
利用冒泡
this->e.target
DOM对象
$(this)
jq对象
模拟触发
$(\”…\”).trigger(\”事件名\”)
模拟触发所有选中元素的指定事件
可简写为
$(…).事件名()
页面加载后触发
只要DOM内容加载完成就触发
DOMContentLoaded
只要等待HTML , js
$(document).ready(fn)
domcontentloaded
早
$().ready(fn)
$(fn)
整个页面加载完才执行
等待HTML,CSS,JS,图片…
window.onload=function(){…}
晚
其实
只要将script代码放在body结尾就可以实现DOM加载后就执行
鼠标事件
mouseover vs mouseenter
mouseover
进出子元素,同样会触发父元素的mouseover
mouseenter
进出子元素,不会再触发父元素的mouseenter
mouseout vs mouseleave
.hover
等效于同时绑定两个事件: mouseenter和mouseleave
如何
.hover(fn_enter, fn_leave)
如果fn_enter和fn_leave的行为可统一成一样的
简写
.hover(fn)
fn即响应enter,又响应leave
向事件处理函数中传入参数
$(…).on(\”事件名\”,data,fn)
其中data: {属性名: 值, …}
读取
fn中
e.data.属性名…
动画效果
简单:
显示隐藏
$(\”…\”).show/hide/toggle(speed,easing,callback)
如果没有参数
默认不带动画,用display控制瞬间显示和隐藏
上下滑动
$(\”…\”).slideUp/slideDown/slideToggle(speed,easing,callback)
淡入淡出
$(\”…\”).fadeIn/fadeOut/fadeToggle(speed,easing,callback)
问题:
不便于维护
使用程序的定时器实现,效率比css动画低
解决
其实都应该用
class + transition
动画结束后执行
每个动画函数的最后一个参数都是一个回调函数,专门在动画结束后自动执行
回调函数中的this->指正在执行动画的DOM对象
万能
$(\”…\”).animate({ css属性: 目标值, css属性: 目标值, … },speed,easing,callback)
多个css属性并发改变
问题
仅对单数值的属性有效
对颜色,字体,C3的变换…无效
排队和并发
并发
1. 放在一个animate中的多个css属性
2. 对不同元素同时执行animate时
排队
对一个元素先后调用animate
$(\”…\”).animate().animate()…
会创建动画队列,依次排队执行
停止:
$(…).stop()
仅停止当前正在执行的动画
队列中后续动画依然执行
$(\”…\”).stop(true)
停止当前正在执行的动画
清空动画队列
延迟执行
.delay(ms)
setTimeout
选择器:
:animated
匹配所有正在执行动画效果的元素
问题:
底层依然是定时器动画,效率低
解决:
animate.css
类数组对象操作
$(…).get(i)
获得jQuery对象中i位置的DOM元素对象
$(…).size()
获得jQuery对象中封装的DOM元素个数
$(…).each(fun)
对jQuery对象中每个DOM元素执行相同的操作
$(…).each(function(i){ //this->正在遍历的DOM元素 })
$(…).index()
查找指定DOM元素在jQuery对象中的存储位置
用法:
1. $(\”selector\”).index(jq对象|DOM对象)
在左边找到的jQuery结果集合中,找右边对象的位置
2. $(\”selector\”).index(\”selector\”)
在右边的查找结果集合中,找左边选中的元素的位置
3. $(\”selector\”).index();
查找当前元素在其父元素下的下标位置
封装自定义插件
添加jQuery对象函数
如果jQuery的简化版API不够用,可自定义API
如何:
1. 判断是否引入jQuery
if(typeof jQuery!=\”function\”) 就报错
2. 向jQuery.fn原型对象中添加自定义函数
jQuery.fn.自定义API=function(){ this->将来调用该API的jQuery对象,不用再用$()封装 }
封装自定义Widget
封装
前提:
使用html, css, js, jquery成功实现过部件的完整效果
Step1:
css拷贝到部件的css文件中
尽量少的使用元素名和id
应该用class和自定义扩展属性代替
Step2:
添加js文件
1. 判断是否提前加载了jQuery
if(typeof(window.jQuery) !==\”function\”) throw new Error(…)
2. 为jQuery.fn添加实例方法
向当前元素及其子元素上侵入class或data-*扩展属性
为data-*的元素绑定事件
使用
1. 引入部件css
2. 按部件要求编写HTML内容
3. 引入jquery
再引入部件js
4. 自定义脚本
查找父元素,调用部件函数
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。