前端面試題

記錄和匯總看到的和碰到的前端面試題
主要來(lái)源:

https://github.com/Advanced-Frontend/Daily-Interview-Question

https://github.com/ltadpoles/web-document/tree/master/Other

HTML + CSS 篇

Q1、 常用的行內(nèi)元素、塊級(jí)元素、空元素分別有哪些?

1. 塊級(jí)元素:div  ul  ol  li h1~h6  p table 等
2. 行內(nèi)元素: a  span   img  input  select 等
3. 空元素: br  hr  link等

Q2、HTML語(yǔ)義化的理解

簡(jiǎn)單來(lái)說(shuō),就是合適的標(biāo)簽做合適的事情
具體的好處有:
- 有助于構(gòu)建良好的HTML結(jié)構(gòu),有利于搜索引擎的建立索引、抓取,利于SEO
- 有利于不同設(shè)備的解析 
- 有利于團(tuán)隊(duì)的開(kāi)發(fā)、維護(hù)

Q3、 常見(jiàn)的瀏覽器內(nèi)核及理解

  • Trident 內(nèi)核: IE
  • Gecko內(nèi)核: NETSCAPE6及以上版本,火狐
  • Presto內(nèi)核:Opera7及以上 [ Opera內(nèi)核原為:Presto, 現(xiàn)為:Blink ]
  • Webkit內(nèi)核:Safari、Chrome等 [ Chrome:Blink(Webkit的分支) ]
    瀏覽器內(nèi)核又可以分為兩部分:渲染引擎和JS引擎。<br />
    渲染引擎主要負(fù)責(zé)取得頁(yè)面的內(nèi)容、整理訊息、計(jì)算網(wǎng)頁(yè)的顯示方式等;<br />
    JS引擎則是解析JavaScript語(yǔ)言,執(zhí)行Javascript語(yǔ)言來(lái)實(shí)現(xiàn)網(wǎng)頁(yè)的動(dòng)態(tài)效果。

Q4、src 與 href 的區(qū)別

區(qū)別在于 src用于替代這個(gè)元素,而href用于建立這個(gè)標(biāo)簽與外部資源之間的關(guān)系。<br />
<link href="style.css" rel="stylesheet" />瀏覽器加載到這里的時(shí)候,html的渲染和解析不會(huì)暫停,css文件的加載是同時(shí)進(jìn)行的 <br />
<script src="script.js"></script>當(dāng)瀏覽器解析到這句時(shí),頁(yè)面的加載和解析會(huì)暫停直到瀏覽器拿到和執(zhí)行完這個(gè)JS文件。


Q5、CSS中l(wèi)ink 和 import 的區(qū)別

link屬于XHTML標(biāo)簽,而@import完全是CSS提供的另一種方式,只能加載CSS<br />
加載順序不同:當(dāng)一個(gè)頁(yè)面被加載時(shí),link引用的css會(huì)被同時(shí)加載,而import引用的css會(huì)等到頁(yè)面全部被下載完再被加載<br />
兼容性的區(qū)別:由于import時(shí)CSS2.1提出的所以老的瀏覽器不支持,而link標(biāo)簽無(wú)此問(wèn)題<br />
當(dāng)使用JavaScript控制DOM去改變樣式時(shí),只能用link標(biāo)簽,因?yàn)锧import不是dom可以控制的


Q6、CSS部分優(yōu)化、提高性能的方法有哪些?

  • 移除空的css規(guī)則
  • 正確使用display屬性
  • 不濫用浮動(dòng)、web字體
  • 不聲明過(guò)多的font-size
  • 不在選擇器中使用ID標(biāo)識(shí)符
  • 遵守盒模型規(guī)則
  • 盡量減少頁(yè)面重排、重繪
  • 提取公共樣式,減少代碼量

Q7、清除浮動(dòng)的方式

浮動(dòng)的元素是脫離文檔標(biāo)準(zhǔn)流的,如果不清除浮動(dòng),就會(huì)造成父元素高度塌陷,影響頁(yè)面布局
清除浮動(dòng)的方式有:

  • 為父元素設(shè)置高度
  • 為父元素設(shè)置overflow: hidden
  • 偽元素
