JavaScript DOM编程艺术 第六章 图片库改进 笔记

发布于:2024-04-03 ⋅ 阅读:(141) ⋅ 点赞:(0)

图片库改进版

6.1 本章内容

  • 把事件处理移除文档
  • 向后兼容
  • 确保可访问

6.2 最终代码展示

效果
在这里插入图片描述

点击切换
在这里插入图片描述

javascript代码

function showPic(whichPic) {
    // 检测图片元素是否存在
    if (document.getElementById("placeholder") == null) return false;
    // 展示图片
    var source = whichPic.getAttribute("href");
    var placeholder = document.getElementById("placeholder");
    // 查看是否为IMG元素
    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");
        description.firstChild.nodeValue = text;
    }
    return true;
}

function prepareGallery() {
    // 检测浏览器是否理解getElemntById()方法
    if (!document.getElementsByTagName) return false;
    if (!document.getElementById) return false;
    if (!document.getElementById("imageGallery")) return false;

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

function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != "function") {

        window.onload = func;
    } else {
        window.onload = function () {
            oldonload();
            func();
        }
    }
}

addLoadEvent(prepareGallery);

HTML代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Image Gallery</title>
    <link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen">
</head>

<body>
    <h1>图片库</h1>
    <ui id="imageGallery">
        <li><a href="image/toWest/monkey.webp" title="悟空"><img src="image/toWest/monkey.webp" alt="悟空"></a></li>
        <li><a href="image/toWest/tulv.webp" title="唐僧"><img src="image/toWest/tulv.webp" alt="唐僧"></a></li>
        <li><a href="image/toWest/pig.webp" title="八戒"><img src="image/toWest/pig.webp" alt="八戒"></a></li>
        <li><a href="image/toWest/wujing.webp" title="悟净"><img src="image/toWest/wujing.webp" alt="悟净"></a></li>
        <li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘"><img src="image/whiteSnake/whiteSnake.webp"
                    alt="白娘娘"></a></li>
        <li><a href="image/whiteSnake/doctor.webp" title="许仙">
                <img src="image/whiteSnake/doctor.webp" alt="许仙"></a>
        </li>
        <li><a href="image/whiteSnake/greenSnake.webp" title="小青"><img src="image/whiteSnake/greenSnake.webp" alt="小青">
            </a></li>
    </ui>
    <img id="placeholder" src="image/gallery.webp" alt="placeholder">
    <p id="description">选择一个图片</p>
    <script type="text/javascript" src="scripts/showPic.js"></script>
</body>

</html>

CSS代码

#imageGallery {
    list-style: none;
    margin: 0;
}

#imageGallery li {
    display: inline-flex;
}

#imageGallery li a img {
    max-width: 90px;
    max-height: 80px;
}

#placeholder img {
    display: inline-block;
    margin: 0 auto;
    width: 300px;
    height: 400px;
}

body {
    font-family: Arial, Helvetica, sans-serif;
    color: #333;
    background-color: #ccc;
    margin: 1em 10%;
}


h1 {
    color: #333;
    background-color: transparent;
}

a {
    color: #c60;
    background-color: transparent;
    font-weight: bold;
    text-decoration: none;
}

ul {
    padding: 0;
}

li {
    float: left;
    padding: 10px 10px 10px 0px;
    list-style-type: none;
}

img {
    display: flex;
    clear: both;
    max-width: 300px;
    max-height: 400px;
}

6.3 回顾

原始 图片库javascript代码

function showPic(whichPic) {
    // 展示图片
    document.getElementById("placeholder").setAttribute("src", whichPic.getAttribute("href"));
    // 显示描述
    var description = document.getElementById("description");
    var text = whichPic.getAttribute("title");
    description.firstChild.nodeValue = text;
}

HTML代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Image Gallery</title>
    <link rel="stylesheet" type="text/css" href="styles/layout.css">
</head>

