《DOM编程艺术》中初步实现的图片库的总结(二)

析构极昼
• 阅读 2065

前言:在《DOM编程艺术》中初步实现的图片库的总结(一)中,有很多不足之处:比如事件处理嵌套在HTML中,显得如此笨重和屌丝;没有对showPic函数进行相应的安全检查等,本篇文章对上述问题做了全面的升级。
--------------------开始---------------------

1.首先要把HTML部分进行改造

去掉嵌套在HTML中的事件处理代码,并且为了js能操作<ul>标签,需要对<ul>标签添加ID属性值


    <h1>电影天堂</h1>
    <ul id="filmlist">
        <li>
            <a href="images/01灰姑娘.jpg" title="灰姑娘">灰姑娘</a>
        </li>
        <li>
            <a href="images/02千与千寻.jpg" title="千与千寻">千与千寻</a>
        </li>
        <li>
            <a href="images/03哆啦A梦.jpg" title="哆啦A梦">哆啦A梦</a>
        </li>
        <li>
            <a href="images/04当幸福来敲门.jpg" title="当幸福来敲门">当幸福来敲门</a>
        </li>
    </ul>
    <!--占位符图片-->
    <img id="placeholder" src="images/placeholder.jpg" alt="hehehe">
    <!--一段描述-->
    <p id="description">选择一张图片</p>

2.获取<ul>标签中的节点a,遍历并且绑定事件处理


    function prepareFilm(){
        if(!document.getElementsByTagName){
            return false;
        }
        if(!document.getElementById){
            return false;
        }
        if(!document.getElementById("filmlist")){
            return false;
        }
        var list = document.getElementById("filmlist");
        var links = list.getElementsByTagName("a");
        for(var i = 0; i<links.length; i++){
            links[i].onclick = function(){
                showPic(this);
                return false;
            }
        }
    }

3.本例非必需:共享onload事件

本例中必须执行prepareFilm函数才能对onclick事件进行绑定,但是这个函数又不能在HTML文档加载之前执行,网页加载完毕时会触发一个onload事件,但是需要执行的函数有多个逐一添加又麻烦,而且后续的函数会覆盖上一个,所以就有必要封装一个addLoadEvent函数把将要执行的函数作为参数传进去,


    //共享onlond事件,封装成一个函数,@func是页面加载时需要执行的那个函数。
    //如果window.onload在页面加载时还没有绑定任何函数,就把需要执行的函数添加给它、
    //如果这个处理函数已经绑定了函数,就把新函数追加到现有指令的末尾
    function addLoadEvent(func){
        //把现有的window.onload存入变量oldonload
        var oldonload = window.onload;
        if(typeof window.onload != 'function'){
            window.onload = func;
        }else{
            window.onload = function(){
                oldonload();
                func();
            }
        }
    }

但是这个时候还有一些bug,就是没有对showPic函数进行必要的安全检查,而showPic函数要被prepareFilm函数调用,假如它获取不到图片呢?

4.对showPic函数进行安全检查

    function showPic(whichpic){
        if(!document.getElementById("placeholder")) return false;
        var source = whichpic.getAttribute("href");
        var placeholder = document.getElementById("placeholder");
        placeholder.setAttribute("src" , source);
        if(document.getElementById("description")){
            var text = whichpic.getAttribute("title");
            var description = document.getElementById("description");
            description.firstChild.nodeValue = text;  
        }
        return true;
    }

但是还是有问题,就是此时prepareFilm函数做了一个假设:showPic函数肯定会正常返回,基于这一假设,prepareFilm函数在执行showPic函数时就会提前返回一个true,从而取消了onclick事件的默认行为。所以是否要返回一个false值取消onclick默认行为,应该由showPic函数决定,图片切换成功返回true,图片切换失败,返回false。
所以此时应该把prepareFilm函数最后两句改为:return !showPic(this);

5.添加更多的检查

(1)假设每个链接都有title属性,假如不存在把text值设置为空;

