2-3Web APIs 网页应用编程-DOM上

136 阅读8分钟

1.Web API 简介

1.Web API简介

1.API的概念

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,

目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访

问源码,或理解内部工作机制的细节。

  • 任何开发语言都有自己的 API

  • API 的特征输入和输出(I/O)

    例如:var max = Math.max(2,3,4);

  • API 的使用方法(console.log("abc"))

2.Web API概念

浏览器提供了一套操作浏览器功能和页面元素的 API(BOM 和 DOM)。

  • 此处的 Web API 特指浏览器提供的 API(一组方法),Web API 在后面的课程中有其它含义。
  • 学习目标:掌握常见浏览器提供的 API 的调用方式。
  • 学习辅助 MDN:developer.mozilla.org/zh-CN/docs/…

3.BOM - 浏览器对象模型

• browser object model,一套操作浏览器功能的 API。

• 通过 BOM 可以操作浏览器窗口,比如:弹出框、控制浏览器跳转、获取分辨率等 。

4.DOM - 文档对象模型

• document object model,一套操作页面元素的 API。

• DOM 可以把 HTML 看做是文档树,通过 DOM 提供的 API 可以对树上的节点进行操作

2.DOM的概念

文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标

记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地

访问程序和脚本,更新其内容、结构和 www 文档的风格(目前,HTML 和 XML 文档是通过

说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM 是一

种基于树的 API 文档,它要求在处理过程中整个文档都表示在存储器中

1.DOM树

• DOM 又称为文档树模型

• - 文档:一个网页可以称为文档

• - 节点:网页中的所有内容都是节点

(标签、属性、文本、注释等)

• - 元素:网页中的标签

• - 属性:标签的属性

image-20210209175048348

2.DOM经常进行的操作

  • 获取元素
  • 对元素进行操作(设置其属性或调用其方法)
  • 动态创建元素
  • 事件(什么时机做相应的操作)

2.DOM获取页面元素

1.根据id获取元素

• 方法:调用 document 对象的 getElementById 方法。

• 参数:字符串类型的 id 的属性值。

• 返回值:对应 id 名的元素对象。

• 注意1:由于 id 名具有唯一性,部分浏览器支持直接使用 id 名访问元素,但不是标准方式,

不推荐使用。

• 注意2:代码执行顺序,如果 js 在 html 结构之前,会导致结构未加载,不能获取对应id的

元素。

  <p id="para">text0</p>
  <p id="para">text1</p>
  <p id="box">text2</p>
  <p>text3</p>
  <p>text4</p>
  <script>
    // 根据 id 获取元素
    var para = document.getElementById("para");
    // console.log(typeof para);
    // 补充:在控制台打印具体的对象
    // console.dir(para);
    para.style.background = "pink";
    // 代码书写顺序:js 中获取元素时,必须保证元素已经在浏览器中渲染成功
    // 需要将 js 的代码写在 html 结构之后
    // box.style.background = "blue"; 不推荐直接使用 id 名
  </script>

2.根据标签名获取元素

• 方法:调用 document 对象的 getElementsByTagName 方法。

• 参数:字符串类型的标签名。

• 返回值:同名的元素对象组成的数组。

• 注意1:操作数据时需要按照操作数组的方法进行。

• 注意2:getElementsByTagName 方法内部获取的元素是动态增加的。

• 注意3:获取所有被选中的标签

  <script>
    // 提前获取元素
    var divs = document.getElementsByTagName("div");
    console.log(divs);
  </script>
</head>
<body>
  <p>text1</p>
  <p>text2</p>
  <p>text3</p>
  <p>text4</p>
  <div>div1</div>
  <div>div2</div>
  <div>div3</div>
  <div>
    <p>text5</p>
  </div>
  <script>
    console.log(divs);
    // 通过标签名获取元素
    var ps = document.getElementsByTagName("p");
    console.log(ps);
    // HTMLCollection  html 元素组成的集合 伪数组
    // 操作室需要按照操作数组的方法进行
    // 遍历数组
    for (var i = 0 ; i <= ps.length - 1; i++) {
      // 输出每一项
      console.log(ps[i]);
    }
    ps[0].style.background = "pink";
  </script>
</body>

3.根据 name 获取元素

• 方法:调用 document 对象的getElementsByName方法。

• 参数:字符串类型的 name 属性值。

• 返回值:name 属性值相同的元素对象组成的数组。

• 不建议使用:在 IE 和 Opera 中有兼容问题,会多选中 id 属性值相同的元素。

<body>
  <form>
    <input type="radio" name="age">0~10<br>
    <input type="radio" name="age">11~20<br>
    <input type="radio" name="age">20~30<br>
  </form>
  <div id="age">年龄</div>
  <script>
    // 通过标签的 name 属性获取元素
    var ages = document.getElementsByName("age");
    // NodeList  节点列表集合  类数组
    console.log(ages);
    // 兼容问题:在 IE 和 Opera中 有兼容问题,会多选中 id 属性值相同的部分
    // 方法选中的元素也是动态变化的,与`getElementsByTagName` 一样
  </script>
</body>

4.根据类名获取元素

• 方法:调用 document 对象的 getElementsByClassName 方法。

• 参数:字符串类型的 class 属性值。

• 返回值:class 属性值相同的元素对象组成的数组。

• 浏览器兼容问题:不支持 IE8 及以下的浏览器

<script>
    // 通过 class 属性值获取元素
    // var paras = document.getElementsByClassName("para");
    // console.log(paras);
  </script>
</head>
<body>
  <div id="box1">
    <p>text1 of box1</p>
    <p class="para">text2 of box1</p>
    <p class="para">text3 of box1</p>
    <p>text4 of box1</p>
  </div>
  <div id="box2">
    <p>text1 of box2</p>
    <p class="para">text2 of box2</p>
    <p class="para">text3 of box2</p>
    <p>text4 of box2</p>
  </div>
  <script>
    // 通过 class 属性值获取元素
    // var paras = document.getElementsByClassName("para");
    // 获取 id 为 box1 的元素对象
    var box1 = document.getElementById("box1");
    // 元素对象内部也可以调用 getElementsByClassName 方法
    var paras1 = box1.getElementsByClassName("para");
    console.log(paras1);
    // 兼容问题:不支持 IE 8 及以下浏览器
  </script>
</body>

5.根据选择器获取元素

• 方法1:调用 document 对象的 querySelector 方法,通过 css 中的选择器去选取第一个

符合条件的标签元素。

• 方法2:调用 document 对象的 querySelectorAll 方法,通过 css 中的选择器去选取

符合条件的标签元素。

• 参数:字符串类型的 css 中的选择器。

浏览器兼容问题:不支持 IE8 以下的浏览器

 <script>
    // // 在结构之前使用 选择器 选取方法
    // var para = document.querySelector("#box1 .para");
    // console.log(para);

    // 选择所有符合条件的元素
    // var paras = document.querySelectorAll("#box1 .para");
    // console.log(paras);
  </script>
</head>
<body>
  <div id="box1">
    <p>text1 of box1</p>
    <p class="para">text2 of box1</p>
    <p class="para">text3 of box1</p>
    <p>text4 of box1</p>
  </div>
  <div id="box2">
    <p>text1 of box2</p>
    <p class="para">text2 of box2</p>
    <p class="para">text3 of box2</p>
    <p>text4 of box2</p>
  </div>
  <script>
    // 在结构之后使用 选择器 选取方法
    var para = document.querySelector("#box1 .para");
    console.log(para);
    var paras = document.querySelectorAll("#box1 .para");
    console.log(paras);
    // 兼容问题:在 IE8 以下不能使用
  </script>
</body>

6.总结

掌握,没有兼容问题

getElementById()

getElementsByTagName()

了解

• getElementsByName()

• getElementsByClassName()

querySelector()

querySelectorAll()

3.DOM事件基本应用

1.事件

• 事件:在什么时候做什么事

• 执行机制:触发--响应机制

• 绑定事件(注册事件)三要素:

1、事件源:给谁绑定事件

2、事件类型:绑定什么类型的事件 click 单击

3、事件函数:事件发生后执行什么内容,写在函数内部

2.常用的鼠标事件类型

onclick鼠标左键单击触发
ondbclick鼠标左键双击触发
onmousedown鼠标按键按下触发
onmouseup鼠标按键放开时触发
onmousemove鼠标按键放开时触发
onmouseover鼠标移动到元素上触发
onmouseout鼠标移出元素边界触发

4.掌握 DOM 元素属性操作方式

1.非表单元素的属性

• 例如:href、title、id、src 等。

• 调用方式:元素对象打点调用属性名,例如 obj.href。

• 注意:部分的属性名跟关键字和保留字冲突,会更换写法。

class → className

for → htmlFor

rowspan → rowSpan

• 属性赋值:给元素属性赋值,等号右侧的赋值都是字符串格式。

<body>    
    <a href="http://www.baidu.com" title="跳转到百度页面" id="link">跳转</a>
    <img src="images/a.jpg" alt="美女" class="pic" id="pic">
    <script>
        // 获取元素
        var link = document.getElementById("link");
        var pic = document.getElementById("pic");
        // 调用元素对象的属性,从而操作 HTML 中标签的属性
        console.log(link.href);
        console.log(link.title);
        console.log(link.id);
        console.log(pic.src);
        console.log(pic.alt);
        console.log(pic.className);
        // 等号赋值,值必须是字符串类型的
        pic.src = "images/b.jpg";
    </script>
</body>

2.---------案例

• 点击按钮切换图片

• 点击按钮显示隐藏 div

• 美女相册

<body>
  <input type="button" value="点击" id="btn"><br>
  <img src="images/a.jpg" id="pic">
  <script>
    // 获取元素
    var btn = document.getElementById("btn");
    var pic = document.getElementById("pic");
    // 通过一个变量作为判断条件,变量值为 1,认为加载的是 a 图片,如果为 2 ,认为加载的是 b 图片
    var num = 1;
    // 给按钮添加点击事件
    btn.onclick = function () {
      // 给图片换 src 的属性值
      // 通过 if 语句判断,如果是 a 图片,就换成 b 图片,反之换成 a 图片
      if (num === 1) {
        pic.src = "images/b.jpg";
        // 数字要对应发生变化
        num = 2;
      } else {
        pic.src = "images/a.jpg";
        num = 1;
      }
    };
  </script>
</body>
 <style>
    * {
      margin: 0;
      padding: 0;
    }
    div {
      width: 200px;
      height: 200px;
      background-color: pink;
    }
    .hide {
      display: none;
    }
    .show {
      display: block;
    }
  </style>
</head>
<body>
  <input type="button" value="点击隐藏" id="btn">
  <div id="box"></div>
  <script>
    // 获取元素
    var btn = document.getElementById("btn");
    var box = document.getElementById("box");
    // 点击按钮,让 div 显示或隐藏
    // box.style.display = "none";
    btn.onclick = function () {
      // 元素 div 当前是显示的,需要让他隐藏
      // 根据 按钮 的 value 值进行条件判断
      if (btn.value === "点击隐藏") {
        box.className = "hide";
        btn.value = "点击显示";
      } else {
        box.className = "show";
        btn.value = "点击隐藏";
      }
      
    };
      
      // 在事件函数内部 有一个 this ,指向事件源

    // 区分一下不同函数内部 this 的指向
    // 普通函数   ->  window 对象
    // 构造函数   ->  指向的是生成的实例对象
    // 对象的方法  -> 指向的是对象本身
    // 事件函数   -> 指向的是事件源
  </script>
    <style type="text/css">
        body {
            font-family: "Helvetica", "Arial", 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: 1em;
            list-style: none;
        }

        #imagegallery {}

        #imagegallery a {
            margin: 0px 20px 20px 0px;
            padding: 0px;
            display: inline;
        }

        #imagegallery a img {
            border: 0;
        }
    </style>
