前端(DOM、BOM和事件) 4

 


前言

        js包含ECMAScript、DOM、BOM。BOM(browser object model)浏览器对象模型,使js获得了操纵浏览器的能力。DOM(document object model)文档对象模型,使js获得了可以获取html内元素的能力。



一、DOM文档流

1.什么是DOM文档流

 DOM(文档对象模型)简单理解就是编写的html页面所有内容构成的树形结构。

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

  •  整个文档是一个文档节点。
  •  每个 HTML 元素是元素节点。
  •  HTML 元素内的文本是文本节点。
  •  每个 HTML 属性是属性节点。
  •  注释是注释节点。


2.  DOM = Document Object Model   DOM文档流

       dom对象 = 把标签封装成的对象
        document对象是js内置提供的对象(html文档对应的dom对象)
        Dom操作 = 可以用来处理页面文档内容的

 1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <meta charset="utf-8">
 5     <title>DMO</title>
 6     <script type="text/javascript">
 7       function tets(){
 8         console.log(document);
 9         console.log(a1)
10         var a1=document.getElementById("id_a")          // 通过id属性 来获取元素或标签(返回对拥有指定 id 的第一个对象的引用。)
11         var b1=document.getElementsByClassName("clsaa_a")   // 通过class属性来获取元素(返回文档中所有指定类名的元素集合,作为 NodeList 对象。)
12         var c1=document.getElementsByName("name_a")      // 通过name属性来获取元素(返回带有指定名称的对象集合。)
13         var d1=document.getElementsByTagName("tag_a")     // 通过tagname来获取元素(返回带有指定标签名的对象集合。)    
14       }
15       test()
16     </script>
17   </head>
18   <body>
19         DOM = Document Object Model   DOM文档流
20         dom对象 = 把标签封装成的对象
21         document对象是js内置提供的对象(html文档对应的dom对象)
22         Dom操作 = 可以用来处理页面文档内容的
23         innerText                   重点    从起始位置到终止位置的内容,但它去除Html标签
24         innerHTML                   重点    从对象的起始位置到终止位置的全部内容,包括Html标签。
25         getElementById               重点    通过id来获取元素或标签
26         getElementsByClassName       重点    通过class来获取元素或标签
27         getElementsByName           重点    通过name来获取元素或标签
28         getElementsByTagName        重点    通过标签name来获取元素或标签
29         value                        重点     取值和赋值
30         
31         <div id="id_a" class="class_a" name="name_a"> bbb </div> <!-- 先定义后使用 -->
32         <button onclick="test2()"> AAA</button>           <!-- 静态 事件绑定 =事件监听   -->
33         
34 
35         <script type="text/javascript">
36             function test2(){                  // 事件绑定 = 事件监听
37                 var dom3 =document.getElementById("id_a3");
38                 dom3.onclick = function(){alert("T-T")}   // 动态事件绑定 js
39                 dom3.onclick = null;               // 取消事件绑定
40                 dom3.addEventListener("click",function(){});// 标准使用格式 添加事件监听
41                 dom3.removeEventListener("click")       // 标准 去除事件监听
42             }
43             
44             function test1(){                  // 如何来操作
45                 var dom1 =document.getElementById("id_a1");
46                 dom1.innerText="asdasd"                     // 将内部文本调整为asdasd    // 必须要会
47                 dom1.innerHTML = "<input type='text' value='asdasd' />" // 必须要会
48                 Console.log(dom1.innerHTML)                  //取出文本内容必须要会
49                               // innerText(只能输出文本内容)
50                               // innerHTML(可以解析标签)
51                   
52                 dom1.value = "改变内容";                       // 改变标签的内容  复合属性  取值  赋值
53                 dom1.style.backgroundColor="salmon";             // 改变标签背景颜色
54             }
55         
56         
57             // function test(){                 // 如何来找
58                                            // 先定义后使用  放在33行之后 才能得到
59             //     var a1=document.getElementById("id_a")  // 通过id属性 来获去元素或标签
60             //     console.log(document);
61             //     console.log(a1)
62             //     var b1=document.getElementsByClassName("clsaa_a") // 得到数组
63             //     var c1=document.getElementsByName("name_a")     // 得到数组
64             //     var d1=document.getElementsByTagName("tag_a")   // 得到数组
65                 
66             // }
67             // test()
68         </script>
69         
70     </body>
71 </html>

 