.father::after {
    content: "";
    display: block;
    clear: both;
}

注:

  1. 使用偽元素的好處:不增加冗余的DOM節(jié)點(diǎn),符合語(yǔ)義化
  2. overflow: hidden; 可以觸發(fā)BFC機(jī)制

Q8、介紹BFC及其應(yīng)用

BFC就是塊級(jí)格式上下文,是頁(yè)面盒模型布局中的一種CSS渲染模式,創(chuàng)建了BFC的元素就相當(dāng)于一個(gè)獨(dú)立的盒子,它規(guī)定了內(nèi)部如何布局,里面的元素和外面的元素互不影響。 計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算。

BFC的特性:

  1. 內(nèi)部box會(huì)在垂直方向上,一個(gè)接一個(gè)的放置
  2. Box垂直方向的距離由margin決定,在一個(gè)BFC中,兩個(gè)相鄰的塊級(jí)元素的垂直外邊距會(huì)產(chǎn)生重疊
  3. 在BFC中,每個(gè)盒子的左外邊緣(margin-left)會(huì)觸碰到容器的左邊緣(border-left)(對(duì)于從右到左的格式來(lái)說(shuō),則觸碰到右邊緣)
  4. 形成了BFC的區(qū)域不會(huì)與float box 重疊
  5. 計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算

創(chuàng)建BFC的方式有:

  1. html根元素
  2. float
  3. 絕對(duì)定位
  4. overflow 不為visiable
  5. display為表格布局或彈性布局

BFC主要的作用:

  1. 清除浮動(dòng)
  2. 防止同一BFC容器中的相鄰元素之間的外邊距重疊的問(wèn)題

Q9、BFC、IFC、GFC 和 FFC

BFC( Block Formatting Contexts ):塊級(jí)格式上下文
頁(yè)面上的一個(gè)隔離的渲染區(qū)域,可觸發(fā)BFC的元素有:float、position、overflow、display: table-cell;/inline-block; 作用有實(shí)現(xiàn)多欄布局等;

IFC(Inline Formatting Contexts):內(nèi)聯(lián)格式上下文
IFC的line box(線框)高度由其包含行內(nèi)元素中最高的實(shí)際高度計(jì)算而來(lái)(不受到豎直方向的padding和margin影響), IFC中的line box 一般左右都貼緊整個(gè)IFC,但是會(huì)因?yàn)閒loat元素而打亂。float元素會(huì)位于IFC 與 line box 之間,使得line box 寬度縮小。同時(shí),IFC下的多個(gè)line box 高度會(huì)不同,IFC中是不可能有塊級(jí)元素的,當(dāng)插入塊級(jí)元素時(shí),會(huì)產(chǎn)生兩個(gè)匿名塊與div隔開(kāi)(即產(chǎn)生兩個(gè)IFC,每個(gè)IFC對(duì)外表現(xiàn)為塊級(jí)元素,與div垂直排列)。作用一般有:水平居中:當(dāng)一個(gè)塊要在環(huán)境中水平居中時(shí),設(shè)置其為inline-block 則會(huì)在外層產(chǎn)生IFC,通過(guò)text-align則可以使其水平居中。垂直居中:創(chuàng)建一個(gè)IFC,用其中一個(gè)元素?fù)伍_(kāi)父元素的高度,然后設(shè)置其vertical-align: middle; 其他行內(nèi)元素就可以在此父元素下垂直居中。

GFC (GridLayout Formatting Contexts):網(wǎng)格化布局格式上下文
當(dāng)為一個(gè)元素設(shè)置display: grid; 的時(shí)候,此元素將會(huì)獲得一個(gè)獨(dú)立的渲染區(qū)域,我們可以通過(guò)在網(wǎng)格容器(grid container)上定義網(wǎng)格定義行(grid definition rows)和網(wǎng)格定義列(grid definition columns)屬性和在網(wǎng)格項(xiàng)目(grid item)上定義網(wǎng)格行(grid rows)和網(wǎng)格列(grid columns)為每一個(gè)網(wǎng)格項(xiàng)目定義位置和空間。與table同為二維的表格,GridLayout會(huì)有更加豐富的屬性來(lái)控制行和列,控制對(duì)齊以及更為精細(xì)的渲染語(yǔ)義和控制。、

