JS事件:一道题的多种解法

本文章著作权归饥人谷_Lyndon和饥人谷所有,转载请注明出处

>>> 引言

现在JS部分已经学到了事件,我发现很多题目已经可以融合之前学过的各种JS基础知识了。今天将从一道作业题目入手,来探究一道题的多种解法(不是全部解法,毕竟JS还没有学完),顺带回顾之前所学习的内容。

题目 补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。
源代码如下:

<ul class="ct">
    <li data-img="1.jpg">鼠标放置查看图片1</li>
    <li data-img="2.jpg">鼠标放置查看图片2</li>
    <li data-img="3.jpg">鼠标放置查看图片3</li>
</ul>
<div class="img-preview"></div>
<script>
//你的代码
</script>

我这里自定义的三张图片如下:


>>> 解法1:正则表达式

我的初步想法是:因为要在div class="img-preview"中展现图片,所以最重要的实现手段就是在div标签中加上一个img标签。由于这里的图片和代码文件处于同一个文件路径之下,我可以先取出每个li中图片的名称,然后利用字符串拼接将图片包裹在img中加入到div里。
这个解法首先要取出图片名称,因此我使用正则表达式。总结起来,完整的思路是:

  • 使用querySelectorAll()方法选择所有的li元素,用querySelector()方法选择将要用于图片展示的div元素
  • 因为querySelectorAll()方法返回匹配指定的CSS选择器的所有节点,返回的是NodeList类型的对象,所以用forEach()方法遍历返回的结果,在每一个li元素上使用addEventListener()方法指定事件处理程序
  • innerHTML属性在div中加入img标签,将图片名称附着进去
var pics = documents.querySelectorAll("li"),
    preview = document.querySelector(".img-preview");
pics.forEach(function(li){
    li.addEventListener("mouseenter", function(){
        // 使用RegExp取出图片名称
        var pic = this.outerHTML.toString().match(/[0-9]\.jpg/)[0];
        // 为了方便观察,加一个控制台输出结果
        console.log(pic);
        preview.innerHTML = "<img src =" + pic + ">";
    })
});

最后的结果完全符合题目要求,只要鼠标悬停在相应的li元素上面,就会在下方出现当前li元素的data-img对应的图片。

在正则表达式匹配过程中需要注意:如果单独用this.outerHTML返回的是一个Object,没有match方法,所以需要加上toString()方法进行转换。

用这个解法完成后,我进行了反思,虽然这个解法代码简单,但是存在一个很大的缺陷:题目中图片的名称相对来说是比较类似的,但是如果一旦没有共性,正则表达式的匹配很可能就失去效力,如果希望用很多个正则表达式去匹配图片名称,代码就会显得很复杂。


>>> 解法2:创建元素并添加属性,将事件绑定到父元素上

总体思路是:

  • 使用createElement()方法来生成HTML元素节点
  • 使用getAttribute()方法来获取相应lidata-img值,再使用setAttribute()方法来给刚才创建的元素节点设置元素属性

这样做的好处是:不再受到图片名称的局限,虽然代码会稍稍复杂一些。

var ct = document.querySelector(".ct"),
    preview = document.querySelector(".img-preview"),
    // 创建元素节点
    image = document.createElement("img");
ct.addEventListener("mouseover", function(e){
    src = e.target.getAttribute("data-img");
    // 为了方便观察,加一个控制台输出结果
    console.log(src);
    // 设置元素属性
    image.setAttribute("src", src);
    preview.appendChild(image);
});

需要注意的是:这里需要使用的事件类型不是上一种方法用到的mouseenter,而是mouseover,两者的区别在于:不论鼠标指针穿过被选元素或其子元素,都会触发mouseover事件;只有在鼠标指针穿过被选元素时,才会触发mouseenter事件,mouseover对应mouseoutmouseenter对应mouseleave
如果在现在的解法中使用mouseenter,就会出现报错,因为这里添加事件处理程序的元素是ul class="ct",因此mouseenter在这种场景下会返回null,因为ul本身是没有"data-img"属性的。而li作为ul的子元素,只要鼠标指针穿过li,就能触发mouseover事件,从而顺利获取到对象中的"data-img"属性值。


>>> 解法3:综合解法1和解法2,兼用循环和属性获取

这个方法就是比较安全、不容易出错的方法。解法1中使用的是forEach()方法,这里直接使用常见的for循环

var pics = document.querySelectorAll(".ct>li"),
    preview = document.querySelector(".img-preview");
for(var i = 0; i < pics.length; i++){
    pics[i].addEventListener("mouseenter", function(){
        var img = this.getAttribute("data-img");
        preview.innerHTML = "![]( + img + )";
    });
}

>>> 总结

通过思考一道题的多种解法,回顾了之前已经学习的部分JS基础知识,关键要点如下:

  • 明确mouseentermouseover的使用场景
  • 摆脱循环可能会让代码更加简单
  • 尽量直接使用DOM中Element对象已有的增、删、改、查方法,可以有效提升效率

BTW,我相信最好的解法永远是学习更多知识后写出的下一个解法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,629评论 1 92
  • (续jQuery基础(1)) 第5章 DOM节点的复制与替换 (1)DOM拷贝clone() 克隆节点是DOM的常...
    凛0_0阅读 1,268评论 0 8
  • 总结: 鼠标事件 1.click与dbclick事件$ele.click()$ele.click(handler(...
    阿r阿r阅读 1,564评论 2 10
  • 第1章 鼠标事件 1-1 jQuery鼠标事件之click与dbclick事件 用交互操作中,最简单直接的操作就是...
    mo默22阅读 1,211评论 0 6
  • “什么事情笑的这么高兴。”夏爸爸搂着早春的小子跨进房门,顿时这个小小的空间充斥了大人的呵斥声、孩子的叫喊声、或是开...
    S菩提只吃半碗饭阅读 362评论 1 1