</head>

<body>
    <h2>
        美女画廊
    </h2>

    <div id="imagegallery">
        <a href="images/1.jpg" title="美女A">
            <img src="images/1-small.jpg" width="100px" alt="美女1" />
        </a>
        <a href="images/2.jpg" title="美女B">
            <img src="images/2-small.jpg" width="100px" alt="美女2" />
        </a>
        <a href="images/3.jpg" title="美女C">
            <img src="images/3-small.jpg" width="100px" alt="美女3" />
        </a>
        <a href="images/4.jpg" title="美女D">
            <img src="images/4-small.jpg" width="100px" alt="美女4" />
        </a>
    </div>

    <div style="clear:both"></div>

    <img id="image" src="images/placeholder.png" alt="" width="450px" />

    <p id="des">选择一个图片</p>
    <script>
        // 1.获取元素
        var imagegallery = document.getElementById("imagegallery");
        var links = imagegallery.getElementsByTagName("a");
        var image = document.getElementById("image");
        var des = document.getElementById("des");

        // 2.遍历数组,添加点击事件
        for (var i = 0 ; i <= links.length - 1 ; i++) {
            links[i].onclick = function () {
                // alert("aaa");
                // 3.更改 image 内部的 src 属性值
                // this 关键字指代的是触发事件的真正事件源
                image.src = this.href;
                // image.src = links[i].href;
                // 4.更改 des 内部的文字内容
                des.innerText = this.title;
                // 5.取消 a 标签的默认跳转效果
                return false;
            };
        }

        // for 循环内部添加的绑定事件,在触发时,所有的批量添加的事件已经成功,触发事件时都是在循环结束之后
        // 批量绑定的事件的事件函数内部如果有 变量 i,要注意,函数执行时已经是在循环结束后
        // 循环内部定义的变量是一个全局变量,在循环后执行的 i 变量的值是 i 跳出循环时的值
        // image.src = links[i].href;
        // console.log(i);
    </script>