(2)placeholder是否存在?假设那是一张图片(本例中它确实是图片),为了验证这个情况,可以用nodeName属性增加这一项测试。

下面是添加更多的检查之后的showPic函数代码:


    function showPic(whichpic){
        if(!document.getElementById("placeholder")) return false;
        var source = whichpic.getAttribute("href");
        var placeholder = document.getElementById("placeholder");
        if(placeholder.nodeName != "IMG") return false;
        placeholder.setAttribute("src" , source);
        if(document.getElementById("description")){
            var text = whichpic.getAttribute("title")?whichpic.getAttribute("title"):"";
            var description = document.getElementById("description");
            if(description.firstChild.nodeType == 3){
                description.firstChild.nodeValue = text; 
            } 
        }
        return true;
    }

6.调用addLoadEvent函数

    //在页面加载完成后调用prepareFilm函数
    addLoadEvent(prepareFilm);

7.完整代码

老规矩,上完整源码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>example</title>
    <style>
        h1 {
            color: #333;
        }
        
        a {
            color: gray;
            font-weight: bold;
            text-decoration: none;
        }
        
        ul {
            padding: 0;
        }
        
        li {
            float: left;
            padding: 1em;
            list-style-type: none;
        }
        
        img {
            display: block;
            clear: both;
        }
    </style>
</head>

<body>
    <h1>电影天堂</h1>
    <ul id="filmlist">
        <li>
            <a href="images/01灰姑娘.jpg" title="灰姑娘">灰姑娘</a>
        </li>
        <li>
            <a href="images/02千与千寻.jpg" title="千与千寻">千与千寻</a>
        </li>
        <li>
            <a href="images/03哆啦A梦.jpg" title="哆啦A梦">哆啦A梦</a>
        </li>
        <li>
            <a href="images/04当幸福来敲门.jpg" title="当幸福来敲门">当幸福来敲门</a>
        </li>
    </ul>
    <!--占位符图片-->
    <img id="placeholder" src="images/placeholder.jpg" alt="hehehe">
    <!--一段描述-->
    <p id="description">选择一张图片</p>

    <!--以下是js代码-->
    <script>
        function showPic(whichpic){
            if(!document.getElementById("placeholder")) return false;
            var source = whichpic.getAttribute("href");
            var placeholder = document.getElementById("placeholder");
            if(placeholder.nodeName != "IMG") return false;
            placeholder.setAttribute("src" , source);
            if(document.getElementById("description")){
                var text = whichpic.getAttribute("title")?whichpic.getAttribute("title"):"";
                var description = document.getElementById("description");
                if(description.firstChild.nodeType == 3){
                    description.firstChild.nodeValue = text; 
                } 
            }
            return true;
        }

        function prepareFilm(){
            if(!document.getElementsByTagName){
                return false;
            }
            if(!document.getElementById){
                return false;
            }
            if(!document.getElementById("filmlist")){
                return false;
            }
            var list = document.getElementById("filmlist");
            var links = list.getElementsByTagName("a");
            for(var i = 0; i<links.length; i++){
                links[i].onclick = function(){
                    return showPic(this)?false:true;
                }
            }
        }

        //共享onlond事件,封装成一个函数,@func是页面加载时需要执行的那个函数。
        //如果window.onload在页面加载时还没有绑定任何函数,就把需要执行的函数添加给它、
        //如果这个处理函数已经绑定了函数,就把新函数追加到现有指令的末尾
        function addLoadEvent(func){
            //把现有的window.onload存入变量oldonload
            var oldonload = window.onload;
            if(typeof window.onload != 'function'){
                window.onload = func;
            }else{
                window.onload = function(){
                    oldonload();
                    func();
                }
            }
        }

        //在页面加载完成后调用prepareFilm函数
        addLoadEvent(prepareFilm);
    </script>
</body>

