本文共 14528 字,大约阅读时间需要 48 分钟。
最近忙着找工作,在这期间的复习过程中,为了方便查阅,总结了很多我常用到的基础内容和面试题。在这里分享给大家,大家也可以参考复习。
首先需要说明的是,因为jQuery本身就是对JS的简化,那么既然能简化,所以我把大部分的代码重心都放在了jQuery上,而不是JS(尤其是DOM操作)。而且这部分的学习,会更好的帮我们去理清思路和逻辑,方便之后在Vue、React里面的运用(我大量时间都使用Vue)。因此这部分的学习也还是比较重要的。
因此我在之前JS的分享中,基础知识并不是很全面,如果想看JS的DOM操作:,更多简化使用的方法jQuery将会在本文中分享。
$(function() {})
和JS中用的window.onload=function(){}
个人遇到的问题:
之前我有点分不清什么时候使用$('#username').val()
和 $('#btn').html()
, 从目前来看,val()就是JS中的value(),也就是会用于,有value属性的标签,那也就是说,val()一定主要用于在input中获取内容。因为input text的文本框中的内容,其实就是存放在value属性上的,而html()就是JS中的innerHtml(),它就可以获取其他普通标签中的内容。如下例。 同时也可以用这两个函数去修改原标签中的内容,只需要在()中添加想要添加的内容,就可以替换掉原内容了。 $()
函数是 jQuery()
函数的别称。$()
函数用于将任何对象包裹成 jQuery 对象,然后就被允许调用定义在 jQuery 对象上的多个不同方法。
ready() 函数用于在文档进入ready状态时执行代码。当DOM 完全加载(例如HTML被完全解析DOM树构建完成时),jQuery允许你执行代码。使用$(document).ready()的最大好处是它适用于所有浏览器,帮我们解决了跨浏览器的难题。
JavaScript window.onload 事件和 jQuery ready 函数之间的主要区别是,前者除了要等待 DOM 被创建还要等到包括大型图片、音频、视频在内的所有外部资源都完全加载。如果加载图片和媒体内容花费了大量时间,用户就会感受到定义在 window.onload 事件上的代码在执行时有明显的延迟。
另一方面,jQuery ready() 函数只需对 DOM 树的等待,而无需对图像或外部资源加载的等待,从而执行起来更快。使用 jQuery $(document).ready() 的另一个优势是你可以在网页里多次使用它,浏览器会按它们在 HTML 页面里出现的顺序执行它们,相反对于 onload 技术而言,只能在单一函数里使用。鉴于这个好处,用 jQuery ready() 函数比用 JavaScript window.onload 事件要更好些。
jQuery对象是一个包含所有匹配的任意多个dom元素的伪数组对象。
方法的作用是:返回对象中元素的个数。
但是不推荐使用size()方法,因为jQuery提供了.length属性,它也做同样的事情。 但是.length属性是首选的,因为它没有函数调用的开销。eq()将元素作为jQuery对象返回。
该方法从该集合中的一个元素构造一个新的jQuery对象并返回它。 这意味着您可以在上面使用jQuery函数。get()返回一个DOM元素。
方法检索与jQuery对象匹配的DOM元素。 但是因为它是一个DOM元素,而不是一个jquery封装的对象。 因此无法使用jQuery函数。选择器和CSS相同。常用选择器:
以下修改css的方式,主要用于实时变换的情况,比如点击按钮变换css样式,也就是说如果有一些不需要变动的默认样式,显然写在这里不方便,当然还要写在style里。//选择所有的div和span元素$('div,span').css('background', 'black')//选择所有class属性为box的li元素$('li.box').css('background', '#666')//获取所有class属性为box的li元素的background样式$('li.box').css('background')
//1. 选中ul下所有的的span$('ul span').css('background', 'yellow')//2. 选中ul下所有的子元素span$('ul>span').css('background', 'yellow')//3. 选中class为box的下一个li$('.box+li').css('background', 'yellow')//4. 选中ul下的class为box的元素后面的所有兄弟元素$('ul .box~*').css('background', 'yellow')//1. 选择第一个div$('div:first').css('background', 'red')//2. 选择最后一个class为box的元素$('.box:last').css('background', 'red')//3. 选择所有class属性不为box的div$('div:not(.box)').css('background', 'red')//4. 选择内容为BBBBB的li$('li:contains("BBBBB")').css('background', 'red')//5. 选择第二个和第三个li元素$('li:gt(0):lt(2)').css('background', 'red') $('li:lt(3):gt(0)').css('background', 'red')//6. 选择有title属性的li元素$('li[title]').css('background', 'red')//7. 选择所有属性title为hello的li元素$('li[title="hello"]').css('background', 'red')
个人遇到的问题:jQuery的选择器,还是有说法的,我自己很容易记混。平常常用的选择器还是和CSS的用法一样,不需要额外记忆。但是除此以外,如果是标签自身就有的属性,那么去调用都是:的。
比如表单选择器$(':checkbox:checked')
就获取到了多选表单项的已被选中的选项。
$('li[title="hello"]')
。 通过选择器,我们获得了满足条件的标签,而我们能对这个标签做的操作就是:
修改它的CSS,输出标签的内容html() 或者 val(),又或者输出length。 如果要修改内容,就在html和val内添加即可。在以上只是获取标签并修改它的样式和内容,接下来就涉及到获取标签属性并对其修改等操作。
//1. 读取第一个div的title属性$('div:first').attr('title')//2. 给所有的div设置name属性(value为hello)$('div').attr('name', 'hello')//3. 给所有的div设置多个属性$('div').attr({ name: 'hello',title: 'hello2'})//4. 移除所有div的title属性$('div').removeAttr('title')//5. 给所有的div设置class='guiguClass'$('div').attr('class', 'guiguClass')//6. 给所有的div添加class='abc'$('div').addClass('abc')//7. 移除所有div的guiguClass $('div').removeClass('guiguClass')
之前我提到我自己分不清:$('#username').val()
和 $('#btn').html()
$(':text').val()
得到输入框的val $('li:last').html()
得到某标签体的文本 前面使用到的attr,专门操作非布尔值的属性,如上面的用法。
而接下来的prop,专门操作布尔值的属性, 也就是说prop十分适用于表单项,如下例。//1. 点击按钮实现多选框全选var $checkboxs = $(':checkbox')$('button:first').click(function() { $checkboxs.prop('checked', true)})//2. 点击按钮实现多选框全不选$('button:last').click(function() { $checkboxs.prop('checked', false)})
对于html元素本身就带有的固定属性(本身就带有的属性),在处理时,使用prop方法,且它可以操作布尔类型的属性。
对于html元素我们自己定义的dom属性,在处理时,使用attr方法,且它不可以操作布尔类型的属性。
以上所有容易混淆的方法的总结:
//1. $.each(): 遍历数组或对象中的数据var obj = { name : 'Tom', setName : function(name) { this.name = name }}$.each(obj, function(key, value) { console.log(key, value)})//2. $.trim(): 去除字符串两边的空格var str = ' hello 'console.log($.trim(str))//3. $.type(obj): 得到数据的类型console.log($.type($)) // 'function'//4. $.isArray(obj): 判断是否是数组console.log($.isArray($('body')), $.isArray([])) // false true//5. $.isFunction(obj): 判断是否是函数console.log($.isFunction($)) // true//6. $.parseJSON(json) : 解析json字符串转换为js对象/数组var json = '{"name":"Tom", "age":12}' // json对象: {}// json对象===>JS对象console.log($.parseJSON(json))json = '[{"name":"Tom", "age":12}, {"name":"JACK", "age":13}]' // json数组: []// json数组===>JS数组console.log($.parseJSON(json))
$('.div1').offset() // 相对页面左上角的坐标$('.div2').position() // 相对于父元素左上角的坐标// 修改盒子在页面中的位置$('.div2').offset({ left : 50, top : 100})$('div').scrollTop() // 读取div滚动条的Y坐标// 兼容IE/Chrome的读取页面滚动条的Y坐标$(document.documentElement).scrollTop() + $(document.body).scrollTop()// 设置div / 页面滚动条的Y坐标$('div').scrollTop(200)$('html,body').scrollTop(300)
$('div').width(), $('div').height()$('div').innerWidth(), $('div').innerHeight()$('div').outerWidth(), $('div').outerHeight()$('div').outerWidth(true), $('div').outerHeight(true)
在上文中,如果要想获取标签,修改样式,是这么做的:
$('div:first').css('background', 'red')
也就是,无论是想获取什么样的标签,这个first,last,not等,都是用在选择器当中的。但是在这里还有一种用法,就是先获取到这个标签到jQuery对象数组中,然后再对这个对象数组进行操作,来获取想要的那个具体的标签,修改样式。 举个简单的例子,上面的代码就可以改成这样:
var $lis = $('ul>li')$lis.first().css('background', 'red')
或者
$lis[0].style.background = 'red'
这就是所谓筛选,对对象数组的筛选。
例子:
var $lis = $('ul>li')//1. ul下li标签第一个$lis.first().css('background', 'red')$lis[0].style.background = 'red'//2. ul下li标签的最后一个$lis.last().css('background', 'red')//3. ul下li标签的第二个$lis.eq(1).css('background', 'red')//4. ul下li标签中title属性为hello的$lis.filter('[title=hello]').css('background', 'red')//5. ul下li标签中title属性不为hello的$lis.not('[title=hello]').css('background', 'red')// 或者:$lis.filter('[title!=hello]').filter('[title]').css('background', 'red')//6. ul下li标签中有span子标签的$lis.has('span').css('background', 'red')var $ul = $('ul')//1. ul标签的第2个span子标签$ul.children('span:eq(1)').css('background', 'red')//2. ul标签的第2个span后代标签$ul.find('span:eq(1)').css('background', 'red')//3. ul标签的父标签$ul.parent().css('background', 'red')//4. id为cc的li标签的前面的所有li标签var $li = $('#cc')$li.prevAll('li').css('background', 'red')//5. id为cc的li标签的所有兄弟li标签$li.siblings('li').css('background', 'red')
//1. 向id为ul1的ul下添加一个span(最后)var $ul1 = $('#ul1')$ul1.append('append()添加的span')$('appendTo()添加的span').appendTo($ul1)//2. 向id为ul1的ul下添加一个span(最前)$ul1.prepend('prepend()添加的span')$('prependTo()添加的span').prependTo($ul1)//3. 在id为ul1的ul下的li(title为hello)的前面添加span$ul1.children('li[title=hello]').before('before()添加的span')//4. 在id为ul1的ul下的li(title为hello)的后面添加span$ul1.children('li[title=hello]').after('after()添加的span')//5. 将在id为ul2的ul下的li(title为hello)全部替换为p$('#ul2>li[title=hello]').replaceWith('replaceAll()替换的p
')//6. 移除id为ul2的ul下的所有li$('#ul2').empty()$('#ul2>li').remove()
三者都被用来移除一个DOM元素, 但三者之间的主要不同在于
.empty():移除被选元素的所有子节点和内容。但该方法不会移除元素本身,或它的属性。 .remove():移除元素及它的数据和事件。 .detach():移除被选元素,但是它会保留数据和事件,允许它们在以后被重新插入。//1. 给.out绑定点击监听(用两种方法绑定)/*$('.out').click(function () { console.log('click out') })*/$('.out').on('click', function() { console.log('on click out')})//2. 给.inner绑定鼠标移入和移出的事件监听(用3种方法绑定)/* $('.inner') .mouseenter(function () { // 进入 console.log('进入') }) .mouseleave(function () { // 离开 console.log('离开') }) *//* $('.inner') .on('mouseenter', function () { console.log('进入2') }) .on('mouseleave', function () { console.log('离开2') }) */$('.inner').hover(function() { console.log('进入3')}, function() { console.log('离开3')})//3. 点击btn1解除.inner上的所有事件监听$('#btn1').click(function() { $('.inner').off()})//4. 点击btn2解除.inner上的mouseenter事件$('#btn2').click(function() { $('.inner').off('mouseenter')})
在这里涉及到了两个区分,
一个是在上面提到的on(‘eventName’, fun)与eventName(fun), 一个是在上面用到的mouseover、mouseenter和hover。 对于第一个区分,其实已经提到了,on的方式无论面对什么样的事件,都可以实行,即通用。但是和不加on相比,会稍微麻烦些。但是不加on虽然编码简单,但是有的事件是不能这样使用的。虽然我没有查阅哪些事件不能使用这个方式,但是常用的事件肯定也能这么用。对于第二个区分,
mouseover + mouseout:在移入子元素时也会触发。 即,如果父元素中存在着子元素,此时若给父元素添加该事件,那么鼠标移入子元素也会触发。而相对的,以下方式就是鼠标移入子元素不会触发。即:每一个事件只会处理仅有该元素的部分。 mouseenter + mouseleave:只在移入当前元素时才触发。hover()没什么特别的,它使用的就是mouseenter()和mouseleave(),也就是在最开始html阶段使用的a:hover。
//5. 点击btn3得到事件坐标$('#btn3').click(function(event) { // event事件对象 console.log(event.offsetX, event.offsetY) // 原点为事件元素的左上角 console.log(event.clientX, event.clientY) // 原点为窗口的左上角 console.log(event.pageX, event.pageY) // 原点为页面的左上角})//6. 点击.inner区域, 外部点击监听不响应$('.inner').click(function(event) { console.log('click inner') //停止事件冒泡 event.stopPropagation()})
停止事件冒泡就是:当你点击子元素,父元素并不会作出任何操作,即点击子元素不会影响父元素。当想要实现父元素的效果,就去点击子元素以外的部分。否则,如果不停止事件冒泡,那么点击子元素 = 点击父元素。
//7. 点击链接, 如果当前时间是偶数不跳转$('#test4').click(function(event) { if (Date.now() % 2 === 0) { event.preventDefault() }})
阻止事件默认行为,就是阻止这个事件被触发。
引例:比如说以下用法,当你点击按钮向ul中添加一个新增的li时,新增的li不会获得之前设置的click事件,这显然是个很棘手的问题。
$('ul>li').click(function() { this.style.background = 'red'})$('#btn').click(function() { $('ul').append('
但是有了事件委托(监听)就可以实现了。
比如上面的例子中,我们要在ul中新增li,同时要能够“发现”ul中新增了li,并且可以为这个li添加事件,那么这个监听肯定要加在父元素中。因为增加或者其他的变化都是在这个父元素上,只有把监听加在父元素上,才能“发现”这一系列的变化。也就是:多个子元素的事件监听委托给父元素处理。那么它的原理到底是怎样的呢?我们已经知道子元素的事件监听委托已经交给父元素处理,也是因为只有父元素才可以监视到变化。那么当我们想操作任何一个子元素时,事件理所应当就会冒泡到父元素上,因为事件已经委托给父元素了。这时,父元素其实也没有直接处理事件,而是根据event.target得到发生事件的子元素,再把事件回调函数给这个子元素调用。也就是父元素真的是实现了事件的委托。
// 设置事件委托$('ul').delegate('li', 'click', function() { this.style.background = 'red'})$('#btn1').click(function() { $('ul').append('
var $div1 = $('.div1') $('#btn1').click(function() { $div1.fadeOut(1000, function() { alert('动画完成了!!!') }) }) $('#btn2').click(function() { $div1.fadeIn("slow",function(){ alert("动画完成了") }) }) $('#btn3').click(function() { $div1.fadeToggle("fast",function(){ alert("动画完成了"); }) })
var $div1 = $('.div1')$div1.mouseenter(function(){ $div1.slideUp(3000)})$div1.mouseleave(function(){ $div1.slideDown(3000)})// 1. 点击btn1, 向上滑动$('#btn1').click(function() { $div1.slideUp(3000)})// 2. 点击btn2, 向下滑动$('#btn2').click(function() { $div1.slideDown('fast',function(){ alert("完成!"); })})// 3. 点击btn3, 向上/向下切换$('#btn3').click(function() { $div1.slideToggle('slow',function(){ alert("完成!"); })})
var $div1 = $('.div1')//1. 点击btn1, 立即显示$('#btn1').click(function() { $div1.show()})//2. 点击btn2, 慢慢显示$('#btn2').click(function() { $div1.show(1000)})//3. 点击btn3, 慢慢隐藏$('#btn3').click(function() { $div1.hide(1000)})//4. 点击btn4, 切换显示/隐藏$('#btn4').click(function() { $div1.toggle(1000)})
在这里就一定要说的:以上三个,淡入淡出效果,滑动效果,显示与隐藏效果。我猜它们本质上就类似于在css里用到的transition和animation,由这些效果所封装的。那么接下来就提到“自定义动画”,也就是说我们可以在jQuery中自己决定动画的效果。也许你会疑问,那我为什么不去css中设置过渡和动画,非要在jQuery中想办法设置呢?这个问题的答案,通过前面对一些问题的看法,看到这部分,其实已经可以猜到了,当然我说的不一定对,但是我可以肯定的是:首先在jQuery中如果调用上述三个效果,通过代码量来判断,它一定会比css的动画和过渡简单的多,这是显而易见的。除此以外,如果你在css中设置,那就固定效果了,我指的是,如果在页面运行过程中,用户新添加一个元素,那么肯定无法在最开始就设置好这些效果。而在jQuery中(及之后的Vue),是可以实现事件监听的。先不论你想要的效果能否通过监听实现,但至少可以通过事件监听实现动态效果。
var $div1 = $('.div1')/* 1. 逐渐扩大:宽先扩为200px, 高后扩为200px */$('#btn1').click(function() { $div1.animate({ width : 200 }, 1000).animate({ height : 200 }, 1000)})/* 2. 移动到指定位置:移动到(100, 20)处 */$('#btn2').click(function() { $div1.animate({ // 向左上移动 left : 100, top : 20 }, 1000)})/* 3.移动指定的距离:移动距离为(-100, -20) */$('#btn3').click(function() { $div1.animate({ left : '-=100', top : '-=20' }, 3000)})$('#btn4').click(function() { $div1.stop()})
var $contents = $('#container>div')var currIndex = 0 //当前显示的内容div的下标$('#tab>li').click(function () { // 隐式遍历 // 隐藏当前已经显示的内容div $contents[currIndex].style.display = 'none' // 显示对应的内容div // 得到当前点击的li在兄弟中下标 var index = $(this).index() // 找到对应的内容div, 并显示 $contents[index].style.display = 'block' // 更新下标 currIndex = index})
html的方法就是瞬间移动到顶部,在jQuery中可以缓慢移动。
test 测试1测试2测试3回到顶部2
作者想说的话:这种类似的效果已经在各种UI组件库中被封装起来,可以去直接使用了,所以虽然现在这些原理不需要掌握,但是去了解还是蛮有意思的。
#navigation ul li ul { background-color: #88C366; position: absolute; width: 80px; overflow: hidden; <-这个是关键 display: none; <-这个是关键}$('#navigation>ul>li:has(ul)').hover(function () { //动画展开 $(this).children('ul').stop(true).slideDown()}, function () { // 动画收缩 $(this).children('ul').stop(true).slideUp()})
全选练习
test 111111 111111 111111 111111 111111 111111 111111 111111我已仔细阅读协议
在这里需要注意:对于input标签,如果要修改其中的属性,一定要用prop。
像我之前就混淆了,直接找$(’:checkbox’).disabled,就发现找不到。那如果是其他标签,就用attr。test
有一些其他的客户端库也使用$()
作为它们的全局函数并定义变量。这种情况会产生冲突。为了克服这种情况,jQuery引入了jQuery.noConflict()。
var $j = jQuery.noConflict();$j(document).ready(function(){ $j("div").hide();});
jQuery库有2个不同的版本:生产和部署。
生产版本在开发时非常有用,因为jQuery是开源的,如果你想改变一些东西,那么你可以在生产版本中进行这些更改。但部署版本是缩小版本或压缩版本,因此无法对其进行更改。因为它是压缩的,因此可以快速加载并节省带宽(适用于生产环境)。有两种方法可以检查元素是否为空。
我们可以使用“:empty”选择器来检查。$(document).ready(function(){ if ($('#element').is(':empty')){ //Element is empty }});
第二种方法是使用“$.trim()”方法。
$(document).ready(function(){ if($.trim($('#element').html())==' ') { //Element is empty }});
使用jQuery length属性,我们可以确保元素是否存在。
$(document).ready(function(){ if ($('#element').length > 0){ //Element exists });});
转载地址:http://elyki.baihongyu.com/