</body>

3.获取标签内部内容的属性

• 获取标签内部内容的属性有两个:innerHTML 和 innerText

• innerHTML属性,在获取标签内部内容时,如果包含标签,获取的内容会包含标签,获取的

内容包括空白换行等。

• innerText属性,在获取标签内部内容时,如果包含标签,获取的内容会过滤标签,获取的

内容会去掉换行和缩进等空白。

<body>
  <div id="box">
    这是一个 div 标签
    <span>这是一个 span 标签</span>
  </div>
  <script>
    // 获取元素
    var box = document.getElementById("box");
    // 打印 box 对象
    console.dir(box);
    // 调用标签内部内容
    console.log(box.innerHTML);
    console.log(box.innerText);
    // 设置标签内部的内容
    // box.innerHTML = "<h2>hello JS</h2>";
    box.innerText = "<h2>hello JS</h2>";
  </script>
</body>

4.更改标签内容

还可以通过两个属性给双标签内部去更改内容:

• innerHTML 设置属性值,有标签的字符串,会按照 HTML 语法中的标签加载。

• innerText 设置属性值,有标签的字符串,会按照普通的字符加载。

对比使用场景

• innerText:在设置纯字符串时使用。

• innerHTML:在设置有内部子标签结构时使用。

5.表单元素属性

• value 用于大部分表单元素的内容获取(option除外)

• type 可以获取input标签的类型(输入框或复选框等)

• disabled 禁用属性

• checked 复选框选中属性

• selected 下拉菜单选中属性

• 注意:在 DOM 中元素对象的属性值只有一个时,会被转成布尔值显示。

例如:txt.disabled = true;

<body>
  <input type="button" value="按钮" id="btn"><br>
  <input type="text" id="txt">
  <select id="list">
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
  </select>
  <script>
    // 获取元素
    var btn = document.getElementById("btn");
    var txt = document.getElementById("txt");
    var list = document.getElementById("list");
    var opts = list.getElementsByTagName("option");
    
    // value 属性
    // console.log(btn.value);
    // console.log(txt.value);
    // console.log(opts[0].value);
    // console.log(opts[0].innerHTML);

    // 更改 input 标签的 value
    // btn.value = "点击";
    // txt.value = "请输入内容"

    // 表单元素特有的一些属性,属性名和属性值是一致的
    // console.log(txt.disabled);
    btn.disabled = true;
  </script>
</body>

6.---------案例

• 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框

• 设置下拉框中的选中项

• 搜索文本框

• 全选反选

    <style>
        .bg{
            background: yellow;
        }
    </style>
</head>
<body>
    <input type="text" id="name"><br>    
    <input type="text" id="pw"><br>
    <input type="button" id="btn" value="提交">
    <script>
        // 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框
        // 1.获取元素
        var btn = document.getElementById("btn");
        
        // 2.给按钮添加点击事件,然后判断位数是否足够
        btn.onclick = function () {
            // 在事件触发后,去获取对象,内部的数据才是最新
            var name = document.getElementById("name");
            var pw = document.getElementById("pw");
            // 用户名位数是否在 3-6 位,不满足需要高亮显示
            if (name.value.length < 3 || name.value.length > 6) {
                name.className = "bg";
                return;
            } else {
                name.className = "";
            }
            // 密码的位数必须在 6-8 位之间,否则高亮显示
            if (pw.value.length < 6 || pw.value.length > 8) {
                pw.className = "bg";
                return;
            } else {
                pw.className = "";
            }
            // 提交数据
            console.log("提交数据");
        };  
    </script>
</body>
<body>
    <input type="button" value="选择" id="btn">
    <br>
    <select id="food">
        <option>烤肉</option>
        <option>拉面</option>
        <option>麻辣烫</option>
        <option>小龙虾</option>
        <option>火锅</option>
        <option>外卖</option>
    </select>
    <script>
        // 1.获取元素
        var btn = document.getElementById("btn");
        var food = document.getElementById("food");
        var opts = food.getElementsByTagName("option");

        // 2.给按钮添加点击事件
        btn.onclick = function () {
            // 3.随机选择一个 option
            // 每次点击需要获取一个 opts 数组的随机下标
            // Math.random()   [0,1)
            // Math.random()*6   [0,6)
            var n = Math.floor(Math.random() * opts.length);
            // console.log(n);
            // 设置对应的随机项的属性
            opts[n].selected = true;
        };
    </script>
</body>
  <style>
    .gray {
      color: gray;
    }

    .black {
      color: black;
    }
  </style>