</html>
点赞
收藏
评论区
推荐文章
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
马丁路德 马丁路德
5年前
对 JavaScript 中事件循环的理解​
一、是什么JavaScript在设计之初便是单线程,即指程序运行时,只有一个线程存在,同一时间只能做一件事为什么要这么设计,跟JavaScript的应用场景有关JavaScript初期作为一门浏览器脚本语言,通常用于操作DOM,如果是多线程,一个线程进行了删除DOM,另一个添加DOM,此时浏览器该如何处理?为了解决单
Karen110 Karen110
4年前
一篇文章带你了解JavaScript htmldom 元素
这篇文章将教会大家如何查找和访问网页中的HTML元素。一、找到HTML元素通常,使用JavaScript,想操作HTML元素。要做到这一点,必须先找到元素。有几种方法可以做到这一点。找到DOM中的HTML元素的最简单的方法,是利用元素的id。使用id"intro"找到元素:varmyElementdocument.getElementById("in
徐小夕 徐小夕
5年前
《javascript高级程序设计》核心知识总结
此文是对js高级程序设计一书难点的总结,也是笔者在看了3遍之后的一些梳理和感想,希望能借此巩固js的基础和对一些核心概念有更深入的了解。摘要js基本的数据类型和关键点变量,作用域和内存问题垃圾回收机制面向对象的程序设计实现类与继承的经典方式BOM和DOM对象DOM扩展与高级API介绍高级编程技巧跨文档消息传递和aja
待兔 待兔
5年前
Dart | 浅析dart中库的导入与拆分
前言最近十分热门的跨平台框架使用了一门比较生僻的编程语言dart。dart语言本身深受早期一些编程语言的影响。特别是Smalltalk,Java和JavaScript。我是从Java语言向dart过度的,一开始感觉很不错,快速就对这门语言有了一个初步的认识,并能够写小段代码了。但在flutter的不断学习过程中,我遇到了不少因为dart的一些语
可莉 可莉
4年前
06. react 初次见面
    React元素的事件处理和DOM元素的很相似。但是有一点语法上的不同:React事件绑定属性的命名采用驼峰式写法,而不是小写。如果采用JSX的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法)    例如,传统的HTML:<buttononclick"activateLas
Stella981 Stella981
4年前
React篇(005)
答案:1、React速度很快:它并不直接对DOM进行操作,引入了一个叫做虚拟DOM的概念,安插在javascript逻辑和实际的DOM之间,性能好。2、跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。3、一切都是co
Wesley13 Wesley13
4年前
Java日期时间API系列21
  通过工作之余,对Java8中java.time包源码的不断学习,使用和总结,开发了xktime,初步完成,欢迎试用和提出建议!xktimexktimeisadatetimeconvertercalculatorandformattertoolset,basedonjava8dateandtime
Stella981 Stella981
4年前
JavaScript面向对象编程的15种设计模式
在程序设计中有很多实用的设计模式,而其中大部分语言的实现都是基于“类”。在JavaScript中并没有类这种概念,面向对象编程不是基于类,而是基于原型去面向对象编程,JS中的函数属于一等对象,而基于JS中闭包与弱类型等特性,在实现一些设计模式的方式上与众不同。ps:本文之讲述面向对象编程的设计模式策略,JavaScript原型的基础请参考阮一峰面向
Wesley13 Wesley13
4年前
Go 语言基础入门教程 —— 函数篇:匿名函数和闭包
匿名函数熟悉Laravel框架(一个PHPWeb框架)的同学对匿名函数应该很熟悉,Laravel框架中有着大量匿名函数的应用场景,比如路由定义、绑定实现到接口等://路由定义再比如Swoole中通过回调函数处理网络事件实现异步事件驱动也是匿名函数的典型应用场景://收到请求时触发可以看到,匿名函数
Stella981 Stella981
4年前
JavaScript 异步编程
❝掌握JavaScript主流的异步任务处理(本篇文章内容输出来源:《拉钩教育大前端训练营》参阅《你不知道的JavaScript中卷》异步章节)❞JavaScrip采用单线程模式工作的原因,需要进行DOM操作,如果多个线程同时修改DOM浏览器无法知道以哪个线程为主。JavaScirpt分为:同步模式、异步模式同步