FFC (Flex Formatting Contexts):自適應(yīng)格式上下文
diaplay為 flex 或 inline-flex 的元素將會(huì)生成自適應(yīng)容器(flex container),可惜這個(gè)屬性只有谷歌和火狐支持(移動(dòng)端夠用了)。Flex Box 由伸縮容器和伸縮項(xiàng)目組成。通過(guò)設(shè)置元素的display為flex 或 inline-flex 就可以得到一個(gè)伸縮容器。設(shè)置為flex的容器被渲染成一個(gè)塊級(jí)元素,而設(shè)置inline-box的元素被渲染成一個(gè)行內(nèi)元素。伸縮容器中的每一個(gè)子元素都是一個(gè)伸縮項(xiàng)目。伸縮項(xiàng)目可以是任意數(shù)量的。伸縮容器內(nèi)外元素互不影響。簡(jiǎn)單的說(shuō)就是,F(xiàn)lex Box 定義了伸縮容器里的伸縮項(xiàng)目怎么布局。


Q10、怎么讓不定寬高的DIV水平垂直居中

<div class="parent">
    <div class="child"></div>
</div>
  1. 定位的方式
.parent {
    position: relative;
}
.child {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}
  1. CSS3屬性
.parent {
    position: relative;
}
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
  1. flex 布局
.parent {
    display: flex;
    align-items: center;
    justify-content: center;
}

Q11、分析比較opacity: 0; visibility: hidden; 和 display: none; 的優(yōu)劣

  1. 結(jié)構(gòu)
    display: none; 會(huì)讓元素完全從渲染樹(shù)中消失,渲染的時(shí)候不占據(jù)任何空間,不能點(diǎn)擊;
    visibility: hidden; 不會(huì)讓元素從渲染樹(shù)中消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容看不見(jiàn),不能點(diǎn)擊;
    opacity: 0; 不會(huì)讓元素從渲染樹(shù)消失,渲染元素繼續(xù)占據(jù)空間,只是內(nèi)容看不見(jiàn),可以點(diǎn)擊;
  2. 繼承性
    display: none;和 opacity: 0; 是非繼承屬性,子孫節(jié)點(diǎn)消失是由于元素從渲染樹(shù)消失造成的,通過(guò)修改子孫節(jié)點(diǎn)的屬性無(wú)法將其顯示;
    visibility: hidden; 是繼承屬性,子孫節(jié)點(diǎn)消失是由于繼承了hidden屬性,通過(guò)給子孫節(jié)點(diǎn)設(shè)置visibility: visible;可以將子孫節(jié)點(diǎn)顯示出來(lái);
  3. 性能
    display: none; 修改元素會(huì)造成文檔回流,性能消耗較大;
    visibility: hidden; 修改元素只會(huì)造成重繪,性能消耗較少;
    opacity: 0; 修改元素會(huì)造成重繪,性能消耗較少;
  4. 聯(lián)系
    三者都可以讓元素不可見(jiàn)

Q12、用CSS或JS實(shí)現(xiàn)多行文本溢出省略效果(考慮兼容性)

  1. CSS
*單行*
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
*多行*
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; // 行數(shù)
overflow: hidden;
text-overflow: ellipsis;
  1. JS
    實(shí)現(xiàn)思路:
  • 使用split + 正則表達(dá)式將單詞與單個(gè)文字切割出來(lái)存入words
  • 加上 '...'
  • 判斷scrollHeight與clientHeight,超出的話就從words中pop一個(gè)出來(lái)
<p>測(cè)試文字,test words  1231231121</p>
const p = document.querySelector('p');
let words = p.innerHTML.split(/(?<=[\u4e00-\u9fa5])|(?<=\w*?\b)/g);
while(p.scrollHeight > p.clientHeight) {
    words.pop()
    p.innerHTML = words.join('') + '...'
}


JavaScript 篇

Q1、數(shù)組對(duì)象有哪些常用的方法

修改器方法
- pop(): 刪除數(shù)組的最后一個(gè)元素,并返回這個(gè)元素
- push() : 在數(shù)組的末尾增加一個(gè)或多個(gè)元素,并返回?cái)?shù)組的新長(zhǎng)度
- reverse() : 顛倒數(shù)組中元素的排列順序
- shift() : 刪除數(shù)組的第一個(gè)元素,并返回這個(gè)元素
- unshift() : 在數(shù)組的開(kāi)頭增加一個(gè)或多個(gè)元素,并返回?cái)?shù)組的新長(zhǎng)度
- sort() : 對(duì)數(shù)組元素進(jìn)行排序,并返回當(dāng)前數(shù)組
- splice() : 在任意的位置給數(shù)組添加或刪除任意個(gè)元素

訪問(wèn)方法
- concat() : 返回一個(gè)由當(dāng)前數(shù)組和其它若干個(gè)數(shù)組或非數(shù)組值組合而成的新數(shù)組
- join() : 連接所有數(shù)組元素組成一個(gè)字符串
- slice() : 抽取當(dāng)前數(shù)組中的一段元素組合成一個(gè)新數(shù)組
- indexOf() : 返回?cái)?shù)組中第一個(gè)與指定值相等的元素的索引,如果找不到這樣的元素則返回 -1
- lastIndexOf() : 返回?cái)?shù)組中最后一個(gè)(從右邊數(shù)第一個(gè))與指定值相等的元素的索引,如果找不到這樣的元素則返回 -1

迭代方法

  • forEach() : 為數(shù)組中的每個(gè)元素執(zhí)行一次回調(diào)函數(shù),無(wú)返回值或默認(rèn)為 undefined
  • map() : 返回一個(gè)由回調(diào)函數(shù)的返回值組成的新數(shù)組
  • filter() : 將所有在過(guò)濾函數(shù)中返回 true 的數(shù)組元素放進(jìn)一個(gè)新數(shù)組中并返回
  • every() : 如果數(shù)組中的每個(gè)元素都滿(mǎn)足測(cè)試函數(shù),則返回 true,否則返回 false
  • some() : 如果數(shù)組中至少由一個(gè)元素滿(mǎn)足測(cè)試函數(shù),則返回 true,否則返回 false

Q2. JS有哪幾種創(chuàng)建對(duì)象的方式

  1. 對(duì)象字面量
    var obj = {}
  2. Object 構(gòu)造函數(shù)
    var obj = new Object
  3. 工廠模式
        function Person(name, age) {
            var o = new Object()
            o.name = name;
            o.age = age;
            o.say = function() {
                console.log(name)
            }
            return 0
        }
    
    缺點(diǎn): 每次通過(guò) Person 創(chuàng)建對(duì)象的時(shí)候,所有的 say 方法都是一樣的,但是卻存儲(chǔ)了多次,浪費(fèi)資源。
  4. 構(gòu)造函數(shù)模式
    function Person(name, age) {
        this.name = name
        this.age = age
        this.say = function() {
            console.log(name)
        }
    }
    var person = new Person('hello', 16)
    
    構(gòu)造函數(shù)模式隱式在最后返回 return this 所以在缺少 new 的情況下,會(huì)將屬性和方法添加給全局對(duì)象,瀏覽器端就會(huì)添加給 window 對(duì)象,可以根據(jù) return this 的特性調(diào)用 call 或者 apply 指定 this
  5. 原型模式
    function Person() {}
    Person.prototype.name = 'Bob'
    Person.prototype.say = function() {
        alert(this.name);
    }
    Person.prototype.friends = ['Tom'];
    var person = new Person();
    
    實(shí)現(xiàn)了方法和屬性的共享,可以動(dòng)態(tài)添加對(duì)象的屬性和方法。但是沒(méi)有辦法創(chuàng)建實(shí)例自己的屬性和方法,也沒(méi)有辦法傳遞參數(shù)。
  6. 構(gòu)造函數(shù)和原型組合
    function Person(name, age) {
        this.name = name
        this.age = age
    }
    Person.prototype.say = function() {
        console.log(this.name)
    }
    var person = new Person('hello')
    

Q3. JavaScript 如何實(shí)現(xiàn)繼承

  • 原型鏈繼承

    function Animal() {}
    Animal.prototype.name = 'cat'
    Animal.prototype.age = 2
    Animal.prototype.say = function() {
        console.log('hello')
    }
    var cat  = new Animal()
    cat.name     // cat
    cat.age    // 2
    cat.say()   // hello
    

    最簡(jiǎn)單的實(shí)現(xiàn)繼承的方式,但是也有缺點(diǎn)
    1. 來(lái)自原型對(duì)象的所有屬性都被所有實(shí)例共享
    2. 創(chuàng)建子類(lèi)實(shí)例時(shí),無(wú)法向父類(lèi)構(gòu)造函數(shù)傳參
    3. 要想為子類(lèi)新增屬性和方法,必須要在 new 語(yǔ)句之后執(zhí)行,不能放到構(gòu)造器中

  • 構(gòu)造繼承

        function Animal() {
            this.species = '動(dòng)物'
        }
        function Cat(name, age) {
            Animal.call(this)
            this.name = name
            this.age = age
        }
        var cat = new Cat('coco', 2)
        cat.name    // coco
        cat.age    // 2
        cat.species // 動(dòng)物
    

    使用 callapply 方法,將父對(duì)象的構(gòu)造函數(shù)綁定在子對(duì)象上

  • 組合繼承

        function Animal() {
            this.species = 'animal'
        }
        function Cat(name) {
            Animal.call(this)
            this.name = name
        }
        Cat.prototype = new Animal() // 重寫(xiě)原型
        Cat.prototype.constructor = Cat
    

    如果沒(méi)有 Cat.prototype = new Animal() 這一行, Cat.prototype.constructor 是指向 Cat 的,加了這一行以后,Cat.prototype.constructor 指向 Animal. 這顯然會(huì)導(dǎo)致繼承鏈的紊亂(cat1 明明是用構(gòu)造函數(shù)Cat生成的),因此必須手動(dòng)糾正,將 Cat.prototype 對(duì)象的 constructor 值改為Cat

  • extends 繼承 ES6 新增繼承方式,class 可以通過(guò) extends 關(guān)鍵字實(shí)現(xiàn)繼承

        class Animal {}
        class Cat extends Animal {
            constructor() {
                super();
            }
        }
    

    使用 extends 實(shí)現(xiàn)繼承,必須添加 super 關(guān)鍵字定義子類(lèi)的 constructor,這里的 super() 就相當(dāng)于 Animal.prototype.constructor.call(this)

Q4、同步和異步的區(qū)別,怎么異步加載JavaScript

同步模式
同步模式,又稱(chēng)為阻塞模式,JavaScript 在默認(rèn)情況下是會(huì)阻塞加載的。當(dāng)前面的 JavaScript 請(qǐng)求沒(méi)有處理和執(zhí)行完時(shí),會(huì)阻止瀏覽器的后續(xù)處理
異步模式
異步加載又叫非阻塞,瀏覽器在下載執(zhí)行 JavaScript 同時(shí),還會(huì)繼續(xù)進(jìn)行后續(xù)頁(yè)面的處理
異步加載 JavaScript

  • 動(dòng)態(tài)添加 script 標(biāo)簽
  • defer
  • async

defer 屬性和 async 都是屬于 script 標(biāo)簽上面的屬性,兩者都能實(shí)現(xiàn) JavaScript 的異步加載。不同之處在于:async 在異步加載完成的時(shí)候就馬上開(kāi)始執(zhí)行了,而 defer 會(huì)等到 html 加載完畢之后再執(zhí)行

VUE篇

Q1. 寫(xiě) React / Vue 項(xiàng)目時(shí)為什么要在列表組件中寫(xiě) key,其作用是什么?

