React面試題

react context

組件經過Context是能夠訪問到其父組件鏈上全部節點組件提供的Context的屬性。css

因此,我借鑑了JS做用域鏈的思路,把Context當成是組件的做用域來使用。html

如何看待前端框架選型

對於同一個類型的項目,採用開發模式,使用的基本框架都是一致的。前端

前端技術選型:vue

(1)外部用戶的PC站;react

(2)外部用戶的mobile站;jquery

(3)外部用戶的Native App開發;android

(4)內部員工的管理後臺webpack

一、外部用戶的PC站es6

須要有SEO,有加載體驗,採用的是先後端分離開發模式,頁面直接渲染,基於jquery。web

爲何使用jquery?

(1)主要是爲了兼容IE8;

(2)是外部用戶,視覺體驗高,權重高。適合先有行,再有行。就是說視覺和行爲要儘量分離,會犧牲一點開發成本,可是用戶更重要。

(3)絕大多數頁面交互輕量用不上數據驅動。

二、外部用戶的Mobile站

這裏說的Mobile站主要是瀏覽器訪問爲主的,所以,頁面切換都是傳統鏈接跳轉,屬於傳統web應用,先後端分離開發模式,頁面直接渲染,採用react。大體緣由:使用react 是爲了 和APP端的react native保持同步。

三、外部用戶的Native App開發

前端組有直接參與 Native APP 開發的項目,使用的是 React Native 進行開發。

爲啥選擇RN,以前Hybrid模式開發有性能優化瓶頸,採用React Native性能能夠突破這個瓶頸,有原生的性能,且支持熱更新,上手不算太難,跨平臺,IOS和android代碼複用率90%。適合交互和動畫不太複雜的項目,最終要根據項目來。特別適合快速迭代的項目或者前期須要大量試錯的項目。

(1)不要隨意使用第三方庫,後期修改維護不方便,儘可能本身寫仍是本身寫;

(2)前期仍是須要客戶端幫忙配合,項目搭建。

四、內部員工的管理後臺

先後端分離開發,頁面側重異步渲染,使用vuejs。

大體內容是:後臺管理系統有大量的增刪改查操做,適合具備雙向綁定的類庫或者框架進行渲染。同時沒有兼容性的要求(SEO,首屏渲染),所以單頁面是合適的。能夠選擇vue,react,angular。由於vue對api,文檔對開發者更友好。選用好的UI組件,規範貫徹,拆分和按需加載,自動化測試有待增強。

對於比較正式的項目,前端技術選型策略必定是產品收益最大化,用戶在首位

react生命週期

react 生命週期函數 初始化階段:

getDefaultProps:獲取實例的默認屬性

getInitialState:獲取每一個實例的初始化狀態

componentWillMount:組件即將被裝載、渲染到頁面上

render:組件在這裏生成虛擬的 DOM 節點

componentDidMount:組件真正在被裝載以後 運行中狀態:

componentWillReceiveProps:組件將要接收到屬性的時候調用

shouldComponentUpdate:組件接受到新屬性或者新狀態的時候(能夠返回 false,接收數據後不更新,阻止 render 調用,後面的函數不會被繼續執行了)

componentWillUpdate:組件即將更新不能修改屬性和狀態

render:組件從新描繪

componentDidUpdate:組件已經更新

銷燬階段: componentWillUnmount:組件即將銷燬

react 的虛擬dom是怎麼實現的?diff算法?

首先說說爲何要使用Virturl DOM,由於操做真實DOM的耗費的性能代價過高,因此react內部使用js實現了一套dom結構,在每次操做在和真實dom以前,使用實現好的diff算法,對虛擬dom進行比較,遞歸找出有變化的dom節點,而後對其進行更新操做。爲了實現虛擬DOM,咱們須要把每一種節點類型抽象成對象,每一種節點類型有本身的屬性,也就是prop,每次進行diff的時候,react會先比較該節點類型,假如節點類型不同,那麼react會直接刪除該節點,而後直接建立新的節點插入到其中,假如節點類型同樣,那麼會比較prop是否有更新,假若有prop不同,那麼react會斷定該節點有更新,那麼重渲染該節點,而後在對其子節點進行比較,一層一層往下,直到沒有子節點。