重点: 

        innerText                              重点    从起始位置到终止位置的内容,但它去除Html标签
        innerHTML                           重点    从对象的起始位置到终止位置的全部内容,包括Html标签。
        getElementById                   重点    通过id来获取元素或标签
        getElementsByClassName  重点    通过class来获取元素或标签
        getElementsByName           重点    通过name来获取元素或标签
        getElementsByTagName     重点    通过标签name来获取元素或标签
        value                                    重点    取值和赋值 


3.关于DOM的小实例 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">
            var name = "aaa";
            var obj = {
                name : "bbb",
                getName:function(){ // object 
                    Console.log(this.name); // bbb
                    // fun =function(){ // 2 (分开写)
                    //     console.log(this.name); // 2 (分开写)
                    // } // 2 (分开写)
                    // return fun;  // 2 (分开写)
                     return function(){ 1(合起来)   // 没有使用var是全局方法    window
                         console.log(this.name); 1(合起来)
                     } 1(合起来)
                }
            };
            obj.getName()(); // 1、2  // 第一个 getName 对象  第二个 return 对象
            // (function(){  // 1、3
            //             console.log(this.name); // 1、3
            // })() // 1、3
        </script>
    </head>
    <body>
    </body>
</html>

 


 

4.DOM 改进:

 dom使js拥有了操纵html标签的能力。浏览器在创建页面的时候,会按照文档,元素,文本,属性,注释分类,形成了以html为根节点的树,那么这个树就叫做HTML DOM树。js可以通过dom获得标签进行操作,使js拥有了动态改变页面中所有元素,以及它们的属性和css样式能力。

  1 查找标签:

    1 直接查找:

document.getElementById document.getElementById('d1') 根据id获取一个标签
document.getElementBysClassName document.getElementBysClassName('c1') 根据class获取一组标签
document.getElementByTagName document.getElementByTagName('div') 根据标签名获取标签合集

 

 

 

    2 间接查找:

parentElement

父节点标签
children 所有子标签
firstElementChild 第一个子标签元素
lastElementChild 最后一个子标签元素
nextElementChild 下一个兄弟标签元素
previousElementSibling 上一个兄弟标签元素

 

 

      间接查找思路寻找一个中间标签,然后通过中间标签再去找想要找的标签

1
2
var a1Ele=document.getElementById("a1");
a1Ele.parentElement

 

  2 操纵节点(根据dom树来分): 

    1 创建元素节点:

1
2
3
4
5
6
7
var imgEle=document.createElement("img");
找到想要加入的元素
var d3Ele=document.getElementById("d3");
在d3Ele内加入imgEle标签
d3Ele.appendChild(imgEle)
设置imgEle的属性
imgEle.src=”图片地址”

    2 添加元素节点:

      1 追加一个子节点,相当于python中列表的append方法:

1
2
3
var imgEle=document.createElement("img");
var d3Ele=document.getElementById("d3");
d3Ele.appendChild(imgEle)

      2  在某个元素节点之前插入一个元素节点:

1
2
3
4
5
6
7
8
9
10
11
先查找想要插入标签的父标签
 var dEle=document.getElementById("cc1");
超找想要插入标签
  var dEle1=document.getElementById("d1");
创建想要被插入的标签
var spanEle1=document.createElement("span");
    插入
dEle.insertBefore(spanEle1,dEle1);
   给被插入标签赋值文本属性
spanEle1.innerText='span---123';
   Cc1 和 d1 为包含关系  使用insertBefor,在确定父标签和目标标签时最好使用id

    3 删除元素节点:

1
2
3
var dEle=document.getElementById("cc1");
Var sonEle=dEle.firstElementChild
dEle.removeChild(sonEle)

    4 替换元素节点:

1
2
在Ele内部用newnode替换oldnode
 Ele.replaceChild(newnode,oldnode)

    5 操纵属性节点:

setAttribute() d1Ele.setAttribute("age","18") 设置属性
getAttribute() d1Ele.getAttribute("age") 获取属性值
removeAttribute() d1Ele.removeAttribute('age') 删除属性

    6 操纵文本节点;

      1 获取文本节点的值;

1
2
3
4
5
6
var divEle = document.getElementById("d1");
 
获得标签以及子标签的全部内容(标签+文本内容)
divEle.innerHTML
获得标签以及子标签文本内容
divEle.innerText

      2 变更文本节点的值:

1
2
3
4
5
6
var divEle = document.getElementById("d1");
 
divEle文本中赋值,此时写入的字符串标签会被浏览器解释成标签来执行
divEle.innerHTML="<div>innerHTML</div>"
给innerText赋值
divEle.innerText="1111"

     7 获取值操作

 

var selEle=document.getElementById('s1');

select

selEle.value

"021"

var u1Ele=document.getElementById('u1');

Input typle=’text’

u1Ele.value

ddd

var u1Ele=document.getElementByname(‘sex’)

Input type=’radio’

 

 使用jquery获取值

var tEle=document.getElementById('t1');

Input type=‘’textarea‘’

tEle.values

ssss

        同样重新赋值可以采取一下方式

        selEle.value=1

      8 class节点操作:

className

Ele.className

获取标签下所有的class属性值

classList.remove(cls)

Ele.classList.remove(cls)

删除指定类

classList.add(cls)

Ele.classList.add(cls)

添加类

classList.contains(cls)

Ele. classList.contains(cls)

存在返回true否则返回false

classList.toggle(cls)

Ele.classList.toggle(cls)

存在就删除,否则添加 

        利用toggle操纵class,实现开关灯:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>class相关操作   开关灯</title>
    <style>
        .c1{
            height: 200px;
            width: 200px;
            border-radius: 50%;
            
        }
        .c2{
            
        }
        /*.c3{*/
        /*    */
        /*}*/
 
    </style>
</head>
<body>
<div class="c1 c2 c3" onclick="chan(this);">dfgdfgdf</div>
<div class="c1 c2 c3" >dfgdfgdf2222</div>
<div class="c1 c2 c3" >dfgdfgdf3333</div>
<div class="c1 c2 c3" >dfgdfgdf444444</div>
 
</body>
 
 
<script>
function chan(ths) {
    ths.classList.toggle('c2');
};
</script>
<script>
    var divEle=document.getElementsByTagName('div');
    for (var i=0;i<divEle.length;i++){
        //遍历返回的列表,给每个标签绑定一个事件
        divEle[i].onclick=function () {
            this.classList.toggle('c2')
 
        }
    }
 
</script>
</html>

        修改指定标签的class属性;

1
2
3
4
对于没有中横线的css属性,一般直接使用style就行
有中横线的css属性,中横线后的第一个字母大写
var divEles=document.getElementsByTagName('div')
divEles[0].style.backgroundColor="blue"

 

 

二、BOM

 1.window对象:

  window对象是客户端javascript的最高层对象之一,所有的浏览器都支持window对象,也可以粗暴的认为打开一个浏览器窗口或页面就是生成了一个window对象。所有js全局对象,函数以及变量均为windows的对象的组成元素。全局变量是window对象的属性,全局函数是window对象的方法,可以想想成python中的类,类中有静态属性和动态属性。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>bom</title>
    </head>
    <body>
        BOM = browser object model
        <script type="text/javascript">
            // 1- window(浏览器) // 最核心 最大  可省略
            // 2- window.location(浏览器的地址栏)  重要
            // 3- window.history (在浏览器窗口中)访问过的 URL。
            // 4- window.navigator  导航 包含有关浏览器的信息。
            // 5- window.screen      包含有关客户端显示屏幕的信息
            function test1(){
                window.alert("aaa")// 信息提示框
                confirm();// = window.confirm();  选择提示框 (是/否  确认/取消)
                var res = confirm("bbb");
                if(res){}
                var res1 = prompt("AA","BB");// 输入提示框  第二个"BB" 默认null
                window.open();// ifname       window 可省略
                var url = location.href;
                alert(url)
                location.href="http://www.baidu.com" // 页面跳转 (动态跳转) 
                location.href=location.href;// 重新加载当前网址
                location.reload(); // 等价于22行
                // location.protocol
                // location.hostname
                // location.port
                // location.pathname
                // history.back()// 回退
                // history.forward()// 前进
                // history.go(1)// 后一页
                // screen.height// 屏幕高度
                // screen.width// 屏幕宽度
                
                
                // document.cookie // 临时数据
                // localStorage // 本地存储数据
                // sessionStorage    // 会话存储数据
            }
        </script>
    </body>
</html>

 

2.计时器相关 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <div id="id_a"></div>
        <button onclick="start()">start</button>
        <button onclick="stop()">stop</button>
        <script type="text/javascript">
            // function setTime(){ // 定时任务的使用(定义在内部)
            //     setInterval(function(){
            //         var dom1 = document.getElementById("id_a");
            //         dom1.innerHTML =new Date().toLocaleString()
            //         console.log(new Date().toLocaleString());
            //     },1000); //每隔1000秒回调一次
            // }
            function setTime(){// 定时任务 (定义在外部 )
                var dom1 = document.getElementById("id_a");
                dom1.innerHTML =new Date().toLocaleString()
                
            }
            var x;
            function start(){
                x = setInterval(setTime,1000); // 设置时间间隔
                // x = setTimeout(setTime,1000); // 设置时间延迟
            }
            
            function stop(){ // 关闭定时器
                clearInterval(x) // 清除时间间隔
                // clearTimeout(x) // 清除时间延迟
            }
            
            
            // time计时器
            window.setInterval() // 设置时间间隔   固定时间执行
            window.clearInterval()// 清除时间间隔
            window.setTimeout()    // 设置时间延迟      指定时间执行一次
            window.clearTimeout() // 清除时间延迟
            
        </script>
    </body>
</html>

 


3. 改进BOM

 window对象:

  window对象是客户端javascript的最高层对象之一,所有的浏览器都支持window对象,也可以粗暴的认为打开一个浏览器窗口或页面就是生成了一个window对象。所有js全局对象,函数以及变量均为windows的对象的组成元素。全局变量是window对象的属性,全局函数是window对象的方法,可以想想成python中的类,类中有静态属性和动态属性。

window.innerHeight 浏览器窗口的内部高度
window.innerWidth 浏览器窗口的内部宽度
window.open() 打开新窗口
window.close() 关闭当前窗口

  window子对象:

location.href 获取当前页面url
location.href='url' 跳转url
location.reload() 刷新

  

  弹出框:

alert() 警告框
confirm() 确认框 返回true和false
prompt() 提示框 提示用户输入某个值,然后点击确认或取消按钮才能操作,如果点击确认,那么返回值就是填写的值,如果取消则为null

 

  计时相关:

    js中我们可以设定一个时间间隔来执行代码,而不是在函数在调用之后立即执行,我们称为计时时间

setTimeout()

var t=setTimeout(“alert(123)”,1000) 

等待1秒后执行,并且有返回值相当于计时事件的id
setInterval()

var t=setTimeout(“alert(123)”,5000) 

每5秒执行一次函数,并且有返回值相当于计时事件的id
clearTimeout()

clearTimeout(t)

取消setTimeout设置
clearInterval() clearInterval(t) 参数必须是setInterval的返回值

 

    以下是定时器的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>计时器</title>
