zoukankan      html  css  js  c++  java
  • js DOM(三)节点、元素创建3种方式、为元素绑定多个事件addEventListener、attachEvent

    录:

         1.节点的概念
         2.节点的属性(nodeType,nodeName,nodeValue)
         3.父节点(父元素)
         4.获取子节点或子元素
         5.获取节点、元素的方法(12行代码)
         6.案例:div标签里面的p标签背景高亮(使用子节点或子元素的方式)
         7.封装节点兼容代码
         8.案例:切换背景图片
         9.案例:全选、全不选
        10.元素创建的第一种方式  document.write("<p>文本</P>");
        11.元素创建的第二种方式 document.getElementById("divId").innerHTML="<p>新添加的文本</P>";
        12.案例:点击按钮,在div中加载一张图片
        13.案例:动态创建列表(元素创建的第二种方式)
        14.第三种元素创建方式  var pEle = document.createElement("p");
        15.案例:动态创建列表(使用第三种元素创建方式)
        16.动态创建表格(使用第三种元素创建方式)
        17.【操作元素的一些方法】
        18.点击按钮,创建元素(只创建一次)
        19.为元素绑定多个事件
        20.为元素绑定事件的兼容代码
        21.解绑事件的三种方式
        22.解绑事件的兼容代码
        23.事件冒泡、阻止事件冒泡
        24.事件的3个阶段
        25.为同一个元素绑定多个不同事件,事件使用同一个处理函数
        26.案例:模拟百度搜索

    1.节点的概念    <--返回目录
        * 文档:document
        * 元素:element,页面中所有的标签都是元素,标签--元素--对象
        * 节点:node,页面中所有的内容(标签、属性、文本)
        * 根元素:html这个标签

    2.节点的属性(nodeType,nodeName,nodeValue)    <--返回目录
        * 节点的属性:可以通过标签(属性或文本).点出来
        * 节点类型nodeType:1--标签,2--属性,3--文本
        * 节点名称nodeName:标签节点--大写的标签名字,属性节点--小写的属性名字,文本节点--#text
        * 节点的值nodeValue:标签节点--null,属性节点--属性值,文本节点--文本内容

    3.父节点(父元素)    <--返回目录
        * 只有标签可以作为父节点(父元素)
            - 获取所有的父节点   ele.parentNode;
            - 获取所有的父元素   ele.parentElement;

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <div id="box">
        div里面的文本
        <p>p里面的文本</p>
    </div>
    <script type="text/javascript">
        var pEle = document.getElementById("box").getElementsByTagName("p")[0];
        console.log(pEle.parentNode);//[object HTMLDivElement]---说明父节点是标签
        console.log(pEle.parentElement);//[object HTMLDivElement]---说明父元素是标签
    
        var parentEle= pEle.parentNode;  //获取父标签
        console.log(parentEle.nodeType);  //1--标签类型
        console.log(parentEle.nodeName);  //DIV--标签名字
        console.log(parentEle.nodeValue);  //null--标签的值
    </script>
    </body>
    </html>

    4.获取子节点或子元素    <--返回目录
        * 获取所有的子节点  ele.childNodes;
        * 获取所有的子元素(子标签)  ele.children;

      【获取子节点或子元素】

    <div id="box">
        div里面的文本
        <p>p里面的文本</p>
        <a href=""></a>
    </div>
    <script type="text/javascript">
        var divEle = document.getElementById("box");
        console.log(divEle.childNodes);//子节点NodeList(5) [ #text, p, #text, a, #text ]
        console.log(divEle.children);//子元素HTMLCollection [ p, a ]
    </script>

      代码:【获取子节点】

    <div id="box">
        div里面的文本
        <p>p里面的文本</p>
        <a href="">a标签里面的文本</a>
    </div>
    <script type="text/javascript">
        var divEle = document.getElementById("box");
        var _childNodes = divEle.childNodes;//子节点NodeList(5) [ #text, p, #text, a, #text ]
        for(var i=0;i<_childNodes.length;i++){
            console.log(_childNodes[i].nodeType+"---"+_childNodes[i].nodeName+"---"+_childNodes[i].nodeValue);
        }
    </script>

      结果:
            3---#text---div里面的文本
            1---P---null
            3---#text---
            1---A---null
            3---#text---

      【根据属性名字获取属性节点】

    <script type="text/javascript">
        var ele = document.getElementById("txt");
        var attNode = ele.getAttributeNode("name");
        console.log(attNode);//属性节点name="username"
        alert(attNode);//属性节点[object Attr]
        console.log(attNode.nodeType+"---"+attNode.nodeName+"---"+attNode.nodeValue);//2---name---username
    </script>

    5.获取节点、元素的方法(12行代码)    <--返回目录
        * 总结:凡是获取节点的代码在谷歌和火狐得到的都是节点,凡是获取元素的代码在谷歌和火狐总都是元素;
          除父(子)节点/元素,凡是获取节点的代码在IE8中得到的是元素,获取元素的代码不支持。

    //父节点
    ele.parentNode;
    //父元素
    ele.parentElement;
    //子节点
    ele.childNodes;
    //子元素
    ele.children;
    //第一个子节点
    ele.firstChild;
    //第一个子元素
    ele.firstElementChild
    //最后一个子节点
    ele.lastChild;
    //最后一个子元素
    ele.lastElementChild;
    //某个元素的前一个兄弟节点
    ele.previousSibling;
    //某个元素的前一个兄弟元素
    ele.previousElementSibling;
    //某个元素的后一个兄弟节点
    ele.nextSibling;
    //某个元素的后一个兄弟元素
    ele.nextElementSibling;

    6.案例:div标签里面的p标签背景高亮(使用子节点或子元素的方式)    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <input type="button" value="变色">
    <div style="300px;border:2px solid blue">
        <span>这是span内的文本1</span>
        <p>这是p内的文本1</p>
        <span>这是span内的文本2</span>
        <p>这是p内的文本2</p>
    </div>
    <script type="text/javascript">
        var divEle = document.getElementsByTagName("div")[0];
        document.getElementsByTagName("input")[0].onclick=function(){
            var eles = divEle.children;//获取div标签里面所有的子标签
            //遍历所有的子标签,并判断是否是p标签
            for(var i=0;i<eles.length;i++){
                if(eles[i].nodeType===1 && eles[i].nodeName==="P"){
                    eles[i].style.backgroundColor="red";
                }
            }
        };
    </script>
    </body>
    </html>

    7.封装节点兼容代码    <--返回目录
      获取任意一个父元素的第一个子元素

    function getfirstEleChild(ele){
        //if(typeof ele.firstElementChild != "undefined"){
        if(ele.firstElementChild){  //ele.firstElementChild有值就为true
            return ele.firstElementChild;
        }else{
            var node = ele.firstChild;
            while(node && node.nodeType !=1){
                node=node.nextSibling;
            }
            return node;
        }
    }

      获取任意一个父元素的最后一个子元素

    function getlastEleChild(ele){
        if(ele.lastElementChild){  //ele.lastElementChild有值就为true
            return ele.lastElementChild;
        }else{
            var node = ele.lastChild;
            while(node && node.nodeType !=1){
                node=node.previousSibling;
            }
            return node;
        }
    }

    8.案例:切换背景图片    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
        <style type="text/css">
            img{
                150px;
            }
            div{
                 700px;
                margin: 0 auto;
            }
            body {
                background:url("images/1.jpg");/*设置背景图片*/
            }
        </style>
    </head>
    <body>
    <div id="box">
        <img src="images/1.jpg">
        <img src="images/2.jpg">
        <img src="images/3.jpg">
        <img src="images/4.jpg">
    </div>
    
    <script type="text/javascript">
        var eles = document.getElementById("box").children;
        for(var i=0;i<eles.length;i++){
            eles[i].onclick=function(){
                console.log(this.src);//file:///C:/Users/oy/Desktop/images/2.jpg
                document.body.style.background="url("+this.src+")";
                console.log("url("+this.src+")");//url(file:///C:/Users/oy/Desktop/images/2.jpg)
            };
        }
    </script>
    </body>
    </html>

    9.案例:全选、全不选    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <table align="center" width="30%" cellspacing="0" border="1" bgcolor="#eee">
        <tr >
            <th><input type="checkbox" id="checkboxId"></th>
            <th>菜名</th>
            <th>饭店</th>
        </tr>
        <tbody>
            <tr align="center">
                <td><input type="checkbox" name=""></td>
                <td>aa</td>
                <td>aa</td>
            </tr >
            <tr align="center">
                <td><input type="checkbox" name=""></td>
                <td>aa</td>
                <td>aa</td>
            </tr>
            <tr align="center">
                <td><input type="checkbox" name=""></td>
                <td>aa</td>
                <td>aa</td>
            </tr>
        </tbody>
    </table>
    <script type="text/javascript">
        var checkboxEle = document.getElementById("checkboxId");
        var eles = document.getElementsByTagName("input");
        //为第一个checkbox注册点击事件
        checkboxEle.onclick=function(){
            //如果第一个checkbox选中,则全部选中; 否则,全部取消选中
            for(var i=0;i<eles.length;i++){
                eles[i].checked=this.checked;
            }
        };
        //为后面3个checkbox注册点击事件
        for(var j=1;j<eles.length;j++){
            eles[j].onclick=function(){
                //判断后面3个checkbox的状态,如果都被选中,则将第一个checkbox也选中
                var count=0;//计数器,用于保存选中的checkbox的个数
                for(var k=1;k<eles.length;k++){
                    if(eles[k].checked){
                        count++;
                    }
                }
                //如果计数器count=3,说明后面3个checkbox都被选中了,则将第一个checkbox也选中
                //如果计数器count<3,则将第一个checkbox去掉选中
                console.log(`count = ${count}`)
                if(count == 3){
                    checkboxEle.checked=true;
                }else if(count<3){
                    checkboxEle.checked=false;
                }
            };
        }
    </script>
    </body>
    </html>

    10.元素创建的第一种方式    <--返回目录
      document.write("<p>文本</P>");
            - 如果是页面加载完毕后,通过该种方式创建元素,页面之前的所有内容被清空
            - 如果是页面加载的时候,通过该种方式创建元素,页面之前的所有内容被保留

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    
    <script type="text/javascript">
    var ele = document.getElementById("btn");
    ele.onclick=function(){
        document.write("<p>文本</P>");//该句代码是在点击按钮后执行,此时页面已经加载完毕,页面之前的所有内容被清空
    };
    document.write("<p>文本</P>");//页面加载的时候,通过该种方式创建元素,页面之前的所有内容被保留
    </script>
    </body>
    </html>

    11.元素创建的第二种方式    <--返回目录
      document.getElementById("divId").innerHTML="<p>新添加的文本</P>";

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    <div id="divId" style=" 300px;height: 200px;border:2px solid pink">div原来的文本</div>
    
    <script type="text/javascript">
    var ele = document.getElementById("btn");
    ele.onclick=function(){
        document.getElementById("divId").innerHTML="<p>新添加的文本</P>";//将原来的文本覆盖了
    };
    </script>
    </body>
    </html>

    12.案例:点击按钮,在div中加载一张图片    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>    
        <style type="text/css">
            img{
                 300px;
                height:300px;
            }
        </style>    
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    <div id="divId" style="300px; height:300px; border:2px solid pink">div原来的文本</div>
    
    <script type="text/javascript">
    var ele = document.getElementById("btn");
    ele.onclick=function(){
        //点击按钮,在div中加载一张图片,加载的图片也会应用已经定义的样式
        document.getElementById("divId").innerHTML="<img src='a.jpg'/>";
    };
    </script>
    </body>
    </html>

    13.案例:动态创建列表(元素创建的第二种方式)    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>    
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
        </style>    
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    <div id="divId" style=" 300px;height: 300px;border:2px solid pink">div原来的文本</div>
    <script type="text/javascript">
        var names = ["西施","杨玉环","貂蝉","王昭君"];
        var ele = document.getElementById("btn");
        ele.onclick=function(){
            var str = "<ul style='list-style-type:none;cursor:pointer'>";
            for(var i=0;i<names.length;i++){
                str += "<li>"+names[i]+"</li>";
            }
            str += "</ul>";
            document.getElementById("divId").innerHTML=str;
        };
    </script>
    </body>
    </html>

    14.第三种元素创建方式    <--返回目录
      var pEle = document.createElement("p");

    <input type="button" id="btn" value="按钮" />
    <div id="divId" style=" 300px;height: 300px;border:2px solid pink">div原来的文本</div>
    <script type="text/javascript">
        document.getElementById("btn").onclick=function(){
            var pEle = document.createElement("p");
            pEle.innerText="这是p标签里面的文本";
            document.getElementById("divId").appendChild(pEle);//在后面追加
        };
    </script>

    15.案例:动态创建列表(使用第三种元素创建方式)    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>    
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
        </style>    
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    <div id="divId" style=" 300px;height: 300px;border:2px solid pink">div原来的文本</div>
    <script type="text/javascript">
        var names = ["a","b","c"];
        document.getElementById("btn").onclick=function(){
            var parent = document.getElementById("divId");
            var ulNode = document.createElement("ul");
            parent.appendChild(ulNode);
    
            for(var i=0;i<names.length;i++){
                var node = document.createElement("li");
                node.innerText=names[i];
                ulNode.appendChild(node);
                node.onmouseover = mouseoverHandler;
                node.onmouseout = mouseoutHandler;
            }
        };
        var mouseoverHandler = function (){
            this.style.backgroundColor = "#ccc";
        };
        var mouseoutHandler = function (){
            this.style.backgroundColor = "";
        };
    </script>
    </body>
    </html>

    16.动态创建表格(使用第三种元素创建方式)    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>        
    </head>
    <body>
    <input type="button" id="btn" value="按钮" />
    <div id="divId" style=" 300px;height: 300px;border:2px solid pink">div原来的文本</div>
    <script type="text/javascript">
        var names = [
            {"name":"百度","href":"http://www.baidu.com"},
            {"name":"谷歌","href":"http://www.google.com"},
        ];
        document.getElementById("btn").onclick=function(){
            //创建table元素,并添加到div元素下
            var parent = document.getElementById("divId");
            var table = document.createElement("table");
            table.border = "1";
    
            parent.appendChild(table);
            for(var i=0;i<names.length;i++){
                var node = names[i];
                //创建tr元素,并添加到table元素下
                var tr = document.createElement("tr");
                table.appendChild(tr);
                //创建第一列,并添加到tr下
                var td = document.createElement("td");
                td.innerText = node.name;
                tr.appendChild(td);
                //创建第二列,并添加到tr下
                var td = document.createElement("td");
                td.innerHTML = "<a href="+node.href+">"+node.name+"</a>";
                tr.appendChild(td);
            }
        };
    </script>
    </body>
    </html>

    17.操作元素的一些方法    <--返回目录
        * parentEle.appendChild(node);//追加子元素
        * parentEle.insertBefore(newChild,refChild);//在指定的元素refEle之前插入newEle
          parentEle.insertBefore(newChild,parentEle.firstElementChild);//在div里面最前面插入newEle

        * parentEle.replaceChild(newChild,refChild);//替换
        * parentEle.removeChild(parentEle.firstElementChild);//删除第一个子元素
        * 删除所有子元素
            while(parentEle.firstElementChild){
                parentEle.removeChild(parentEle.firstElementChild);//删除第一个子元素
            }

    18.点击按钮,创建元素(只创建一次)    <--返回目录
        * 有则删除,无则创建,即创建之前先判断是否存在,存在删除,然后创建
        * 或者,创建之前先判断是否存在,存在就什么也不做,不存在就创建。

    19.为元素绑定多个事件    <--返回目录
        * ele.addEventListener(type,listener,useCapture);//可以为同一个元素绑定多个相同的事件,谷歌火狐都支持,IE8不支持
            - 参数一:{string}type 事件的类型,没有on前缀
            - 参数二:{Function}listener 事件处理函数
            - 参数三:{boolean}useCapture 目前就写false,不解释

        * ele.attachEvent("onclick",fn);谷歌火狐不支持,IE8支持

     * 区别
      addEventListener 谷歌、火狐、IE11支持,IE8不支持
      attachEvent 谷歌、火狐不支持,IE11不支持,IE8支持

    ele.addEventListener("click", function(){
        console.log(this); // this为ele这个对象
    }, false);
    ele.attachEvent("onclick", function(){
        console.log(this); // this为window这个对象
    });

    20.为元素绑定事件的兼容代码    <--返回目录
      为任意元素,绑定任意的事件,事件处理函数

    function addEventListener(ele,type,fn){
        //判断浏览器是否支持这个方法
        if(ele.addEventListener){
            ele.addEventListener(type,fn,false);
        }else if(ele.attachEvent){
            ele.attachEvent("on"+type,fn);
        }else{
            ele["on"+type]=fn;
        }
    }

    21.解绑事件的三种方式    <--返回目录

      第一种:ele.onclick=null;

      注意:用什么方式绑定事件,就应该用对应的方式解绑事件

    <input type="button" id="btn" value="按钮" />
    <input type="button" id="btn2" value="解绑事件" />
    <script type="text/javascript">
        document.getElementById("btn").onclick=function(){
            alert(1);
        };
        document.getElementById("btn2").onclick=function(){
            document.getElementById("btn").onclick=null;
        };
    </script>

      第二种:ele.removeEventListener("click",命名函数的名字,false);

      IE8不支持addEventListener和removeEventListener

    <input type="button" id="btn" value="按钮" />
    <input type="button" id="btn2" value="解绑事件" />
    <script type="text/javascript">
        var ele = document.getElementById("btn");
        ele.addEventListener("click",f1,false);
        ele.addEventListener("click",f2,false);
    
        //移除第二个绑定事件
        document.getElementById("btn2").onclick=function(){
            ele.removeEventListener("click",f1,false);
        };
        function f1(){
            console.log(1);
        }
        function f2(){
            console.log(2);
        }
    </script>

      第三种:
      谷歌、火狐不支持,IE8支持

    <input type="button" id="btn" value="按钮" />
    <input type="button" id="btn2" value="解绑事件" />
    <script type="text/javascript">
        var ele = document.getElementById("btn");
        ele.attachEvent("onclick",f1,false);
        ele.attachEvent("onclick",f2,false);
    
        //移除第二个绑定事件
        document.getElementById("btn2").onclick=function(){
            ele.detachEvent("onclick",f1);
        };
        function f1(){
            console.log(1);
        }
        function f2(){
            console.log(2);
        }
    </script>

    22.解绑事件的兼容代码    <--返回目录

    //为任意的一个元素解绑任意事件、任意响应函数
    function removeEventListener(ele,type,fnName){
        if(ele.removeEventListener){
            ele.removeEventListener(type,fnName,false);
        }else if(ele.detachEvent){
            ele.detachEvent("on"+type,fnName);
        }else{
            ele["on"+type]=null;
        }
    }

      注意:以后,一般都使用兼容代码,不使用ele.onclick=null;为了以防多个人给同一个元素绑定了相同的事件

    23.事件冒泡、阻止事件冒泡    <--返回目录
        * 事件冒泡:多个元素嵌套,这些元素都绑定了相同的事件,如果里面的元素的事件触发了,外面的元素的事件也自动触发。
        
        * 阻止事件冒泡:
            - window.event.cancelBubble = true; // IE特有的,谷歌支持,火狐不支持
            - e.stopPropagation(); // 谷歌火狐支持,IE不支持

    24.事件的3个阶段    <--返回目录
        * 事件捕获阶段:从外向里
        * 事件目标阶段
        * 事件冒泡阶段:从里向外
        
        * addEventListener(,,false|true)
            - false:从目标阶段开始,从里向外冒泡
            - true:从外到里开始捕获,直到目标阶段【直到捕获事件的触发目标】
            - 一般默认使用false,很少用true

    25.为同一个元素绑定多个不同事件,事件使用同一个处理函数    <--返回目录

    <input type="button" id="btn" value="按钮" />
    <script type="text/javascript">
        var ele = document.getElementById("btn");
        ele.onclick = fun;
        ele.onmouseover = fun;
        ele.onmouseout = fun;
        function fun(e){
            switch(e.type){
                case "click":
                    console.log("鼠标点击事件");
                    break;
                case "mouseover":
                    console.log("鼠标进入事件");
                    break;
                case "mouseout":
                    console.log("鼠标离开事件");
                    break;
            }
        }
    </script>

    26.案例:模拟百度搜索    <--返回目录

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>标题</title>    
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            ul{
                list-style-type: none;
            }
        </style>    
    </head>
    <body>
    <div>
        <input type="text" id="txt" style=" 200px;"/>
        <input type="button" id="btn" value="搜索"/>
        <div id="divId" style=" 200px;display: none;border: 1px solid #ccc"></div>    
    </div>
    <script type="text/javascript">
        var keywords = ["我爱你","我喜欢你","我不喜欢你"];
        var txtEle = document.getElementById("txt");
        txtEle.onkeyup = function() {
            //获取文本框输入的内容
            var text = this.value;
            var tempArr = [];//用于存放匹配上的数据
            //把文本框输入的内容与数组中的数据进行对比,匹配上的数据添加到tempArr中
            for(var i=0;i<keywords.length;i++){
                console.log(text.length);
                if(text.length>0 && keywords[i].indexOf(text)==0){
                    tempArr.push(keywords[i]);//追加
                }
            }
            console.log(tempArr);
    
            var div = document.getElementById("divId");
            //如果tempArr中有数据,创建列表
            if(tempArr.length>0){
                //先清空div中内容
                while(div.firstElementChild){
                    div.removeChild(div.firstElementChild);//删除第一个子元素
                }
                var ul = document.createElement("ul");
                div.appendChild(ul);
                //根据tempArr的数据创建列表,添加到div中
                for(var j=0;j<tempArr.length;j++){
                    var li = document.createElement("li");
                    li.innerText = tempArr[j];
                    ul.appendChild(li);
    
                    //为li标签添加鼠标进入和移出事件
                    li.onmouseover = function(){
                        this.style.backgroundColor = "#888";
                    };
                    li.onmouseout = function(){
                        this.style.backgroundColor = "";
                    };
                    //为li标签添加鼠标点击事件
                    li.onclick = function(){
                        //将li标签内的文本添加到输入框中
                        txtEle.value = this.innerText;
                        //将div隐藏
                        div.style.display = "none";
                    };
                }
                //使得div显示
                div.style.display = "block";
            }else{
                div.style.display = "none";
            }
        }
    </script>
    </body>
    </html>

    ---

  • 相关阅读:
    SVM学习笔记-线性支撑向量机
    阿里面试回来,想和Java程序员谈一谈
    看外国女程序员如何直播写代码
    shoeBox超实用的雪碧图(Sprite)图制作工具-使用
    Android图像处理之图形特效处理
    SMP、NUMA、MPP体系结构介绍
    TIOBE 2017 8月编程语言排行榜 后院“硝烟四起”
    Android Studio中Git和GitHub使用详解
    矩阵乘法快速幂 codevs 1574 广义斐波那契数列
    矩阵乘法 codevs 1287 矩阵乘法
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12185293.html
Copyright © 2011-2022 走看看