diff算法實現

把樹形結構按照層級分解,只比較同級元素。

給列表結構的每一個單元添加惟一的 key 屬性,方便比較。

React 只會匹配相同 class 的 component(這裏面的 class 指的是組件的名字)

合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty.到每個事件循環結束, React 檢查全部標記 dirty 的 component 從新繪製. 選擇性子樹渲染。開發人員能夠重寫 shouldComponentUpdate 提升 diff 的性能。

React 中 refs 的做用是什麼?

Refs 是 React 提供給咱們的安全訪問 DOM 元素或者某個組件實例的句柄。咱們能夠爲元素添加 ref 屬性而後在回調函數中接受該元素在 DOM 樹中的句柄,該值會做爲回調函數的第一個參數返回

React 中有三種構建組件的方式

React.createClass()、ES6 class 和無狀態函數。

react 組件的劃分業務組件技術組件?

根據組件的職責一般把組件分爲 UI 組件和容器組件。

UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯。

二者經過 React-Redux 提供 connect 方法聯繫起來。

應該在 React 組件的何處發起 Ajax 請求

在 React 組件中,應該在 componentDidMount 中發起網絡請求。這個方法會在組件第一次「掛載」(被添加到 DOM)時執行,在組件的生命週期中僅會執行一次。更重要的是,你不能保證在組件掛載以前 Ajax 請求已經完成,若是是這樣,也就意味着你將嘗試在一個未掛載的組件上調用 setState,這將不起做用。在 componentDidMount 中發起網絡請求將保證這有一個組件能夠更新了

描述事件在 React 中的處理方式。

爲了解決跨瀏覽器兼容性問題,您的 React 中的事件處理程序將傳遞 SyntheticEvent 的實例,它是 React 的瀏覽器本機事件的跨瀏覽器包裝器。

這些 SyntheticEvent 與您習慣的原生事件具備相同的接口,除了它們在全部瀏覽器中都兼容。有趣的是,React 實際上並無將事件附加到子節點自己。React 將使用單個事件監聽器監聽頂層的全部事件。這對於性能是有好處的,這也意味着在更新 DOM 時,React 不須要擔憂跟蹤事件監聽器。

react 的渲染過程當中,兄弟節點之間是怎麼處理的?也就是key值不同的時候。

一般咱們輸出節點的時候都是map一個數組而後返回一個ReactNode,爲了方便react內部進行優化,咱們必須給每個reactNode添加key,這個key prop在設計值處不是給開發者用的,而是給react用的,大概的做用就是給每個reactNode添加一個身份標識,方便react進行識別,在重渲染過程當中,若是key同樣,若組件屬性有所變化,則react只更新組件對應的屬性;沒有變化則不更新,若是key不同,則react先銷燬該組件,而後從新建立該組件。

React 中 keys 的做用是什麼?

開發過程當中,咱們須要保證某個元素的 key 在其同級元素中具備惟一性。在 React Diff 算法中 React 會藉助元素的 Key 值來判斷該元素是新近建立的仍是被移動而來的元素,從而減小沒必要要的元素重渲染。此外,React 還須要藉助 Key 值來判斷元素與本地狀態的關聯關係,所以咱們毫不可忽視轉換函數中 Key 的重要性。

調用 setState 以後發生了什麼?

在代碼中調用 setState 函數以後,React 會將傳入的參數對象與組件當前的狀態合併,而後觸發所謂的調和過程(Reconciliation)。通過調和過程,React 會以相對高效的方式根據新的狀態構建 React 元素樹而且着手從新渲染整個 UI 界面。在 React 獲得元素樹以後,React 會自動計算出新的樹與老樹的節點差別,而後根據差別對界面進行最小化重渲染。在差別計算算法中,React 可以相對精確地知道哪些位置發生了改變以及應該如何改變,這就保證了按需更新,而不是所有從新渲染。