</head>

<body>
  <input type="text" class="gray" value="请输入搜索关键字" id="txtSearch">
  <input type="button" value="搜索" id="btnSearch">
  <script>
    // 获取元素
    var txtSearch = document.getElementById("txtSearch");
    // 1.获得焦点时,可以使用一个 onfocus,如果文本框内容是默认 请输入搜索关键字,需要清空文字,让文字加载黑色
    txtSearch.onfocus = function () {
      // 判断是否是默认的提示文字
      if (this.value === "请输入搜索关键字") {
        this.value = "";
        this.className = "black";
      }
    };
    // 2.失去焦点时,可以使用一个 onblur,如果文本框内容为空,需要改为默认提示内容 请输入搜索关键字,让文字颜色变为灰色
    txtSearch.onblur = function () {
      // 如果用户输入的内容正好与默认提示文本相同,失去焦点时,也应该让文字颜色变为灰色
      // 判断内容是否为空
      if (this.value === "" || this.value === "请输入搜索关键字") {
        this.value = "请输入搜索关键字";
        this.className = "gray";
      }
    };
  </script>
</body>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        .wrap {
            width: 300px;
            margin: 100px auto 0;
        }

        table {
            border-collapse: collapse;
            border-spacing: 0;
            border: 1px solid #c0c0c0;
            width: 300px;
        }

        th,
        td {
            border: 1px solid #d0d0d0;
            color: #404060;
            padding: 10px;
        }

        th {
            background-color: #09c;
            font: bold 16px "微软雅黑";
            color: #fff;
        }

        td {
            font: 14px "微软雅黑";
        }

        tbody tr {
            background-color: #f0f0f0;
        }

        tbody tr:hover {
            cursor: pointer;
            background-color: #fafafa;
        }
    </style>

</head>
<body>
  <div class="wrap">
      <table>
          <thead>
            <tr>
                <th>
                    <input type="checkbox" id="all" />
                </th>
                <th>商品</th>
                <th>价钱</th>
            </tr>
          </thead>
          <tbody id="tb">
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>iPhone8</td>
                <td>8000</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>iPad Pro</td>
                <td>5000</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>iPad Air</td>
                <td>2000</td>
            </tr>
            <tr>
                <td>
                    <input type="checkbox" />
                </td>
                <td>Apple Watch</td>
                <td>2000</td>
            </tr>

          </tbody>
      </table>
      <input type="button" value="  反 选  " id="btn">
  </div>
  <script>
    // 获取元素
    var all = document.getElementById("all");
    var tb = document.getElementById("tb");
    var btn = document.getElementById("btn");
    var tb_inputs = tb.getElementsByTagName("input");

    // 1.全选:让子选项的选择效果始终与全选保持一致
    all.onclick = function () {
        // 遍历所有的子选项
        for (var i = 0 ; i < tb_inputs.length ; i++) {
            // 让每一个子选项的 checked 属性值与全选保持一致
            tb_inputs[i].checked = all.checked;
        }
    };
    // 2.单独选择子选项过程
    // 给每一次点击任何一个子选项进行判断
    for (var i = 0 ; i < tb_inputs.length ; i++) {
        tb_inputs[i].onclick = function () {
            // 需要判断所有的子选项是否都是选中的状态,如果都选中,让全选被选中,如果有的没有被选中,让全选取消选择
            allChecked();
        }
    }
    // 3.反选
    btn.onclick = function () {
        // 让所有子选项与之前的状态相反
        for (var i = 0 ; i < tb_inputs.length ; i++) {
            // 让属性值取原来相反的值
            tb_inputs[i].checked = !tb_inputs[i].checked;
        }
        // 控制全选效果,也需要进行取反
        allChecked();
    };
    // 定义一个 all 是否被选中的函数
    function allChecked() {
        // 使用一个中间过渡变量,初始认为所有的子选项都是被选中的
        var isAllChecked = true;
        // 遍历所有子选项,进行判断
        for (var j = 0 ; j < tb_inputs.length ; j++) {
            // 一旦有一个是没有被选择的,让变量变为 false
            if (tb_inputs[j].checked === false) {
                isAllChecked = false;
                // 只要走到这里,说明肯定不是全选,不需要往下执行循环
                break;
            }
        }
        // 如果循环内部条件永远不成立,说明所有子选项都是被选中,isAllChecked 的值没有发生变化,还是 true
        // 给 all 元素设置 checked 属性
        all.checked = isAllChecked;
    }
  </script>
</body>

7.自定义属性操作

getAttribute(name) 获取标签行内属性

setAttribute(name,value) 设置标签行内属性 :修改属性或者添加新的属性

removeAttribute(name) 移除标签行内属性

element.属性的区别: 上述三个方法用于获取任意的行内属性,包括自定义的属性。

<body>
  <div id="box" age="18" sex="male">小明</div>
  <script>
    // 获取元素
    var box = document.getElementById("box");
    // 元素自有属性
    console.log(box.id);
    // 元素自定义的新属性不能用点语法直接调用
    // 可以调用元素对象的获取自定义属性的方法
    console.log(box.getAttribute("age"));
    console.log(box.getAttribute("sex"));
    // 也可以调用自有的属性
    console.log(box.getAttribute("id"));

    // 设置属性,添加新的自定义属性或者自有属性
    box.setAttribute("age","20");
    box.setAttribute("city","Beijing");
    // 传的参数不需要进行属性名的修改
    box.setAttribute("class","demo");

    // 移除属性
    box.removeAttribute("age");
    box.removeAttribute("class");
  </script>
</body>

8.style 样式属性操作

• 使用 style 属性方式设置的样式显示在标签行内。

• element.style 属性的值,是所有行内样式组成的一个样式对象。

• 样式对象可以继续点语法调用或更改 css 的行内样式属性,例如 width、height 等属性。

• 注意1:类似 background-color 这种复合属性的单一属性写法,是由多个单词组成的,要

修改为驼峰命名方式书写 backgroundColor。

• 注意2:通过样式属性设置宽高、位置的属性类型是字符串,需要加上 px 等单位。

    <style>
        .bg{
            background-color: pink;
        }
    </style>
    <script src="common.js"></script>