</head>
<body>
<label for="i1">显示日期</label>
<input type="text" id="i1">
<input type="button" value="开始" id="start_button">
<input type="button" value="结束" id="stop_button">
 
 
<script>
    var t;
 
    var startEle=document.getElementById("start_button");
    var stopEle=document.getElementById("stop_button");
   function foo_time() {
       var new_time=new Date();
       var str_time=new_time.toLocaleString();
        var i1Ele=document.getElementById("i1");
       i1Ele.value=str_time;
 
   };
   startEle.onclick=function () {
       if (t===undefined) {
             foo_time();
      t= setInterval(foo_time,1000);
       }
 
   };
   stopEle.onclick=function () {
       clearTimeout(t);
       console.log('cleartimeout',t);
       t=undefined;
 
   }
 
</script>
</body>
</html>

三、事件

1.精点

                 onclick 单机  ondblclick 双击 
                 onfocus 获得焦点  onblur 失去焦点 (鼠标所在位置) 
                 onchange  一般在select标签中
                 onchange  onreset 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>事件</title>
    </head>
    <body>
        <!-- onclick 单机  ondblclick 双击 -->
        <!-- onfocus 获得焦点  onblur 失去焦点 (鼠标所在位置) -->
        <!-- onchange  一般在select标签中-->
        <!-- onchange  onreset -->
        
        <!-- 静态事件绑定 -->
        <!-- 动态事件绑定 -->
        
        <form onsubmit="test()" onreset="test()">
            <input type="submit"/>
            <input  type="reset"/>
        </form>
        
        <textarea onselect="test()" ></textarea>
        
        
        
        <select> <!-- 重要   级联(选定省 指定对应的市) -->
            <option onchange ="test()">aa</option>
            <option onchange ="test()">bb</option>
            <option onchange ="test()">cc</option>
        </select>
        <input type="text" onfocus="test()" />
        <script type="text/javascript">
            function test(){
                // alert(123)  
                var dom1 = document.getElementById("aa")
                var val  = dom1.value;
                var num = new Number
                
                
            }
        </script>
    </body>
</html>

 

2.级联 (经常用到)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
//省份的下拉菜单
 <select name="" id="sheng">
     <option value="0">-----请选择省-----</option>
     <option value="1">四川省</option>
     <option value="2">云南省</option>
     <option value="3">贵州省</option>
 </select>//城市的下拉菜单
<select name="" id="city">
    <option value="0">-----请选择市-----</option>
</select>
</body>
</html>
<script>
//获得省份对象
let shengObj=document.getElementById("sheng");
//获得城市对象
let cityObj=document.getElementById("city");
//给省份的下拉菜单绑定一个change事件
shengObj.onchange=()=>{
    if(shengObj.value==0){
        cityObj.innerHTML="<option value='0'>-----请选择城市------</option>";
    }else if(shengObj.value==1){
        cityObj.innerHTML="<option value='1'>成都市</option><option value='2'>绵阳市 </option><option value='3'>德阳市</option>";
    }else if(shengObj.value==2){
        cityObj.innerHTML="<option value='1'>昆明市</option><option value='2'>玉溪市    </option><option value='3'>大理市</option>";
    }else{
        cityObj.innerHTML="<option value='1'>遵义市</option><option value='2'>贵阳市</option><option value='3'>赤水市</option>";

     }
}


</script>

 

效果: 


​ 

​ 

四、 实例应用(小练习)

