DOM + 事件

  • A+
所属分类:JavaScript

DOM

添加class、移除class、是否同级元素、获取元素位置

先来一些简单的,在你的util.js中完成以下任务:

思路:

  1. 其实这里可以先定义一个hasClass函数。用来判断该节点是否含有某个className。
    • addClass添加样式。调用hasClass函数,判断element是否含有待添加的新className,若没有则添加,否则什么都不做。
    • removeClass删除样式。调用hasClass函数,判断element是否含有该指定样式,若含有的话删除该className。没有的话什么都不做。
  2. 判断siblingNode和element是否为同一个父元素下的同一级的元素。这里直接判断parentNode就可以了吧
  3. 获取element相对于浏览器窗口的位置,返回一个对象{x, y}。
    • 这个题应该是这几个中比较复杂的一个了。因为不能直接使用offsetLeft/TopoffsetLeft/Top所获取的是其相对父元素的相对位置。当多层定位嵌套时想要获取到当前元素相对网页的位置就会不对。
    • 并且由于在表格iframe中,offsetParent对象未必等于父容器,所以也不能直接利用该元素的parent来获取位置,因为其对于表格iframe中的元素不适用。
    • 通过查询知道有一个Element.getBoundingClientRect()方法。它返回一个对象,其中包含了left、right、top、bottom四个属性,分别对应了该元素的左上角和右下角相对于浏览器窗口(viewport)左上角的距离。
    • 但是用该方法获取到的是元素的相对位置,在出现滚动时,距离会发生改变,要获得绝对位置时,还需要加上滚动的距离。因为Firefox或Chrome的不兼容问题需要进行兼容性处理,参考document.body.scrollTop or document.documentElement.scrollTop
    • 最终根据两个值,得到绝对位置。

实现:

参考资料:(还没看完)

挑战mini $

接下来挑战一个mini $,它和之前的$是不兼容的,它应该是document.querySelector的功能子集,在不直接使用document.querySelector的情况下,在你的util.js中完成以下任务:

实现思路:
嗯,这个题思考了很久,网上找了很多资料但还是不怎么会,还达不到想要的效果,有点钻牛角尖了。尽量来写一下吧。(我果然是个弱鸡)。感谢秒味课堂的免费课程。

  1. 题目要求获取到所有的节点中的第一个,所以不需要用数组来储存获取到的节点。
  2. 额。。想了半天,还是使用函数包装来实现后代选择器比较好,所以VQuery函数返回是获取到的完整节点对象数组,$函数用来达到题目要求。
  3. 所以在VQuery函数中就不需要考虑空格了,直接使用switch分支,来判定不同的情况。#、.、[、 [=]。
  4. 在$函数中,判断字符串中是否含有空格,有空格的话需要分割成数组,数组的前一项是为父选择符,后一项为子选择符。分不同的情况来调用VQuery函数,并返回对象。

事件

事件绑定、事件移除

我们来继续用封装自己的小jQuery库来实现我们对于JavaScript事件的学习,还是在你的util.js,实现以下函数

这里慕课网的视频讲的特别清楚,就不赘述了。

click事件、Enter事件

利用上面写好的事件绑定函数就很简单了。

  • click事件,这个简单,直接函数封装一层就行。
  • Enter事件,这里主要考察的键盘的事件的触发。
    1. keydown事件:在键盘按下时触发.
    2. keyup事件:在按键释放时触发,也就是你按下键盘起来后的事件
    3. keypress事件:在敲击按键时触发,我们可以理解为按下并抬起同一个按键
    4. keyCode属性:在键盘事件触发时,按下的键的值。值=13时,为Enter键。(需进行兼容处理)

接下来我们把上面几个函数和$做一下结合,把他们变成$对象的一些方法

  • addEvent(element, event, listener) -> $.on(element, event, listener);
  • removeEvent(element, event, listener) -> $.un(element, event, listener);
  • addClickEvent(element, listener) -> $.click(element, listener);
  • addEnterEvent(element, listener) -> $.enter(element, listener);

事件代理

接下来考虑这样一个场景,我们需要对一个列表里所有的<li>增加点击事件的监听

我们通过自己写的函数,取到id为list这个ul里面的所有li,然后通过遍历给他们绑定事件。这样我们就不需要一个一个去绑定了。但是看看以下代码:

我们增加了一个按钮,当点击按钮时,改变list里面的项目,这个时候你再点击一下li,绑定事件不再生效了。那是不是我们每次改变了DOM结构或者内容后,都需要重新绑定事件呢?当然不会这么笨,接下来学习一下事件代理,然后实现下面新的方法:

实现思路:

写到这里,刚好前几天CSS魔法写的《前端进阶之路:点击事件绑定》有提到“事件代理/委托”,不过是直接使用jQuery来实现的。所以地址有兴趣的自己搜索吧-_-。

  • “事件代理” 的本质是利用了事件冒泡的特性。当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;
  • 这个事件从原始元素开始一直冒泡到DOM树的最上层。任何一个事件的目标元素都是最开始的那个元素,在我们的这个例子中也就是按钮,并且它在我们的元素对象中以属性的形式出现。使用事件代理,我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。
  • 这里就不细说事件冒泡与事件捕获了(阻止默认行为也会用到,有兴趣去网上找找看),但是要理解事件代理就必须先知道它们。下面这张图可以先看看。(图片来自网络,侵删)

DOM + 事件

实现如下:

封装改变

估计有同学已经开始吐槽了,函数里面一堆$看着晕啊,那么接下来把我们的事件函数做如下:(这里应该是把前面的$.on、$.click、$.un、$.delegate都改写一下。比较简单,就拿一个出来作例子吧。)

 

weinxin
我的微信公众号
我的微信公众号扫一扫

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: