46-2 JavaScript的对象-host object-DOM

DOM(文档对象模型,Document Object Model) 定义了访问 HTML 和 XML 文档的标准,允许程序和脚本动态地访问和更新文档的内容、结构和样式。

DOM 是 W3C(万维网联盟)的标准。分为 3 个不同的部分:

  • 核心 DOM:       针对任何结构化文档的标准模型
  • XML DOM:       针对 XML 文档的标准模型,定义了所有 XML 元素的对象和它的属性、方法。
  • HTML DOM:    针对 HTML 文档的标准模型,定义了所有 HTML 元素的对象和它的属性、方法。

本文讲的是HTML DOM。对谁、在何时、做什么样的操作。

一、对谁操作

(一)DOM节点

根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点(node):

  • 整个文档是一个文档节点 :                            document对象
  • 每个 HTML 元素(即标签)是元素节点 :          element 对象
  • HTML 元素内的文本是文本节点 :                   text对象
  • 每个 HTML 属性是属性节点 :                        attribute对象
  • 注释是注释节点 :                                        comment对象

每个节点都有自己的“自身属性”和“导航属性”。节点中最常用的是Document节点对象和Element节点对象。

 

1、自身属性

  • nodeName :  节点名称
  • nodeType :    节点类型
  • nodeValue :   节点值
  • attributes :     节点(元素)的属性节点
  • innerHTML :  节点(元素)内部的文本
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>
        <div id="div1">
            <div>hello div</div>
            <p>hello p</p>
        </div>
    </div>

<script>
    var ele=document.getElementById("div1");
    console.log(ele.nodeName);                     // DIV    标签名字
    console.log(ele.nodeType);                     // 1      编号,代表类型号
    console.log(ele.nodeValue);                    // null
    console.log(ele.attributes);                   // NamedNodeMap {0: id, length: 1}
</script>

</body>
</html>
View Code

2、导航属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="div1">
    <div>hello div</div>
    <a herf="#">hello a</a>
    <p>hello p</p>
</div>
</body>
</html>

 以上document的文档树:

节点树中的节点彼此拥有层级关系:

    • 在节点树中,顶端节点被称为根(root)
    • 除了根,每个节点都有父节点(parent)
    • 一个父节点可拥有任意数量的子节点(child)
    • 同级的子节点被称为同胞、兄弟或姐妹(sibling)

(二)获取对象

1、通过导航属性获取节点对象:

<script>
    var ele_obj=document.getElementById("div1");
    console.log(ele_obj.nodeName);                                         // DIV

    // 方式一:所有node都拿
    console.log(ele_obj.parentNode.nodeName);                              // BODY
    console.log(ele_obj.firstChild.nodeName);                              // #text  div2前有一个换行符,还有个缩进,它们属于text节点对象
    console.log(ele_obj.firstChild.nextSibling.nodeName);                  // DIV
    console.log(ele_obj.lastChild.nodeName);                               // #text
    console.log(ele_obj.lastChild.previousSibling.nodeName);               // P
    console.log(ele_obj.childNodes);                                       // [text, div, text, a, text, p, text]

    //  方式二:只拿element(标签)对象。推荐使用的方式
    console.log(ele_obj.parentNode.nodeName);                               // BODY
    console.log(ele_obj.firstElementChild.nodeName);                        // DIV
    console.log(ele_obj.firstElementChild.nextElementSibling.nodeName);     // A
    console.log(ele_obj.lastElementChild.nodeName);                         // P
    console.log(ele_obj.lastElementChild.previousElementSibling.nodeName);  // A
    console.log(ele_obj.children);                                          // [div, a, p]
</script>

2、通过对象的方法获取节点对象

(1)全局查找:document下查找

document.getElementById()
document.getElementsByTagName()            // 获取到的是一个数组
document.getElementsByClassName()          // 获取到的是一个数组
document.getElementsByName()               // 获取到的是一个数组

(2)局部查找:在某一标签对象下查找

ele_obj.getElementsByTagName()             // 获取到的是一个数组
ele_obj.getElementsByClassName()           // 获取到的是一个数组

 

二、在何时操作—— DOM 事件 

当用户点击某个 HTML 元素时启动一段 JavaScript代码。

1、给元素添加事件

(1)方式一:直接写在标签上(注意函数名后加括号才表示执行)

<div id="div1" onclick="alert(123)">点我呀</div>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
<p id="p1" onclick="func1(this)">hellop</p>
</body>

<script>
    function func1(self){
        alert(self.innerHTML);
    }
</script>

</html>
View Code

(2)方式二:在js区域,先找到标签对象,再对其进行事件绑定

var ele=document.getElementById("div1");
ele.onclick=function(){
    alert("123");
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
<p id="p1">hellop</p>
</body>

<script>
    var ele=document.getElementById("p1");
    ele.onclick=function(){
        alert(this.innerHTML);
    }
</script>

</html>
View Code

2、各种事件属性的介绍:

  • onclick                  用户点击某个对象时
  • ondblclick             用户双击某个对象时
  • onfocus                元素获得焦点时
  • onblur                   元素失去焦点时
  • onchange             域的内容被改变时
  • onselect                文本被选中时
  • onsubmit               确认按钮被点击时
  • onload                  一张页面或一幅图像完成加载时
  • onmousedown      鼠标按钮被按下时
  • onmousemove      鼠标被移动时
  • onmouseover        鼠标移到某元素之上时
  • onmouseout          鼠标从某元素移开时
  • onmouseleave       鼠标从元素离开时
  • onkeydown            某个键盘按键被按下时
  • onkeyup                某个键盘按键被松开时
  • onkeypress           某个键盘按键被按下并松开

(1)onfocusonblur

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input class="vip_no" type="text" onfocus="func1()" onblur="func2()" value="请输入卡号">
<input type="text" value="请输入卡号">               <!--获取焦点后,值不能自动消失,失去焦点后值不自动出现-->
<input type="text" placeholder="请输入卡号">         <!--在用户输入空格后,失去焦点提示不出现-->

<script>
    function func1(){
        var ele=document.getElementsByClassName("vip_no")[0];
        ele.value="";
    }

    function func2(){
        var ele=document.getElementsByClassName("vip_no")[0];
        if (ele.value.trim().length==0){                            // 判断用户是否输入空或仅为空格
            ele.value="请输入卡号";                                  // 如果未有效输入,则重现提示
        }
    }
</script>

</body>
</html>
示例:input输入提示

(2)onchange

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<select onchange="func3()" >
    <option>上海</option>
    <option>北京</option>
    <option>广州</option>
</select>

<script>
    function func3(){
        alert(1234);
    }
</script>

</body>
</html>
选择框

(3)onsubmit

用于form标签的提交验证。

a. 通过 return false 阻止表达提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--注意:加return关键字,因为onsubmit需要一个布尔值。而函数返回的结果是字符串,并不是真正的布尔值-->
<form id="form1" onsubmit="return check()">
    <input type="text" name="username">
    <input type="submit" value="submit">
</form>

<script>
    function check(){
        alert("验证失败!");
        return false;   // 当onsubmit得到false后,阻止提交并且知道先不要清空输入框中的内容,以便用户纠正已输入的内容而不是重新输
    }
</script>

</body>
</html>
表单验证

 b. 通过 event.preventDefault() 阻止表达提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form id="form1">
    <input type="text" name="username">
    <input type="submit" value="submit">
</form>

<script>
    var Form=document.getElementById("form1");
    Form.onsubmit=function(event){          // event参数可以省略不写
        alert("验证失败");
//        return false                      // 阻止方式一(与上面的例子在函数中返回false道理一样)
        event.preventDefault();             // 阻止方式二
    };
</script>

</body>
</html>
表达验证2

关于event对象:

event对象在事件发生时系统已经创建好了,并且会在事件函数被调用时传给事件函数。我们获得仅仅需要接收一下即可。

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

(4)onmouseoveronmousedownonmousemoveonmouseout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div{
            height: 100px;
            background-color: green;
            width:200px;
        }
    </style>
</head>
<body>
<div onmouseover="over()" onmousedown="down()" onmousemove="move()" onmouseout="out()" >div1</div>

</body>

<script>
    function over(){
        console.log("over");
    }

    function down(){
        console.log("down");
    }

    function move(){
        console.log("move");
    }

    function out(){
        console.log("out");
    }
</script>

</html>
View Code

(5)onload

定义代码一加载完就触发的事件。

使用场景1:当script代码放在html文档头部时,script中可能有操作html标签对象的部分,而此时所有html标签对象还没有加载呢,所以会报错。正确的做法是等加载完整个文档后,再执行这些代码。(另一种方法是:script代码放在文档后部,执行script代码时,html标签对象在上面都已经加载了)

a. 方式一:对windows对象设置onload事件(常用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        // 对 window对象设置onload事件:执行function函数时,整个文档都已经加载完成了,所以function函数能正常工作
        window.onload=function(){         // 文档加载完时,立马触发执行function函数              
            var p=document.getElementById("id1");
            alert(p.nodeName)
        }
    </script>
</head>

<body>
<p id="id1">hello p</p>
</body>
</html>
View Code

b. 方式二:对body设置onload事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        function func1(){
            var p=document.getElementById("id1");
            alert(p.nodeName)
        }
    </script>
</head>
<!--对 body设置 onload事件: 执行func1函数时,body里面所有的标签对象都已经加载完成了,所以func1可正常执行-->
<body onload="func1()">     <!--body加载完成,立马执行func1函数-->  
<p id="id1">hello p</p>
</body>
</html>
View Code

 (6)onkeydownonkeyuponkeypress

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" value="press" onkeydown="func1(event)" onkeyup="func2(event)">
<input type="button" value="press2" onkeypress="func3(event)">
<script>
    function func1(e){
        console.log(e.keyCode);    // 按键的数字编码
    }
    function func2(e){
        console.log(456);
    }
    function func3(e){
        console.log(789);
    }
</script>
</body>
</html>
View Code

3、事件传播

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--所谓事件传播,就是点击div2后,先alert出div2,还要再alert出div1-->
<div id="div1" style="background-color:green;width:300px;height:300px;">
    <div id="div2" style="background-color: red;width:200px;height:200px;"></div>
</div>

<script type="text/javascript">
    document.getElementById("div1").onclick=function(){
        alert('div1');
    };
    document.getElementById("div2").onclick=function(event){
        alert('div2');
        event.stopPropagation();    // 阻止事件向外层div传播.
    }
</script>
</body>
</html>
View Code

4、事件委托

$("要绑定的标签的上级").on("click", "要绑定的标签", function(){})

 好处:

1、省内存

2、子代可能还未出生,所以无法对其直接绑定事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table border="1px">
    <tbody id="tb">
    <tr>
        <td>111</td>
        <td class="del-row">删除</td>
    </tr>
    <tr>
        <td>222</td>
        <td class="del-row">删除</td>
    </tr>
    <tr>
        <td>333</td>
        <td class="del-row">删除</td>
    </tr>
    <tr>
        <td>444</td>
        <td class="del-row">删除</td>
    </tr>
    </tbody>

</table>

</body>
<script src="jquery-3.2.1.js"></script>
<script>

    /*将事件绑定在父辈或以上*/
    $("#tb").on("click", ".del-row", function(){
        $(this).parent().remove();
    })


</script>

</html>
View Code

5、补充

(1)this

可很方便的根据点击确定操作对象。两种事件绑定方法下this的使用:

a、在html标签上直接绑定事件时:要将this传给函数,函数中使用的this才是本标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="div" onclick="func1(this)">hello</div>           <!--将this作为实参传给函数-->
<div id="div" onclick="func2()">hello2</div>               <!--没有给函数传this参数-->
<script>

    function func1(arg){
        console.log(arg);                                 // 接收到的this代指的是本标签
        //打印的结果为:<div id="div" onclick="func1(this)">hello</div>
    }

    function func2(){
        console.log(this);                                // 直接在函数中调用this,this代指window
        //打印结果Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    }

</script>
</body>
</html>
View Code

b、在script代码中绑定事件时:直接在函数中用this即可,this代指本标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="div">hello</div>
<script>
 document.getElementById("div").onclick=function() {
     console.log(this);                // 直接使用this,this代指本标签
     // 打印结果为:<div id="div">hello</div>
 }
</script>
</body>
</html>
View Code

(2)用a标签做伪协议--类似于onclick事件触发

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--<a href="javascript:void(0)">hello</a>-->      <!--url不变,不同于加#-->
<a href="javascript:show()">hello</a>              <!--类似于onclick功能了。伪协议-->

<script>
    function show(){
        alert(123);
        return 66;
    }
</script>

</body>

</html>
View Code

 

三、做什么样的操作——对node对象的增删改

1、增加

createElement(ele_name);               // 先创建元素
parent_ele.appendChild(ele);           // 再将元素添加

2、删除

parent_ele.removeChild(ele);

3、更新

即替换,删除旧的,原位置再添加进一个新的。

parent_ele.replaceChild(ele2, ele1)    // ele2:新元素  ele1:待替换元素

4、修改

(1)修改元素的属性

ele.getAttribute(att);                // 查看ele元素的att属性,如:ele.getAttribute("id")
ele.setAttribute(att, value);         // 修改ele元素的att属性, value:对该属性的重新赋值

(2)修改元素的内容

ele.innerHTML=value;

(3)修改元素的样式

// 直接改
ele.style.fontsize="30px";

// 通过类的样式改
ele.className                         // 一个数组。ele属于哪些类(一般不同的类应用了不同的样式)
ele.classList.add(class_name)         // 在ele的class属性中,添加到一个名为class_name的新类
ele.classList.remove(class_name)      // 在els的class属性中,移除一个名为class_name的新类
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="div_1" style="background-color: green;width:200px;height:200px;">hello div1</div>
<div id="div_2" style="background-color: red;width:200px;height:200px;">hello div2</div>
<div id="div_3" style="background-color: dodgerblue;width:200px;height:200px;">hello div3</div>
<div id="div_4" style="background-color: yellow;width:200px;height:200px;">hello div4</div>
<input type="button" value="addNode" onclick="addNode()">
<input type="button" value="deleteNode" onclick="deleteNode()">
<input type="button" value="updateNode" onclick="updateNode()">
<input type="button" value="copyNode" onclick="copyNode()">


<script type="text/javascript">
    //添加:在第一个div中动态增加一个a标签. 该a标签点击之后跳转到百度首页.
    function addNode(){
        var div = document.getElementById("div_1");           // 1.获得 第一个div
        var eleA =  document.createElement("a");              // 2.创建a标签  createElement ==> <a></a>
        eleA.setAttribute("href", "http://www.baidu.com");    // 3.为a标签添加属性 <a href="http://www.baidu.com"></a>
        eleA.innerHTML = "百度";                              // 4.为a标签添加内容 <a href="http://www.baidu.com">百度</a>
        div.appendChild(eleA);                                // 5.将a标签添加到div中
    }

    //删除:删除第二个div
    function deleteNode(){

            var div = document.getElementById("div_2");       // 1.获得要删除的div区域
            var parent = div.parentNode;                      // 2.获得父亲
            parent.removeChild(div);                          // 3.由父亲操刀
    }

    //替换:替换第三个div为一个美女
    function updateNode(){
        var div = document.getElementById("div_3");           // 1.获得要替换的div区域3
        var img = document.createElement("img");              // 2.创建img标签对象<img/>
        img.setAttribute("src", "001.JPG");                   // 3.添加属性 <img src="001.jpg" />
        // img.src="001.jpg";                                 //   Dhtml html写法(动态html:增强html功能,即把繁杂的写法,用简单的写法表达)
        var parent = div.parentNode;                          // 4.获得父节点
        parent.replaceChild(img, div);                        // 5.替换
    }

    //克隆:将第四个div克隆一份,添加到页面底部
    function copyNode(){
        var div = document.getElementById("div_4");           // 1.获取要克隆的div
        var div_copy = div.cloneNode(true);                   // 2.克隆 参数为true 那么克隆时克隆所有子元素. false 只克隆自己
        var parent = div.parentNode;                          // 3.获得父亲
        parent.appendChild(div_copy);                         // 4.添加
    }
</script>
</body>
</html>
示例:1-4
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        .bigger{
            font-size: 30px;
            color: red;
        }

        .small{
            font-size: 10px;
            color: red;
        }
    </style>
</head>
<body>
<div id="div1">abscdk</div>
<input type="button" value="big" onclick="change('bigger')">
<input type="button" value="small" onclick="change('small')">



<script>
//    function changeBig(){
//        var ele=document.getElementById("div1");
//        ele.style.fontSize="30px";
//    }
//
//    function changeSmall(){
//        var ele=document.getElementById("div1");
//        ele.style.fontSize="15px";
//    }

    function change(a){
        var ele=document.getElementById("div1");
        ele.classList.remove('bigger');           // 初始化
        ele.classList.remove('small');            // 初始化
        ele.classList.add(a);
    }
</script>
</body>
</html>
示例:变大变小

 

应用实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            margin: 0;
        }

        #div1{
            position: fixed;
            height: 2000px;
            width: 100%;
            background-color: dodgerblue;
            z-index: 1000;
        }

        #div2{
            position: fixed;
            top: 0;
            left: 0;
            right:0;
            bottom:0;
            background-color: lightgray;
            opacity: 0.3;
            z-index: 1001;
        }

        #div3{
            position: absolute;
            top:50%;
            left:50%;
            height: 200px;
            width: 200px;
            background-color: yellow;
            z-index: 1002;
            margin-top:-100px;
            margin-left:-100px;
        }

        .hide{
            display: none;
        }
    </style>


</head>
<body>
<!--模块对话框应用场景:登录界面弹出时,背景变灰,登录完成后背景在变回来-->
<div id="div1">
    <input type="button" value="click" onclick="show()">
</div>
<div id="div2" class="div hide"></div>
<div id="div3" class="div hide">
    <input type="button" value="cancel" onclick="cancel()">
</div>


<script>
    function show(){
        var ele=document.getElementsByClassName("div");
        for (var i=0;i<ele.length;i++){
        ele[i].classList.remove("hide");
        }
    }

    function cancel(){
        var ele=document.getElementsByClassName("div");
        for (var i=0;i<ele.length;i++){
        ele[i].classList.add("hide");
        }
    }
</script>

</body>
</html>
模态对话框

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<select id="province" onchange="func1(this)"></select>
<select id="city"></select>

<script>
    data={"河北":["邯郸","廊坊"], "北京":["海淀","朝阳"], "山东":["济南", "青岛"]};

    // 动态生成一级
    for (var i in data){
        var pro=document.getElementById("province");
        var optionProvince=document.createElement("option");    // <option></option>
        optionProvince.innerHTML=i;                             // loop1:<option>河北省</option>
        pro.appendChild(optionProvince);
    }
    
    // 动态生成二级
    function func1(self){
        var city=document.getElementById("city");
        var choice=(self.options[self.selectedIndex]).innerHTML;    // 写法2:var choice=self.value;
        city.options.length=0;                                      // 先清空 city中的option
        for (i in data[choice]) {                                   // 再通过for循环往 city中加入值
            var optionCity = document.createElement("option");
            optionCity.innerHTML = data[choice][i];
            city.appendChild(optionCity);
        }
    }
</script>
</body>
</html>
省市二级菜单联动

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #box_L, #choice, #box_R{
            display: inline-block;
        }

    </style>
</head>
<body>
<div id="box_L">
    <select id="left" multiple size="10">
        <option>选项1</option>
        <option>选项2</option>
        <option>选项3</option>
        <option>选项4</option>
        <option>选项5</option>
        <option>选项6</option>
    </select>
</div>

<div id="choice">
    <input type="button" value="-->" onclick="add()"><br>
    <input type="button" value="==>" onclick="addAll()"><br>
    <input type="button" value="<--"><br>
    <input type="button" value="<=="><br>
</div>

<div id="box_R">
    <select id="right" multiple size="10">
    <option>选项7</option>
    </select>
</div>

<script>
    var right=document.getElementById("right");
    var left=document.getElementById("left");

    function add(){
        var options=left.children;
        for (var i=0;i<options.length;i=i+1){
            if (options[i].selected==true){
                right.appendChild(options[i]);    // 注意:option[i]并不是新创建的。等于从左边移到右边了
                i=i-1;                            // 因为left的options已经发生了变化,还是需要从第一个开始,否则会漏
            }
        }
    }

    function addAll(){
        var options=left.children;
        for (var i=0;i<options.length;i=i+1){
                right.appendChild(options[i]);
                i=i-1;
            }
    }
</script>
</body>
</html>
左右移动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="select('all');">全选</button>
<button onclick="select('cancel');">取消</button>
<button onclick="select('reverse');">反选</button>

<table border="1" id="Table">
    <tr>
         <td><input type="checkbox"></td>
         <td>111</td>
    </tr>
    <tr>
         <td><input type="checkbox"></td>
         <td>222</td>
    </tr>
    <tr>
         <td><input type="checkbox"></td>
         <td>333</td>
    </tr>
    <tr>
         <td><input type="checkbox"></td>
         <td>444</td>
    </tr>
</table>

<script>
    function select(choice){
        var ele=document.getElementById("Table");

        var inputs=ele.getElementsByTagName("input");
        for (var i=0;i<inputs.length;i=i+1){
            var ele2=inputs[i];
            if (choice=="all"){
                ele2.checked=true;
            }else if(choice=="cancel"){
                ele2.checked=false;
            }
            else {
                if (ele2.checked){
                    ele2.checked=false;
                }else {
                    ele2.checked=true;
                }
            }
         }
    }
</script>

</body>
</html>
全选反选取消

 

  

 

 参考:

http://www.cnblogs.com/yuanchenqi/articles/5980312.html

posted @ 2017-09-09 22:40  seaidler  阅读(125)  评论(0)    收藏  举报