shouldComponentUpdate 是作什麼的,(react 性能優化是哪一個周期函數?)

shouldComponentUpdate 這個方法用來判斷是否須要調用 render 方法從新描繪 dom。由於 dom 的描繪很是消耗性能,若是咱們能在 shouldComponentUpdate 方法中可以寫出更優化的 dom diff 算法,能夠極大的提升性能。

爲何虛擬 dom 會提升性能?(必考)

虛擬 dom 至關於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法避免了沒有必要的 dom 操做,從而提升性能。

用 JavaScript 對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中當狀態變動的時候,從新構造一棵新的對象樹。而後用新的樹和舊的樹進行比較,記錄兩棵樹差別把 2 所記錄的差別應用到步驟 1 所構建的真正的 DOM 樹上,視圖就更新了。

React 中 refs 的做用是什麼?

Refs 是 React 提供給咱們的安全訪問 DOM 元素或者某個組件實例的句柄。咱們能夠爲元素添加 ref 屬性而後在回調函數中接受該元素在 DOM 樹中的句柄,該值會做爲回調函數的第一個參數返回:

展現組件(Presentational component)和容器組件(Container component)之間有何不一樣

展現組件關心組件看起來是什麼。展現專門經過 props 接受數據和回調,而且幾乎不會有自身的狀態,但當展現組件擁有自身的狀態時,一般也只關心 UI 狀態而不是數據的狀態。

容器組件則更關心組件是如何運做的。容器組件會爲展現組件或者其它容器組件提供數據和行爲(behavior),它們會調用 Flux actions,並將其做爲回調提供給展現組件。容器組件常常是有狀態的,由於它們是(其它組件的)數據源。

類組件(Class component)和函數式組件(Functional component)之間有何不一樣

類組件不只容許你使用更多額外的功能,如組件自身的狀態和生命週期鉤子,也能使組件直接訪問 store 並維持狀態

當組件僅是接收 props,並將組件自身渲染到頁面時,該組件就是一個 '無狀態組件(stateless component)',可使用一個純函數來建立這樣的組件。這種組件也被稱爲啞組件(dumb components)或展現組件

(組件的)狀態(state)和屬性(props)之間有何不一樣

State 是一種數據結構,用於組件掛載時所需數據的默認值。State 可能會隨着時間的推移而發生突變,但多數時候是做爲用戶事件行爲的結果。

Props(properties 的簡寫)則是組件的配置。props 由父組件傳遞給子組件,而且就子組件而言,props 是不可變的(immutable)。組件不能改變自身的 props,可是能夠把其子組件的 props 放在一塊兒(統一管理)。Props 也不只僅是數據--回調函數也能夠經過 props 傳遞。

何爲受控組件(controlled component)

在 HTML 中,相似 input, textarea 和 select> 這樣的表單元素會維護自身的狀態,並基於用戶的輸入來更新。當用戶提交表單時,前面提到的元素的值將隨表單一塊兒被髮送。但在 React 中會有些不一樣,包含表單元素的組件將會在 state 中追蹤輸入的值,而且每次調用回調函數時,如 onChange 會更新 state,從新渲染組件。一個輸入表單元素,它的值經過 React 的這種方式來控制,這樣的元素就被稱爲"受控元素"。

何爲高階組件(higher order component)

高階組件是一個以組件爲參數並返回一個新組件的函數。HOC 運行你重用代碼、邏輯和引導抽象。最多見的多是 Redux 的 connect 函數。除了簡單分享工具庫和簡單的組合,HOC 最好的方式是共享 React 組件之間的行爲。若是你發現你在不一樣的地方寫了大量代碼來作同一件事時,就應該考慮將代碼重構爲可重用的 HOC。

爲何建議傳遞給 setState 的參數是一個 callback 而不是一個對象

由於 this.props 和 this.state 的更新多是異步的,不能依賴它們的值去計算下一個 state。

除了在構造函數中綁定 this,還有其它方式嗎

你可使用屬性初始值設定項(property initializers)來正確綁定回調,create-react-app 也是默認支持的。在回調中你可使用箭頭函數,但問題是每次組件渲染時都會建立一個新的回調。

(在構造函數中)調用 super(props) 的目的是什麼

在 super() 被調用以前,子類是不能使用 this 的,在 ES2015 中,子類必須在 constructor 中調用 super()。傳遞 props 給 super() 的緣由則是便於(在子類中)能在 constructor 訪問 this.props。

createElement 和 cloneElement 有什麼區別?

React.createElement():JSX 語法就是用 React.createElement()來構建 React 元素的。它接受三個參數,第一個參數能夠是一個標籤名。如 div、span,或者 React 組件。第二個參數爲傳入的屬性。第三個以及以後的參數,皆做爲組件的子組件。

React.cloneElement()與 React.createElement()類似,不一樣的是它傳入的第一個參數是一個 React 元素,而不是標籤名或組件。新添加的屬性會併入原有的屬性,傳入到返回的新元素中,而就的子元素獎盃替換。

簡述 flux 思想

Flux 的最大特色,就是數據的"單向流動"。

用戶訪問 View

View 發出用戶的 Action

Dispatcher 收到 Action,要求 Store 進行相應的更新

Store 更新後,發出一個"change"事件

View 收到"change"事件後,更新頁面

React 項目用過什麼腳手架

creat-react-app

瞭解 redux 麼,說一下 redux 把

redux 是一個應用數據流框架,主要是解決了組件間狀態共享的問題,原理是集中式管理,主要有三個核心方法,action,store,reducer,工做流程是 view 調用 store 的 dispatch 接收 action 傳入 store,reducer 進行 state 操做,view 經過 store 提供的 getState 獲取最新的數據,flux 也是用來進行數據操做的,有四個組成部分 action,dispatch,view,store,工做流程是 view 發出一個 action,派發器接收 action,讓 store 進行數據更新,更新完成之後 store 發出 change,view 接受 change 更新視圖。Redux 和 Flux 很像。主要區別在於 Flux 有多個能夠改變應用狀態的 store,在 Flux 中 dispatcher 被用來傳遞數據到註冊的回調事件,可是在 redux 中只能定義一個可更新狀態的 store,redux 把 store 和 Dispatcher 合併,結構更加簡單清晰

新增 state,對狀態的管理更加明確,經過 redux,流程更加規範了,減小手動編碼量,提升了編碼效率,同時缺點時當數據更新時有時候組件不須要,可是也要從新繪製,有些影響效率。通常狀況下,咱們在構建多交互,多數據流的複雜項目應用時纔會使用它們

redux 有什麼缺點

一個組件所須要的數據,必須由父組件傳過來,而不能像 flux 中直接從 store 取。

當一個組件相關數據更新時,即便父組件不須要用到這個組件,父組件仍是會從新 render,可能會有效率影響,或者須要寫複雜的 shouldComponentUpdate 進行判斷。

我如今有一個數組[1,2,3,4],請實現算法,獲得這個數組的全排列的數組,如[2,1,3,4],[2,1,4,3]。。。。你這個算法的時間複雜度是多少

將每個數組拆除倆個小數組進行求它的全排列,而後獲得的結果互相之間又進行全排列,而後把最後的結果鏈接起來

你說一下webpack的一些plugin,怎麼使用webpack對項目進行優化

構建優化 一、減小編譯體積 ContextReplacementPugin、IgnorePlugin、babel-plugin-import、babel-plugin-transform-runtime。

二、並行編譯 happypack、thread-loader、uglifyjsWebpackPlugin開啓並行

三、緩存 cache-loader、hard-source-webpack-plugin、uglifyjsWebpackPlugin開啓緩存、babel-loader開啓緩存

四、預編譯 dllWebpackPlugin && DllReferencePlugin、auto-dll-webapck-plugin

性能優化 一、減小編譯體積 Tree-shaking、Scope Hositing。

二、hash緩存 webpack-md5-plugin

三、拆包 splitChunksPlugin、import()、require.ensure

說說從輸入URL到看到頁面發生的全過程,越詳細越好

一、首先瀏覽器主進程接管,開了一個下載線程。

二、而後進行HTTP請求(DNS查詢、IP尋址等等),中間會有三次捂手,等待響應,開始下載響應報文。

三、將下載完的內容轉交給Renderer進程管理。

四、Renderer進程開始解析css rule tree和dom tree,這兩個過程是並行的,因此通常我會把link標籤放在頁面頂部。

五、解析繪製過程當中,當瀏覽器遇到link標籤或者script、img等標籤,瀏覽器會去下載這些內容,遇到時候緩存的使用緩存,不適用緩存的從新下載資源。

六、css rule tree和dom tree生成完了以後,開始合成render

七、tree,這個時候瀏覽器會進行layout,開始計算每個節點的位置,而後進行繪製。 繪製結束後,關閉TCP鏈接,過程有四次揮手

你剛剛說了三次握手,四次揮手,那你描述一下?

(1)第一次握手:Client將標誌位SYN置爲1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。 (2)第二次握手:Server收到數據包後由標誌位SYN=1知道Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認鏈接請求,Server進入SYN_RCVD狀態。 (3)第三次握手:Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間能夠開始傳輸數據了。

1)第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。 (2)第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。 (3)第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。 (4)第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。

CSS中幾種垂直水平居中的方式

一、絕對定位+margin:auto

二、絕對定位+margin反向偏移

三、絕對定位+transform反向偏移

四、display:tabel

五、display: flex

react和vue的比較

觀察者模式實現 ?

http報文頭部有哪些字段? 有什麼意義 ?

請求頭(Request):

Accept:text/html application/xml 告訴服務器客戶端瀏覽器這邊能夠出裏什麼數據;

Accept-Encodeing:gzip 告訴服務器我能支持什麼樣的壓縮格式

accept-language:告訴服務器瀏覽器支持的語言

Cache-control:告訴服務器是否緩存

Connection:keep-alive 告訴服務器當前保持活躍(與服務器處於連接狀態)

Host:遠程服務器的域名

User-agent:客戶端的一些信息,瀏覽器信息 版本

referer:當前頁面上一個頁面地址。通常用於服務器判斷是否爲同一個域名下的請求

返回頭(response-header):

cache-control:private/no-cache; 私有的不須要緩存/no-cache也不須要緩存

connection:keep-live; 服務器贊成保持鏈接

content-Enconding:gzip;除去頭的剩餘部分壓縮返回格式

content-length:內容長度

content-type:text/css;返回內容支持格式

Date: 時間

server:ngnix 服務器類型

set-Cookie:服務器向客戶端設置cookie 第一次訪問服務器會下發cookie看成身份認證信息,第二次訪問服務器再把cookie送給服務器,能夠看成認證信息

last-modified: 時間戳 文檔的最後改動時間。客戶能夠經過If-Modified-Since請求頭提供一個日期,該請求將被視爲一個條件GET,只有改動時間遲於指定時間的文檔纔會返回,不然返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。

expires 告訴瀏覽器把回送的資源緩存多長時間 -1或0則是不緩存

etag:版本專有的加密指紋。(有的網站不用,並不是必須)優先檢查etag再檢查last-modif

ied的時間戳。向服務器請求帶if-none-match,服務器判斷是否過時未過時返回304,過時返回200

// 註釋:第一次請求出來的數據先進行緩存協商,是否緩存expires,cache-control 緩存時間,etag,last-modified等 //註釋:屢次訪問的時候,瀏覽器先判斷是否有緩存,是否過時 //未過時:直接從緩存中讀取。

//http狀態碼

//1.指示信息–表示請求已經接受,繼續處理 //2.成功–表示請求已經被成功接受,理解 //3.重定向–表示完成請求必須進行更進一步操做 //4.客戶端錯誤–請求有語法錯誤或者請求沒法實現 //5.服務器端錯誤–服務器未能實現合法的請求

移動端高清方案如何解決 ?

webpack的原理, loader 和 plugin 是幹什麼的? 有本身手寫過麼 ?

1.2 打包原理

識別入口文件

經過逐層識別模塊依賴。(Commonjs、amd或者es6的import,webpack都會對其進行分析。來獲取代碼的依賴)

webpack作的就是分析代碼。轉換代碼,編譯代碼,輸出代碼 最終造成打包後的代碼

loader是文件加載器,可以加載資源文件,並對這些文件進行一些處理,諸如編譯、壓縮等,最終一塊兒打包到指定的文件中

在 Webpack 運行的生命週期中會廣播出許多事件,Plugin 能夠監聽這些事件,在合適的時機經過 Webpack 提供的 API 改變輸出結果

SSR 和 客戶端渲染有什麼區別 , vue是如何實現綁定事件的 ?

客戶端渲染和服務器端渲染的最重要的區別就是到底是誰來完成html文件的完整拼接,若是是在服務器端完成的,而後返回給客戶端,就是服務器端渲染,而若是是前端作了更多的工做完成了html的拼接,則就是客戶端渲染。

服務器端渲染的優缺點是?

優勢:

前端耗時少。由於後端拼接完了html,瀏覽器只須要直接渲染出來。 有利於SEO。由於在後端有完整的html頁面,因此爬蟲更容易爬取得到信息,更有利於seo。 無需佔用客戶端資源。即解析模板的工做徹底交由後端來作,客戶端只要解析標準的html頁面便可,這樣對於客戶端的資源佔用更少,尤爲是移動端,也能夠更省電。 後端生成靜態化文件。即生成緩存片斷,這樣就能夠減小數據庫查詢浪費的時間了,且對於數據變化不大的頁面很是高效 。 缺點:

不利於先後端分離,開發效率低。使用服務器端渲染,則沒法進行分工合做,則對於前端複雜度高的項目,不利於項目高效開發。另外,若是是服務器端渲染,則前端通常就是寫一個靜態html文件,而後後端再修改成模板,這樣是很是低效的,而且還經常須要先後端共同完成修改的動做; 或者是前端直接完成html模板,而後交由後端。另外,若是後端改了模板,前端還須要根據改動的模板再調節css,這樣使得先後端聯調的時間增長。 佔用服務器端資源。即服務器端完成html模板的解析,若是請求較多,會對服務器形成必定的訪問壓力。而若是使用前端渲染,就是把這些解析的壓力分攤了前端,而這裏確實徹底交給了一個服務器。

客戶端渲染的優缺點是? 優勢:

先後端分離。前端專一於前端UI,後端專一於api開發,且前端有更多的選擇性,而不須要遵循後端特定的模板。 體驗更好。好比,咱們將網站作成SPA或者部份內容作成SPA,這樣,尤爲是移動端,可使體驗更接近於原生app。 缺點:

前端響應較慢。若是是客戶端渲染,前端還要進行拼接字符串的過程,須要耗費額外的時間,不如服務器端渲染速度快。 不利於SEO。目前好比百度、谷歌的爬蟲對於SPA都是不認的,只是記錄了一個頁面,因此SEO不好。由於服務器端可能沒有保存完整的html,而是前端經過js進行dom的拼接,那麼爬蟲沒法爬取信息。 除非搜索引擎的seo能夠增長對於JavaScript的爬取能力,這才能保證seo。

移動端rem佈局如何實現? 簡述原理?

原理是,先按定高寬設計出來頁面,而後轉換爲rem單位,

配合js查詢屏幕大小來改變html的font-size,

最終作出所謂的完美自適應。

rem+js是寬度自適應,沒法作到高度自適應,因此那些對高度要求很高的rem+js沒法實現。

改變瀏覽器寬度,你會發現,頁面全部元素的高寬都等比例縮放,

也就是大屏幕下導航是橫的,小屏幕下仍是橫的只不過變小了。。

優勢:理想狀態是全部屏幕的高寬比和最初的設計高寬比同樣,或者相差很少,完美適應。

缺點:碰到重視高度的設計,或者重視元素間間距的設計,那就玩不開了。

DOM節點類型

相關文章
相關標籤/搜索