<body>
    <h1>图片库</h1>
    <ui>
        <li><a href="image/toWest/monkey.webp" title="悟空" onclick="showPic(this);return false;">悟空</a></li>
        <li><a href="image/toWest/tulv.webp" title="唐僧" onclick="showPic(this);return false;">唐僧</a></li>
        <li><a href="image/toWest/pig.webp" title="八戒" onclick="showPic(this);return false;">八戒</a></li>
        <li><a href="image/toWest/wujing.webp" title="悟净" onclick="showPic(this);return false;">悟净</a></li>
        <li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘" onclick="showPic(this);return false;">白娘娘</a></li>
        <li><a href="image/whiteSnake/doctor.webp" title="许仙" onclick="showPic(this);return false;">许仙</a></li>
        <li><a href="image/whiteSnake/greenSnake.webp" title="小青" onclick="showPic(this);return false;">小青</a></li>
    </ui>
    <img id="placeholder" src="image/gallery.png" alt="placeholder">
    <p id="description">选择一个图片</p>
    <script type="text/javascript" src="scripts/showPic.js"></script>
</body>

</html>

6.4 它支持平稳退化吗

问题一:JS被禁用,上述代码是否能正常运行?

答案:JS被禁用,支持,点击时,通过href直接跳转到图片界面,通过浏览器回退可以进入每个界面

但是如果使用js伪协议就会出现问题,比如:

<a href="#" onclick="showPic(this);return false;">悟空</a>

因此,在href中设置路径是最好的选择。

6.5 它的JavaScript与HTML标记是否分离

网页的行为层(JavaScript)和结构层(HTML)是否分离?
答案:否

<li><a href="image/toWest/monkey.webp" title="悟空" onclick="showPic(this);return false;">悟空</a></li>

理想情况下,HTML标记应该只负责结构,JavaScript应该只负责行为。但是HTML标记中包含了JavaScript代码,这就违背了分离原则。
修改后的HTML代码如下:

<ui id="imageGallery">
    <li><a href="image/toWest/monkey.webp" title="悟空">悟空</a></li>
    <li><a href="image/toWest/tulv.webp" title="唐僧">唐僧</a></li>
    <li><a href="image/toWest/pig.webp" title="八戒">八戒</a></li>
    <li><a href="image/toWest/wujing.webp" title="悟净">悟净</a></li>
    <li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘">白娘娘</a></li>
    <li><a href="image/whiteSnake/doctor.webp" title="许仙">许仙</a></li>
    <li><a href="image/whiteSnake/greenSnake.webp" title="小青">小青</a></li>
</ui>

对列表中相同的方法使用id=“image-gallery”

6.5.1 添加事件处理函数

事件处理函数需要实现

  • 检测浏览器是否理解getElemntById()方法
  • 检测浏览器是否理解getElemntByTagName()方法
  • 检查网页是否存在一个id为"imageGallery"的元素
  • 遍历"imageGallery"元素中的所有链接
  • 设置onclick事件处理函数,点击时完成如下操作:
    • 调用showPic()函数,显示图片
    • 显示描述
    • 阻止默认行为
function prepareGallery() {
    // 检测浏览器是否理解getElemntById()方法
    if (!document.getElementsByTagName) return false;
    if (!document.getElementById) return false;
    if (!document.getElementById("imageGallery")) return false;

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

6.5.2 共享onload事件处理函数

在网页加载完成后执行prepareGallery函数

window.onload = function() {
    prepareGallery();
}

为了兼容可能存在要加载多个函数

function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != "function") {

        window.onload = func;
    } else {
        window.onload = function() {
            oldonload();
            func();
        }
    }
}

addLoadEvent(prepareGallery);

到此为止,实现prepareGallery函数,可以正常运行。

6.6 不要做太多的假设

在prepareGallery函数中,我们假设了document.getElementById()方法存在,但是如果浏览器不支持该方法,该函数将无法正常运行。
因此不用在showPic函数中使用document.getElementById()方法

但是,代码里面还是假设了一定存在id为"placeholder"的元素和"description"元素,并未检测到是否存在。
因此,在showPic函数中,我们也需要添加对这两个元素的检测。这里图片显示是核心功能,描述是锦上添花,因此只做到点击图片,在占位符placeholder显示

function showPic(whichPic) {
    // 检测图片元素是否存在
    if (document.getElementById("placeholder") == null) 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;
}    

此时,图片库改进版已经可以正常运行,并且兼容了JS被禁用情况。

后面还有一种描述不明白,“把placeholder图片从标记文档里删掉,并在浏览器刷新界面,无论点击imageGallery中的哪个链接都没有反应”?(我实测好像可以)这里记录优化方法