key是給每一個(gè)vnode的唯一id,可以依靠key,更準(zhǔn)確,更快的拿到oldVnode中對(duì)應(yīng)的vnode節(jié)點(diǎn)

1. 更準(zhǔn)確

帶key就不是就地復(fù)用了,在samenode函數(shù)a.key === b.key對(duì)比中可以避免就地復(fù)用的情況,所以更加準(zhǔn)確。

2. 更快

利用key的唯一性生成map對(duì)象來(lái)獲取對(duì)應(yīng)節(jié)點(diǎn),比遍歷方式更快。


vue和React都是采用diff算法來(lái)對(duì)比新舊虛擬節(jié)點(diǎn),從而更新節(jié)點(diǎn)。vue的diff算法在交叉對(duì)比中,當(dāng)新節(jié)點(diǎn)跟舊節(jié)點(diǎn)頭尾交叉對(duì)比沒(méi)有結(jié)果時(shí),會(huì)根據(jù)新節(jié)點(diǎn)的key去對(duì)比舊節(jié)點(diǎn)數(shù)組中的key,從而找到相應(yīng)舊節(jié)點(diǎn)(這里對(duì)應(yīng)的是一個(gè)key => index的map映射)。如果沒(méi)找到就認(rèn)為是一個(gè)新增節(jié)點(diǎn)。而如果沒(méi)有key,那么就會(huì)采用遍歷查找的方式去找到對(duì)應(yīng)的舊節(jié)點(diǎn)。一種是map映射,另一種是遍歷查找。相對(duì)比而言,map映射的速度更快。
vue 部分源碼如下:

// oldCh 是一個(gè)舊虛擬節(jié)點(diǎn)數(shù)組
if (isUndef(oldKeyToIdx)) {
    oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
}
if(isDef(newStartVnode.key)) {
    // map 方式獲取
    idxInOld = oldKeyToIdx[newStartVnode.key]
} esle {
    // 遍歷方式獲取
    idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
}

創(chuàng)建map函數(shù)

function createKeyToOldIdx(children, beginIdx, endIdx) {
    let i, key
    const map = {}
    for(i = beginIdx; i <= endIdx; ++i) {
        key = children[i].key
        if(isDef(key)) map[key] = i
    }
    return map
}

遍歷尋找

// sameVnode 是對(duì)比新舊節(jié)點(diǎn)是否相同的函數(shù)
function findIdxInOld(node, oldCh, start, end) {
    for(let i = start; i < end; i++) {
        const c = oldCh[i]
        if(isDef(c) && sameVnode(node, c)) return i
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • vue中雙向數(shù)據(jù)綁定是如何實(shí)現(xiàn)的 數(shù)據(jù)雙向綁定,一個(gè)是監(jiān)聽(tīng)頁(yè)面的數(shù)據(jù)變化,一個(gè)是將數(shù)據(jù)變化映射到頁(yè)面。 分成兩個(gè)進(jìn)...
    抱以惡意閱讀 201評(píng)論 0 0
  • 1、active-class是哪個(gè)組件的屬性?嵌套路由怎么定義? 答:vue-router模塊的router-li...
    world_7735閱讀 776評(píng)論 0 7
  • js閉包概念:在函數(shù)內(nèi)壁定義一個(gè)子函數(shù),可以用子函數(shù)訪問(wèn)父函數(shù)的私有變量,執(zhí)行完成操作后將函數(shù)通過(guò)return對(duì)象...
    瞳孔里的溫柔你看得見(jiàn)不閱讀 1,093評(píng)論 0 4
  • js閉包概念:在函數(shù)內(nèi)壁定義一個(gè)子函數(shù),可以用子函數(shù)訪問(wèn)父函數(shù)的私有變量,執(zhí)行完成操作后將函數(shù)通過(guò)return對(duì)象...
    這是這時(shí)閱讀 359評(píng)論 0 0
  • 【轉(zhuǎn)載】CSDN - 張林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牘閱讀 3,589評(píng)論 1 14

友情鏈接更多精彩內(nèi)容