</head>
<body>
    <input type="button" value="按钮" id="btn">
    <div id="box" style="width: 100px" class="bg">文字</div>
    <script>
        // 获取元素        
        var btn = my$("btn");
        var box = my$("box");
        // console.log(btn);
        // 1.更改类名的方式去更改样式
        // 2.根据对象的 style 属性去操作样式
        console.log(btn.style);
        // 元素对象的 style 属性的值是一个行内样式组成对象,对象内部封装了所有的行内的样式属性及属性值
        // 元素的样式属性对象可以继续打点调用,获取或设置相关的行内样式属性
        console.log(box.style);
        console.log(box.style.width);
        // 注意:如果使用的 css 属性名是复合属性的单一属性,需要更改为驼峰命名法
        console.log(box.style.backgroundColor);
        box.style.width = "200px";
    </script>
</body>

9.className 类名属性操作

• 修改元素的 className 属性相当于直接修改标签的类名。

• 如果需要修改多条 css 样式,可以提前将修改后的样式设置到一个类选择器中,后续通过

修改类名的方式,批量修改 css 样式。

    <style>
        .cls {
          width: 100px;
          height: 100px;
          background-color: pink;
        }
    </style>
    <script src="common.js"></script>
</head>
<body>
    <input type="button" value="按钮" id="btn">
    <div id="box">文字</div>
    <script>
        // 问题:实际工作中我们应该选择哪种方法?
        // 获取元素
        var btn = my$("btn");
        var box = my$("box");
        // 给按钮添加事件
        btn.onclick = function () {
          // 1.通过更改类名
          // box.className = "cls";
          // 2.通过元素对象的 style 属性进行设置
          box.style.width = "100px";
          box.style.height = "200px";
          box.style.backgroundColor = "yellow";
        };
    </script>
</body>

10.---------案例

• 开关灯

• 图片切换二维码案例

• 当前输入的文本框高亮显示

• 点击按钮改变div的大小和位置

• 表格隔行变色、高亮显示

• tab选项卡切换

<body>
  <input type="button" value="关灯" id="btn">
  <script src="common.js"></script>
  <script>
    // 获取元素
    var btn = my$("btn");
    // console.log(btn);
    // 定义一个判断变量,true 表示开灯状态,false 表示关灯状态
    // var isOpen = true;
    // 点击事件,控制 body 的背景
    btn.onclick = function () {
      // 开灯时,需要点击后让它关灯并切换文字为 开灯
      // if (isOpen) {
      //   document.body.style.backgroundColor = "black";
      //   this.value = "开灯";
      //   isOpen = false;
      // } else {
      //   document.body.style.backgroundColor = "white";
      //   this.value = "关灯";
      //   isOpen = true;
      // }
      // 直接使用 btn 的 value 值进行判断
      if (this.value === "关灯") {
        document.body.style.backgroundColor = "black";
        this.value = "开灯";
      } else {
        document.body.style.backgroundColor = "white";
        this.value = "关灯";
      }
    };
  </script>