links[i].onclick = function() {
    showPic(this);
    return false;
}

// 修改为根据showPic函数返回值判断是否成功显示图片
links[i].onclick = function() {
    return !showPic(this);

先这样吧,没看懂

6.7 优化

看下代码清单

function showPic(whichPic) {
    // 检测图片元素是否存在
    if (document.getElementById("placeholder") == null) 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;
}

这里witchPic默认存在title属性,但是如果没有title属性,则会报错,因此可以优化一下,如下:

if (whichPic.getAttribute("title")) {
    var text = whichPic.getAttribute("title");
} else {
    var text = "";
}

// 或者
var text = whichPic.getAttribute("title") ? whichPic.getAttribute("title") : "";

检查description元素是否为文本

if (document.getElementById("description") && document.getElementById("description").firstChild.nodeType == 3) {
    var description = document.getElementById("description");
    description.firstChild.nodeValue = text;
}

在一般工作中,可以根据需要进行判断

6.8 键盘访问

现在代码假设用户只能通过鼠标点击图片,但是如果用户通过键盘Tab键切换到图片,则无法触发事件。
这里添加onkeypress事件处理函数,按下tab可以移动链接,按下enter可以触发事件。

links[i].onkeypress = function(event) {
    if (event.keyCode == 13) {
        if (showPic(this)) ? true : false;
    }
}

书里原文是按下任意键可以触发事件

links[i].onkeypress = links[i].onclick;

这里就是js和html分离的好处,可以让html代码更加简洁,js代码可以更加灵活。

实际上,在几乎所有浏览器,tab键都可以切换到链接,enter键就可以触发onclick事件。因此,这里的优化并没有带来实际的好处。

6.9 把JavasScript与CSS结合起来

css可以设置图片的大小,位置,边框等,可以让图片库更加美观。
在head标签中加入如下代码:

<link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen">

在css文件,利用id="imageGallery"中加入如下代码:
这个地方和书里不一样,我百科下载的图片,大小不一,调整了一下样式
最终css代码如下:

#imageGallery {
    list-style: none;
    margin: 0;
}

#imageGallery li {
    display: inline-flex;
}

#imageGallery li a img {
    max-width: 90px;
    max-height: 80px;
}

#placeholder img {
    display: inline-block;
    margin: 0 auto;
    width: 300px;
    height: 400px;
}

body {
    font-family: Arial, Helvetica, sans-serif;
    color: #333;
    background-color: #ccc;
    margin: 1em 10%;
}


h1 {
    color: #333;
    background-color: transparent;
}

a {
    color: #c60;
    background-color: transparent;
    font-weight: bold;
    text-decoration: none;
}

ul {
    padding: 0;
}

li {
    float: left;
    padding: 10px 10px 10px 0px;
    list-style-type: none;
}

img {
    display: flex;
    clear: both;
    max-width: 300px;
    max-height: 400px;
}

把图片链接转换成微缩图。

<a href="image/toWest/monkey.webp" title="悟空">
    <img src="image/toWest/monkey.webp" alt="悟空">
</a>    

6.10 DOM Core和HTML-DOM

这里使用的DOM方法getElemntById()、getElementsByTagName()、setAttribute()和getAttribute()等都是DOM Core中的方法。

不单单js,HTML等标记语言也可以用

HTML-DOM的方法onkeypress()、onclick()等都是HTML-DOM中的方法。

在HTML-DOM提供了许多描述HTML元素的属性,如获取图片src属性

var img = element.getElementById("myImg");
// 也可以使用
var img = element.src;

这些属性和方法可以互换
本书主要使用DOM Core中的方法,HTML-DOM中的方法可以作为补充。

6.11后记

本章主要介绍了图片库的改进版,主要内容是:

  • 事件处理移除文档
  • 向后兼容
  • 确保可访问

结构和行为分离的程度越大越好。
下章将介绍如何利用DOM提供的方法和属性去创建HTML元素,并插入HTML文档中。

6.12参考

  • HTML DOM
  • 《JavaScprpt DOM 编程艺术(第2版)》
  • 主要内容由Fitten Code生成, 强烈推荐

网站公告

今日签到

点亮在社区的每一天
去签到