代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        
        <div id="">
            记录列表 <br><br>
            姓名<input type="text" /> 年龄 <input type="text" /> 
            <button onclick="testAdd()">添加</button><br><br>
            姓名<input type="text" />
            <button onclick="testSel()">搜索</button><br><br>
            <table style="border: 1px solid black; width: 600px;">
                <thead>
                    <tr>
                        <td>ID</td>
                        <td>姓名</td>
                        <td>年龄<td>
                        <td>操作</td>
                    </tr>
                </thead>    
                <tbody id='tbody'></tbody>
            </table>
        </div>
        <script type="text/javascript">
            // 1- 获取标签内容
            // 2- 将获得的内容整合成 tr + td
            // 3- 写回到网页当中(tabale)
            
            var inputs = document.getElementsByTagName("input");
            var ids = 1;
            // function testAdd1(){
            //     var name = inputs[0].value;
            //     var age = inputs[1].value;
            //     var oTr = document.createElement("tr");// <tr>
            //     var oTd = document.createElement("td");// <td>
            //     oTd.innerHTML = ids++;
            //     oTr.appendChild(oTd);
            //     var oTd = document.createElement("td");// <td>
            //     oTd.innerHTML = name;
            //     oTr.appendChild(oTd);
            //     var oTd = document.createElement("td");// <td>
            //     oTd.innerHTML = age;
            //     oTr.appendChild(oTd);
            //     var oTd = document.createElement("td");// <td>
            //     oTd.innerHTML = "<a href='javascript:'onclick = 'testDel(this)'> 删除</a>
            //             +    "&nbsp;<a href='javascript:' onclick = ''> 修改</a>";
            //     oTr.appendChild(oTd);
            //     document.getElementById("tbody").appendChild(oTr);
            // }
            function testAdd(){ // 添加
                var name = inputs[0].value;
                var age = inputs[1].value;
                    // <tr><td></td><td></td><td></td><td></td></tr>  字符串拼接
                var html = ""
                    +"<tr>"
                    +    "<td>" + (ids++) + "</td>"
                    +    "<td>" + name + "</td>"
                    +    "<td>" + age + "</td>"
                    +    "<td>" 
                    +        "<a href='javascript:'onclick = 'testDel(this)'> 删除</a>&nbsp"
                    +        "&nbsp;<a href='javascript:' onclick = 'testUpd(this)'> 修改</a>"
                    +     "</td>"
                    +"</tr>";
                    // console.log(html)
                var tbody = document.getElementById("tbody");
                tbody.innerHTML += html;
            }
            
            function testDel(obj){ // 删除            // removeChild
                if(confirm("是否删除该行记录?")){
                    var otr = obj.parentNode.parentNode;
                    document.getElementById("tbody").removeChild(otr);
                }
            }
            
            function testUpd(obj){ //修改
                // console.log(obj)
                var td_this = obj.parentNode;
                var td_age = td_this.previousSibling; // id唯一标识  //前一个
                var td_name = td_age.previousSibling;
                var td_id = td_name.previousSibling.innerHTML;
                
                td_age.innerHTML = "<input type='text' id='tAge"+td_id+"' value ='"+td_age.innerHTML+"' />";
                td_name.innerHTML = "<input type='text' id='tName"+td_id+"' value='"+td_name.innerHTML+"' />";
                td_this.innerHTML = "<a href='javascript:'>保存</a>"
                td_this.getElementsByTagName('a')[0].onclick=function(){
                    td_age.innerHTML = document.getElementById('tAge' + td_id).value;
                    td_name.innerHTML = document.getElementById('tName'+td_id).value;
                    td_this.innerHTML = "<a href='javascript:' onclick='testDel(this)'>删除</a>"
                    +      "&nbsp;&nbsp;<a href='javascript:' onclick='testUpd(this)'>修改</a>";
                }
            }
    
            function testSel(){
                var rows = document.getElementsByTagName("tr");
                var len = rows.length;
                for(var i = 1;i < len;i++){
                    rows[i].removeAttribute("style");
                }
                var name = inputs[2].value;
                if(name == '')
                    return;
                for(var i = 1;i < len;i++){
                    var td_name = rows[i].cells[1].innerHTML;
                    if(td_name.indexOf(name) > -1)
                        rows[i].style.backgroundColor = 'yellow'
                }
            }
        </script>
    </body>
    
</html>

 

展示: 


​ 

​ 


 

总结

        文档流是另一个概念,流实际上就是浏览器在页面上摆放Html元素所用的方法,大多数元素默认在文档流中。浏览器从Html文件最上面开始,从上到下沿着元素流逐个显示所遇到的各个元素。即:元素按HTML中编写的先后顺序,上下左右堆叠排列。其中块级元素前后换行,内联元素前后不换行。

        If not now, when? If not me, who? “时不我待,舍我其谁。”

        又是愉快的一天,加油!

posted @ 2021-12-24 00:25  小码成长日记  阅读(58)  评论(0)    收藏  举报