</body>
    <style>
        .box {
            width: 50px;
            height: 50px;
            background: url(images/bgs.png) no-repeat -159px -51px;
            position: fixed;
            right: 10px;
            top: 40%;
        }
        .erweima {
            position: absolute;
            top: 0;
            left: -150px;
        }
        .box a {
            display: block;
            width: 50px;
            height: 50px;
        }
        .hide {
            display: none;
        }
        .show {
            display: block;
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        <div class="erweima hide" id="er">
            <img src="images/456.png" alt=""/>
        </div>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var box = my$("box");
        var er = my$("er");
        // 给 box 添加鼠标移上事件 onmouseover ,添加鼠标离开事件 onmouseout
        box.onmouseover = function () {
            // 让子级元素进行显示,就是将 hide 改为 show
            // er.className = "erweima show";
            er.className = er.className.replace("hide","show");
        };
        box.onmouseout = function () {
            // 让子级元素进行隐藏,就是将 show 改为 hide
            // er.className = "erweima hide";
            er.className = er.className.replace("show","hide");
        };
    </script>
</body>
<body>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <button id="btn">按钮</button>    
    <script>
        // 获取元素
        var txts = document.getElementsByTagName("input");
        // 添加批量的获取焦点事件
        for (var i = 0 ; i < txts.length ; i++) {
            // 排他思想:1.排除其他 2.保留自己         

            // 给每一个input标签添加获取焦点事件
            txts[i].onfocus = function () {
                // 排除其他的方法:将所有的项包含自己都设置为默认样式
                // 遍历数组,让所有的样式恢复默认
                for (var j = 0 ; j < txts.length ; j++) {
                    txts[j].style.backgroundColor = "";
                }
                // 设置元素自己高亮显示
                // 保留自己的特殊样式
                // this 指代事件源自己
                this.style.backgroundColor = "yellow";
            };
        }
    </script>
</body>
    <style>
        div{
            width: 100px;
            height: 100px;
            background-color: pink;
        } 
        .new {
            position: absolute;
            width: 200px;
            height: 200px;
            left: 200px;
            top: 200px;
        }       
    </style>
</head>
<body>
    <input type="button" value="按钮" id="btn">
    <div id="box"></div>
    <script src="common.js"></script>
    <script>
        //获取元素
        var btn = my$("btn"); 
        var box = my$("box"); 
        // 添加事件
        btn.onclick = function () {
            // 修改类名
            // box.className = "new";
            // 修改 style 样式对象中的属性
            box.style.width = "200px";
            box.style.height = "200px";
            box.style.left = "200px";
            box.style.top = "200px";
            box.style.position = "absolute";
        };
    </script>
</body>
    <style>
        td{
            width: 100px;
            height: 40px;
        }
    </style>
</head>
<body>
    <table border="1" style="border-collapse: collapse;">
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </table>
    <script>
        // 获取所有的行
        var trs = document.getElementsByTagName("tr");
        // 1.隔行变色
        for (var i = 0; i < trs.length ; i++) {
            // 下标为偶数的行显示粉色
            // 下标为奇数的行显示灰色
            if (i % 2 == 0) {
                trs[i].style.backgroundColor = "pink";
            } else {
                trs[i].style.backgroundColor = "lightgray";
            }
            // 2.鼠标移上高亮显示,鼠标离开恢复默认
            // 全局变量
            var bgc;
            // 鼠标移上高亮显示
            trs[i].onmouseover = function () {
                // 定义变量记录 tr 原来的颜色
                bgc = this.style.backgroundColor;
                this.style.backgroundColor = "skyblue";
            };
            // 鼠标离开恢复默认
            trs[i].onmouseout = function () {
                this.style.backgroundColor = bgc;
            };
        }
    </script>
</body>
    <style>
        * {margin:0; padding: 0;}
        ul {
            list-style-type: none;
        }
        .box {
            width: 400px;
            height: 300px;
            border: 1px solid #ccc;
            margin: 100px auto;
            overflow: hidden;
        }
        .hd {
            height: 45px;
        }
        .hd span {
            display:inline-block;
            width: 90px;
            background-color: pink;
            line-height: 45px;
            text-align: center;
            cursor: pointer;
        }
        .hd span.current {
            background-color: skyblue;
        }
        .bd div {
            height: 255px;
            background-color: skyblue;
            display: none;
        }
        .bd div.current {
            display: block;
        }
    </style>

</head>
<body>
    <div class="box">
        <div class="hd" id="hd">
            <span class="current">体育</span>
            <span>娱乐</span>
            <span>新闻</span>
            <span>综合</span>
        </div>
        <div class="bd" id="bd">
            <div class="current">我是体育模块</div>
            <div>我是娱乐模块</div>
            <div>我是新闻模块</div>
            <div>我是综合模块</div>
        </div>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var hd = my$("hd");
        var spans = hd.getElementsByTagName("span");
        var bd = my$("bd");
        var divs = bd.getElementsByTagName("div");
        // 鼠标移上某个 span 让它添加一个类名,其他的失去类名
        for (var i = 0 ; i < spans.length ; i++) {
            // 给每一个 span 元素添加一个新的属性,记录自己在数组中的下标
            spans[i].index = i;
            spans[i].onmouseover = function () {
                // console.dir(this);
                // 1.让 span 自己进行切换
                // 排他思想:
                // 排除其他
                for (var j = 0; j < spans.length ; j++) {
                    spans[j].className = "";
                    // 由于 divs 中数据个数与 spans 一样,所以可以再同一个遍历循环中,进行排他操作
                    divs[j].className = "";
                }
                // 保留自己
                this.className = "current";
                // console.log(this.index);
                // 2.让 bd 中的 div 也对应进行切换
                // 对应控制思想:有两组数据中存储了相同个数的元素对象,一组对象的变化,会引起另外一组的变化
                // 实现方法:找两个数据中的共同点,两个数组中元素对象的下标是一样的
                // 对应控制中也会涉及到排他的操作
                // 保留 div 自己的类名
                divs[this.index].className = "current";
            };
        }

    </script>
</body>

11.节点属性

• nodeType 节点的类型,属性值为数字,表示不同的节点类型,共 12 种,只读

1 元素节点

2 属性节点

3 文本节点

• nodeName 节点的名称(标签名称),只读

• nodeValue 节点值,返回或设置当前节点的值

元素节点的 nodeValue 始终是 null

<body>
    <div id="box">div 1</div>
    <div id="demo">
        <p>paragraph 1</p>
        <p>paragraph 2</p>
        <p>paragraph 3</p>
        <div class="inner">
            <p>inner p</p>
        </div>
    </div>
    <script>
        // 生成一个新的元素对象
        var newNode = document.createElement("div");
        newNode.innerHTML = "新的 div";
        // 给 body 添加一个新的节点子元素
        document.body.appendChild(newNode);
        // 移除一些元素
        var box = document.getElementById("box");
        var demo = document.getElementById("demo");
        document.body.removeChild(box);

        // 获取节点内部的子元素节点
        var child1 = demo.children;
        console.log(child1);
    </script>
</body>
<body>
    <div id="box">div 1</div>
    <script>
        var box = document.getElementById("box");
        // 元素节点
        // console.dir(box);
        // 属性节点获取
        var idNode = box.getAttributeNode("id");
        console.dir(idNode);
        idNode.nodeValue = "demo";

        // 文本节点
        var childNodes = box.childNodes;
        console.log(childNodes);
        childNodes[0].nodeValue = "box 1";
    </script>
</body>

12.节点层级-父子节点常用属性

childNodes只读属性,获取一个节点所有子节点的实时的集合,集合是动态变化的。
children只读属性,返回一个节点所有的子元素节点集合,是一个动态更新的 HTML 元素
firstChild只读属性,返回该节点的第一个子节点,如果该节点没有子节点则返回 null。
lastChild只读属性,返回该节点的最后一个子节点,如果该节点没有子节点则返回 null。
parentNode返回一个当前节点的父节点,如果没有这样的节点,比如说像这个节点是树结构的顶端或者没有插入一棵树中,这个属性返回 null。
parentElement返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个 DOM
<body>
    <div id="box">
      <p>段落</p>
      <span>span 小盒子</span>
    </div>
    <script>
        var box = document.getElementById("box");
        // 获取子节点
        console.log(box.childNodes);   //或获取所有类型的子节点
        console.log(box.children);   //或获取所有元素类型的子节点
        console.log(box.firstChild);   //或获取所有类型的子节点的第一个
        console.log(box.lastChild);   //或获取所有类型的子节点的最后一个
        console.log(box.lastElementChild);   //或获取所有元素类型的子节点的最后一个
        // 获取父级
        console.log(box.parentNode);
        console.log(box.parentElement);
    </script>
</body>

父子节点-隔行变色 案例

    <style>
        td{
            width: 100px;
            height: 40px;
        }
    </style>
</head>
<body>
    <table border="1" style="border-collapse: collapse;">
        <tbody id="tb">
          <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        </tbody>
    </table>
    <script src="common.js"></script>
    <script>
        // 获取父级元素
        var tb = my$("tb");
        // 获取子元素的所有节点
        var trs = tb.children;  //获取的是所有的子元素的节点
        // console.log(trs);
        // 隔行变色
        for (var i = 0 ; i < trs.length; i++) {
          if (i % 2 == 0) {
            trs[i].style.backgroundColor = "pink";
          } else {
            trs[i].style.backgroundColor = "skyblue";
          }
        }
    </script>
</body>

13.节点层级-兄弟节点常用属性

nextSibling只读属性,返回与该节点同级的下一个节点,如果没有返回null。
previousSibling只读属性,返回与该节点同级的上一个节点,如果没有返回null
nextElementSibling只读属性,返回与该节点同级的下一个元素节点,如果没有返回null
previousElementSibling只读属性,返回与该节点同级的上一个元素节点,如果没有返回null

注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9以后才支持。

<body>
    <div id="box">
        <p>这是段落1</p>
        <p>这是段落2</p>
        <p id="p3">这是段落3</p>
        <p>这是段落4</p>
        <p>这是段落5</p>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var p3 = my$("p3");
        // 上一个兄弟节点
        console.log(p3.previousSibling);
        // 下一个兄弟节点
        console.log(p3.nextSibling);
        // 上一个兄弟元素的节点
        console.log(p3.previousElementSibling);
        // 下一个兄弟元素的节点
        console.log(p3.nextElementSibling);
        
    </script>
</body>

14.创建新节点的方法

document.createElement("div")创建元素节点
document.createAttribute("id")创建属性节点
document.createTextNode("hello")创建文本节点
<body>
  <div id="box">
    <p>段落内容 1</p>
    <p>段落内容 2</p>
    <p>段落内容 3</p>
    <p>段落内容 4</p>
  </div>
  <script src="common.js"></script>
  <script>
    // 创建新的节点
    var div = document.createElement("div");
    console.dir(div);

    var cls = document.createAttribute("class");
    console.dir(cls);

    var txt = document.createTextNode("hello");
    console.dir(txt);
    // 创建的新的节点,是存储在内存中的,但是并没添加到 DOM 树上
  </script>
</body>

15.节点操作方法 1-添加节点

parentNode.appendChild(child)将一个节点添加到指定父节点的子节点列表末尾。
parentNode.replaceChild(newChild, oldChild)用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。
parentNode.insertBefore(newNode, referenceNode)在参考节点之前插入一个拥有指定父节点的子节点,referenceNode 必须设置,如果 referenceElement 为 null 则 newNode将被插入到子节点的末尾。
parentNode.removeChild(child)移除当前节点的一个子节点。这个子节点必须存在于当节点中
Node.cloneNode()克隆一个节点,并且可以选择是否克隆这个节点下的所有内容。参数为Boolean 布尔值,表示是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被克隆,如果为 false,则只克隆该节点本身,默认值为 true,节点下的内容会被克隆。
Node.hasChildNodes()没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有子节点,不区分节点类型(空格也算)
Node.contains(child)返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后 代节点。祖孙级别也算
<body>
  <div id="box">
    <p>段落内容 1</p>
    <p id="p2">段落内容 2</p>
    <p>段落内容 3</p>
    <p>段落内容 4</p>
  </div>
  <script src="common.js"></script>
  <script>
    // 创建新的节点
    // 创建的新的节点,是存储在内存中的,但是并没添加到 DOM 树上
    var div = document.createElement("div");
    var cls = document.createAttribute("class");
    var txt = document.createTextNode("hello");
    
    // 获取元素
    var box = my$("box");
    var p2 = my$("p2");
    box.appendChild(div);
    // 文本节点也可以添加到元素内部
    div.appendChild(txt);
    // 注意:自己创建的元素节点本身也是一个对象,也可以去添加一些新的属性和方法,这些操作将来在元素加载到 DOM 树中时,依旧保留

    // DOM 中原有的节点也可以传给 appendChild 的参数
    // 1.将节点从原始位置删除   2.添加到新的指定位置
    // 原因: 内存中这个原有节点只有一个,渲染时只能有一个位置
    box.appendChild(p2);
  </script>
</body>

16.节点操作方法 2-替换、插入、移除

<body>
  <div id="box">
    <p>段落内容 1</p>
    <p id="p2">段落内容 2</p>
    <p>段落内容 3</p>
    <p>段落内容 4</p>
  </div>
  <script src="common.js"></script>
  <script>
    // 创建新的节点
    var div = document.createElement("div");
    var cls = document.createAttribute("class");
    var txt = document.createTextNode("hello");
    // 创建的新的节点,是存储在内存中的,但是并没添加到 DOM 树上
    div.appendChild(txt);
    // 获取元素
    var box = my$("box");
    var p2 = my$("p2");
    // 替换节点
    // box.replaceChild(div,p2);
    
    // 在某个指定子节点之前添加一个新的子节点
    // box.insertBefore(div,p2);
    // box.insertBefore(div,null);

    // 移除节点
    box.removeChild(p2);
  </script>
</body>

17.节点操作方法 3-克隆节点

<body>
  <div id="box">
    <p>段落内容 1</p>
    <p id="p2">段落内容 2</p>
    <p>段落内容 3</p>
    <p>段落内容 4</p>
  </div>
  <script src="common.js"></script>
  <script>
    // 获取元素
    var box = my$("box");
    var p2 = my$("p2");
    box.onclick = function () {
      alert(2);
    };

    // 克隆元素 box
    // 浅度克隆
    // var newBox = box.cloneNode(false);
    // 深度克隆
    var newBox = box.cloneNode(true);
    newBox.id = "newBox";
    document.body.appendChild(newBox);
  </script>
</body>

18.节点操作方法 4-判断节点

<body>
  <div id="box">
    <p>段落内容 1</p>
    <div>
      <p id="p2">段落内容 2</p>
    </div>
    <p>段落内容 3</p>
    <p>段落内容 4</p>
  </div>
  <div id="demo">

  </div>
  <script src="common.js"></script>
  <script>
    // 获取元素
    var box = my$("box");
    var p2 = my$("p2");
    var demo = my$("demo");
    
    // 判断内部有子节点的方法有三种
    // 1.判断有没有子节点,不区分节点类型
    // console.log(box.hasChildNodes());
    // console.log(demo.hasChildNodes());
    // 2.判断节点内部第一个子节点是否不为空
    // console.log(box.firstChild !== null);
    // console.log(demo.firstChild !== null);
    // 3.判断子节点的数组对象的长度是否为0
    console.log(box.childNodes.length > 0);
    console.log(demo.childNodes.length > 0);

    // 补充子元素节点是否存在
    console.log(box.children.length > 0);
    console.log(demo.children.length > 0);
    // 判断节点内部是否有某个后代节点
    // console.log(box.contains(p2));

  </script>
</body>

19.节点操作--判断方法总结

有三种方法可以判断当前节点是否有子节点。

• node.firstChild !== null

• node.childNodes.length > 0

• node.hasChildNodes()

20.---------案例

• 动态创建列表

• 动态创建表格

• 选择水果

<body>
  <h1>动态创建列表</h1>
  <div id="box">
    <!-- <ul>
      <li>刘备</li>
    </ul> -->
  </div>
  <script src="common.js"></script>
  <script>
    // 获取元素
    var box = my$("box");
    // 创建一组数据
    var names = ["刘备","曹操","孙权","关羽"];
    // 生成 ul 元素
    var ul = document.createElement("ul");
    // 添加 元素 到 box内部
    box.appendChild(ul);
    // 根据数组的项数往 ul 中添加数据
    for (var i = 0; i < names.length ; i++) {
      // 每次都要生成一个新的 li 标签元素
      var li = document.createElement("li");
      // 添加到 ul 对象内部
      ul.appendChild(li);
      // 给每个生成的 li 元素添加内容
      li.innerText = names[i];
    }
  </script>
</body>
  <style>
    table{
        border-collapse: collapse;
    }
    thead{
        background-color: #ccc;
    }
    th,td{
        width: 100px;
        height: 40px;
        text-align: center;
    }
  </style>
</head>
<body>
  <h1>动态创建表格</h1>
  <table id="wrap" border="1">
    <thead>
      <tr>
        <th>姓名</th>
        <th>科目</th>
        <th>成绩</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody id="tb">

    </tbody>
  </table>
  <script src="common.js"></script>
  <script>
    // 获取元素
    var tb = my$("tb");
    // 模拟后台传输的数据
    var datas = [
      {name: "zs",subject: "语文",score: 80},
      {name: "ls",subject: "数学",score: 87},
      {name: "ww",subject: "英语",score: 90},
      {name: "lb",subject: "物理",score: 89},
      {name: "cc",subject: "生物",score: 100},
      {name: "sq",subject: "化学",score: 98}
    ];
    // 根据数组中的数据个数生成对应个数的 tr 
    // 将生成 tr 添加到 tbody 中
    // 数组遍历
    for (var i = 0 ; i < datas.length ; i++) {
      // 每一个数据都要生成一个 tr
      var tr = document.createElement("tr");
      // 添加到 tb 中
      tb.appendChild(tr);
      // 每一个 tr 中还需要添加对应的 td 
      // 每一行 内部的 td 中的数据来自于 数组的每一项
      var data = datas[i]; //{name: "zs",subject: "语文",score: 80}
      // 遍历 data 对象,根据它的项数来确定添加的 td 的个数
      for (var k in data) {
        // 生成一个 td
        var td = document.createElement("td");
        // 添加到 tr 中去
        tr.appendChild(td);
        // 添加给每一个 td 数据
        td.innerText = data[k];
      }
      // 除了前面动态获取的数据 td 之外,还要添加一个删除的 td
      td = document.createElement("td");
      // 添加到 tr 中去
      tr.appendChild(td);
      // 最后一个 td 中需要添加一个 a 标签
      var a = document.createElement("a");
      a.innerText = "删除";
      a.href = "javascript:void(0);"
      // 将 a 添加到 td 中
      td.appendChild(a);
      // 给生成的每个 a 添加一个点击事件,移除当前所在的行
      a.onclick = function () {
        // 找到所在的行的 tr
        // this.parentNode.parentNode
        // 从 tbody 中移除对应的 tr
        tb.removeChild(this.parentNode.parentNode);
      };
    }
  </script>
</body>
 <style>
    select {
      width: 200px;
      height: 200px;
      background-color: #33cccc;
      font-size: 20px;
    }
  </style>
</head>

<body>
  <select id="all" size="5" multiple="multiple">
    <option>苹果</option>
    <option>橘子</option>
    <option></option>
    <option>西瓜</option>
    <option>水蜜桃</option>
  </select>

  <input type="button" value=">>" id="btn1">
  <input type="button" value="<<" id="btn2">
  <input type="button" value=">" id="btn3">
  <input type="button" value="<" id="btn4">

  <select id="choose" multiple="multiple">
  </select>

  <script src="common.js"></script>
  <script>
    // 获取元素
    var all = my$("all");
    var choose = my$("choose");
    var btn1 = my$("btn1");
    var btn3 = my$("btn3");
    // 给第一个按钮添加点击事件,让 all 中的所有子元素移动到 choose 中
    btn1.onclick = function () {
      var opts = all.children;  //内部的元素时动态添加的
      // 获取 all 中所有的子元素
      // 获取最开始的数组的个数
      var n = opts.length;
      // console.log(n);
      // 将所有的 opts 中的元素添加给 choose
      for (var i = 0 ; i < n ; i++) {
        choose.appendChild(opts[0]);
      }
    };  

    // 单选移动
    btn3.onclick = function () {
      var opts = all.children;  //内部的元素时动态添加的
      // 移动的内容希望可以是固定的一个数组中的项
      var arr = [];
      // 通过判断条件,往 arr 中添加需要移动的元素
      for (var i = 0 ; i < opts.length ; i++) {
        if (opts[i].selected === true) {
          arr.push(opts[i]);
        }
      }
      // console.log(arr);
      // 对需要移动的固定数组进行遍历
      for (var j = 0 ; j < arr.length ; j++) {
        choose.appendChild(arr[j]);
        arr[j].selected = false;
      }
      
    };
  </script>
</body>