在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ JavaScript 與 DOM(下)
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計(jì)模式之狀態(tài)模式
JavaScript 核心(晉級(jí)高手必讀篇)
設(shè)計(jì)模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計(jì)模式之中介者模式
設(shè)計(jì)模式之裝飾者模式
設(shè)計(jì)模式之模板方法
設(shè)計(jì)模式之外觀模式
強(qiáng)大的原型和原型鏈
設(shè)計(jì)模式之構(gòu)造函數(shù)模式
揭秘命名函數(shù)表達(dá)式
深入理解J avaScript 系列(結(jié)局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設(shè)計(jì)模式之適配器模式
設(shè)計(jì)模式之組合模式
設(shè)計(jì)模式之命令模式
S.O.L.I.D 五大原則之單一職責(zé) SRP
編寫高質(zhì)量 JavaScript 代碼的基本要點(diǎn)
求值策略
閉包(Closures)
對(duì)象創(chuàng)建模式(上篇)
This? Yes,this!
設(shè)計(jì)模式之代理模式
變量對(duì)象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向?qū)ο缶幊讨话憷碚?/span>
設(shè)計(jì)模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設(shè)計(jì)模式之迭代器模式
立即調(diào)用的函數(shù)表達(dá)式
設(shè)計(jì)模式之享元模式
設(shè)計(jì)模式之原型模式
根本沒有“JSON 對(duì)象”這回事!
JavaScript 與 DOM(下)
面向?qū)ο缶幊讨?ECMAScript 實(shí)現(xiàn)
全面解析 Module 模式
對(duì)象創(chuàng)建模式(下篇)
設(shè)計(jì)模式之職責(zé)鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設(shè)計(jì)模式之橋接模式
設(shè)計(jì)模式之策略模式
設(shè)計(jì)模式之觀察者模式
代碼復(fù)用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設(shè)計(jì)模式之工廠模式

JavaScript 與 DOM(下)

介紹

上一章我們介紹了 JavaScript 的基本內(nèi)容和 DOM 對(duì)象的各個(gè)方面,包括如何訪問 node 節(jié)點(diǎn)。本章我們將講解如何通過 DOM 操作元素并且討論瀏覽器事件模型。

操作元素

上一章節(jié)我們提到了 DOM 節(jié)點(diǎn)集合或單個(gè)節(jié)點(diǎn)的訪問步驟,每個(gè) DOM 節(jié)點(diǎn)都包括一個(gè)屬性集合,大多數(shù)的屬性都提供為相應(yīng)的功能提供了抽象。例如,如果有一個(gè)帶有 ID 屬性 intro 的文本元素,你可以很容易地通過 DOM API 來改變?cè)撛氐念伾?/p>

document.getElementById('intro').style.color = '#FF0000';

為了理解這個(gè) API 的功能,我們一步一步分開來看就非常容易理解了:

var myDocument = document;  
var myIntro = myDocument.getElementById('intro');  
var myIntroStyles = myIntro.style;  
// 現(xiàn)在,我們可以設(shè)置顏色了:  
myIntroStyles.color = '#FF0000';

現(xiàn)在,我們有了該文本的 style 對(duì)象的引用了,所以我們可以添加其它的 CSS 樣式:

myIntroStyles.padding = '2px 3px 0 3px';  
myIntroStyles.backgroundColor = '#FFF';  
myIntroStyles.marginTop = '20px'; 

這里我們只是要了基本的 CSS 屬性名稱,唯一區(qū)別是 CSS 屬性的名稱如果帶有-的話,就需要去除,比如用 marginTop 代替 margin-top。例如,下面的代碼是不工作的,并且會(huì)拋出語法錯(cuò)誤:

myIntroStyles.padding-top = '10em';     
// 產(chǎn)生語法錯(cuò)誤:
// 在JavaScript里橫線-是減法操作符
// 而且也沒有這樣的屬性名稱

屬性可以像數(shù)組一樣訪問,所以利用這個(gè)知識(shí)我們可以創(chuàng)建一個(gè)函數(shù)來改變?nèi)魏谓o定元素的樣式:

function changeStyle(elem, property, val) {
    elem.style[property] = val; // 使用[]來訪問屬性
}
// 使用上述的函數(shù):  
var myIntro = document.getElementById('intro'); // 獲取intro文本對(duì)象
changeStyle(myIntro, 'color', 'red');  

這僅僅是個(gè)例子,所以該函數(shù)也許沒什么用,語法上來說,直接用還是會(huì)快點(diǎn),例如(elem.style.color = ‘red’)。除了 style 屬性以外,一個(gè)節(jié)點(diǎn)(或元素)也還有其他很多屬性可以操作,如果你使用 Firebug,點(diǎn)擊 DOM 選項(xiàng)卡可以看到所有該節(jié)點(diǎn)(或元素)的所有屬性:

http://wiki.jikexueyuan.com/project/javascript-depth-understanding/images/15.png" alt="" />

所有的屬性都可以通過點(diǎn)標(biāo)示符來訪問(例如:Element.tabIndex)。不是所有的屬性都是原始數(shù)據(jù)類型(strings,numbers,Booleans 等等),sytle 屬性也是一個(gè)包含自己屬性的對(duì)象,很多元素的屬性都是只讀的,也就是說不能修改他們的值。例如,你不能直接修改一個(gè)節(jié)點(diǎn)的 parentNode 屬性,如果你修改只讀屬性的時(shí)候?yàn)g覽器會(huì)拋出錯(cuò)誤:例如,拋出錯(cuò)誤“setting a property that has only a getter”,只是我們需要注意的。

通常 DOM 操作都是改變?cè)嫉膬?nèi)容,這里有幾種方式來實(shí)現(xiàn)這個(gè),最簡單的是使用 innerHTML 屬性,例如:

var myIntro = document.getElementById('intro');  
// 替換當(dāng)前的內(nèi)容
myIntro.innerHTML = 'New content for the <strong>amazing</strong> paragraph!';  
// 添加內(nèi)容到當(dāng)前的內(nèi)容里 
myIntro.innerHTML += '... some more content...';

唯一的問題是該方法沒在規(guī)范里定義,而且在 DOM 規(guī)范里也沒有定義,如果你不反感的話請(qǐng)繼續(xù)使用,因?yàn)樗任覀兿旅嬉懻撈渌姆椒於嗔恕?/p>

Node 節(jié)點(diǎn)

通過 DOM API 創(chuàng)建內(nèi)容的時(shí)候需要注意 node 節(jié)點(diǎn)的 2 種類型,一種是元素節(jié)點(diǎn),一種是 text 節(jié)點(diǎn),上一章節(jié)已經(jīng)列出了所有的節(jié)點(diǎn)類型,這兩種需要我們現(xiàn)在特別注意。創(chuàng)建元素可以通過 createElement 方法,而創(chuàng)建 text 節(jié)點(diǎn)可以使用 createTextNode,相應(yīng)代碼如下:

var myIntro = document.getElementById('intro');  
// 添加內(nèi)容
var someText = 'This is the text I want to add';  
var textNode = document.createTextNode(someText);  
myIntro.appendChild(textNode);

這里我們使用了 appendChild 方法將新 text 節(jié)點(diǎn)附件到文本字段,這樣做比非標(biāo)準(zhǔn)的 innerHTML 方法顯得有點(diǎn)長,但了解這些原理依然很重要,這里有一個(gè)使用 DOM 方法的更詳細(xì)例子:

var myIntro = document.getElementById('intro');  
// 添加新連接到文本節(jié)點(diǎn)
// 首先,創(chuàng)建新連接元素
var myNewLink = document.createElement('a'); // <a/>  
myNewLink.; // <a />  
myNewLink.appendChild(document.createTextNode('Visit Google')); 
// <a >Visit Google</a>  
// 將內(nèi)容附件到文本節(jié)點(diǎn)
myIntro.appendChild(myNewLink);

另外 DOM 里還有一個(gè) insertBefore 方法用于再節(jié)點(diǎn)前面附件內(nèi)容,通過 insertBefore 和 appendChild 我們可以實(shí)現(xiàn)自己的 insertAfter 函數(shù):

// 'Target'是DOM里已經(jīng)存在的元素
// 'Bullet'是要插入的新元素
function insertAfter(target, bullet) {  
    target.nextSibling ?  
        target.parentNode.insertBefore(bullet, target.nextSibling)  
        : target.parentNode.appendChild(bullet);  
}  
// 使用了3目表達(dá)式:  
// 格式:條件?條件為true時(shí)的表達(dá)式:條件為false時(shí)的表達(dá)式

上面的函數(shù)首先檢查 target 元素的同級(jí)下一個(gè)節(jié)點(diǎn)是否存在,如果存在就在該節(jié)點(diǎn)前面添加 bullet 節(jié)點(diǎn),如果不存在,就說明 target 是最后一個(gè)節(jié)點(diǎn)了,直接在后面 append 新節(jié)點(diǎn)就可以了。DOM API 沒有給提供 insertAfter 是因?yàn)檎娴臎]必要了——我們可以自己創(chuàng)建。

DOM 操作有很多內(nèi)容,上面你看到的只是其中一部分。

Event 事件

瀏覽器事件是所有 web 程序的核心,通過這些事件我們定義將要發(fā)生的行為,如果在頁面里有個(gè)按鈕,那點(diǎn)擊此按鈕之前你需要驗(yàn)證表單是否合法,這時(shí)候就可以使用 click 事件,下面列出的最標(biāo)準(zhǔn)的事件列表:

注:正如我們上章所說的,DOM 和 JavaScript 語言是 2 個(gè)單獨(dú)的東西,瀏覽器事件是 DOM API 的一部分,而不是 JavaScript 的一部分。

鼠標(biāo)事件

  1. ‘mousedown’ – 鼠標(biāo)設(shè)備按下一個(gè)元素的時(shí)候觸發(fā) mousedown 事件。
  2. ‘mouseup’ – 鼠標(biāo)設(shè)備從按下的元素上彈起的時(shí)候觸發(fā) mouseup 事件。
  3. ‘click’ – 鼠標(biāo)點(diǎn)擊元素的時(shí)候觸發(fā) click 事件。
  4. ‘dblclick’ – 鼠標(biāo)雙擊元素的時(shí)候觸發(fā) dblclick 事件。
  5. ‘mouseover’ – 鼠標(biāo)移動(dòng)到某元素上的時(shí)候觸發(fā) mouseover 事件。
  6. ‘mouseout’ – 鼠標(biāo)從某元素離開的時(shí)候觸發(fā) mouseout 事件。
  7. ‘mousemove’ – 鼠標(biāo)在某元素上移動(dòng)但未離開的時(shí)候觸發(fā) mousemove 事件。

鍵盤事件

  1. ‘keypress’ – 按鍵按下的時(shí)候觸發(fā)該事件。
  2. ‘keydown’ – 按鍵按下的時(shí)候觸發(fā)該事件,并且在 keypress 事件之前。
  3. ‘keyup’ – 按鍵松開的時(shí)候觸發(fā)該事件,在 keydown 和 keypress 事件之后。

表單事件

  1. ‘select’ – 文本字段(input, textarea等)的文本被選擇的時(shí)候觸發(fā)該事件。
  2. ‘change’ – 控件失去 input 焦點(diǎn)的時(shí)候觸發(fā)該事件(或者值被改變的時(shí)候)。
  3. ‘submit’ – 表單提交的時(shí)候觸發(fā)該事件。
  4. ‘reset’ – 表單重置的時(shí)候觸發(fā)該事件。
  5. ‘focus’ – 元素獲得焦點(diǎn)的時(shí)候觸發(fā)該事件,通常來自鼠標(biāo)設(shè)備或 Tab 導(dǎo)航。
  6. ‘blur’ – 元素失去焦點(diǎn)的時(shí)候觸發(fā)該事件,通常來自鼠標(biāo)設(shè)備或 Tab 導(dǎo)航。

其它事件

  1. ‘load’ – 頁面加載完畢(包括內(nèi)容、圖片、frame、object)的時(shí)候觸發(fā)該事件。
  2. ‘resize’ – 頁面大小改變的時(shí)候觸發(fā)該事件(例如瀏覽器縮放)。
  3. ‘scroll’ – 頁面滾動(dòng)的時(shí)候觸發(fā)該事件。
  4. ‘unload’ – 從頁面或 frame 刪除所有內(nèi)容的時(shí)候觸發(fā)該事件(例如離開一個(gè)頁面)。

還有很多各種各樣的事件,上面展示的事件是我們?cè)?JavaScript 里最常用的事件,有些事件在跨瀏覽器方面可能有所不同。還有其它瀏覽器實(shí)現(xiàn)的一些屬性事件,例如 Gecko 實(shí)現(xiàn)的 DOMContentLoaded 或 DOMMouseScroll 等,Gecko 的詳細(xì)事件列表請(qǐng)查看這里。

事件處理

我們將了事件,但是還沒有將到如何將處理函數(shù)和事件管理起來,使用這些事件之前,你首先要注冊(cè)這些事件句柄,然后描述該事件發(fā)生的時(shí)候該如何處理,下面的例子展示了一個(gè)基本的事件注冊(cè)模型:

基本事件注冊(cè):

<!-- HTML -->  
<button id="my-button">Click me!</button>  
// JavaScript:  
var myElement = document.getElementById('my-button');
// 事件處理句柄:  
function buttonClick() {
    alert('You just clicked the button!');
}
// 注冊(cè)事件
myElement.onclick = buttonClick; 

使用 document.getElementById 命令,通過 ID=my-button 獲取該 button 對(duì)象,然后創(chuàng)建一個(gè)處理函數(shù),隨后將該函數(shù)賦值給該 DOM 的 onclick 屬性。就這么簡單!

基本事件注冊(cè)是非常簡單的,在事件名稱前面添加前綴 on 作為 DOM 的屬性就可以使用了,這是事件處理的基本核心,但下面的代碼我不推薦使用:

<button onclick="return buttonClick()">Click me!</button>

上述 Inline 的事件處理方式不利用頁面維護(hù),建議將這些處理函數(shù)都封裝在單獨(dú)的 js 文件,原因和CSS樣式的一樣的。

高級(jí)事件注冊(cè):

別被標(biāo)題迷惑了,“高級(jí)”不意味著好用,實(shí)際上上面討論的基本事件注冊(cè)是我們大部分時(shí)候用的方式,但有一個(gè)限制:不能綁定多個(gè)處理函數(shù)到一個(gè)事件上。這也是我們要講解該小節(jié)原因:

該模型運(yùn)行你綁定多個(gè)處理句柄到一個(gè)事件上,也就是說一個(gè)事件觸發(fā)的時(shí)候多個(gè)函數(shù)都可以執(zhí)行,另外,該模型也可以讓你很容易里刪除某個(gè)已經(jīng)綁定的句柄。

嚴(yán)格來說,有 2 種不同的模型:W3C 模型和微軟模型,除 IE 之外 W3C 模型支持所有的現(xiàn)代瀏覽器,而微軟模型只支持 IE,使用 W3C 模型的代碼如下:

// 格式:target.addEventListener( type, function, useCapture );  
// 例子:  
var myIntro = document.getElementById('intro');
myIntro.addEventListener('click', introClick, false);

使用 IE 模型的代碼如下:

// 格式: target.attachEvent ( 'on' + type, function );  
// 例子:  
var myIntro = document.getElementById('intro');
myIntro.attachEvent('onclick', introClick);

introClick 的代碼如下:

function introClick() {  
    alert('You clicked the paragraph!');  
}

事實(shí)上,要做出通用的話,我們可以自定義一個(gè)函數(shù)以支持跨瀏覽器:

function addEvent(elem, type, fn) {
    if (elem.attachEvent) {
        elem.attachEvent('on' + type, fn);
        return;
    }
    if (elem.addEventListener) {
        elem.addEventListener(type, fn, false);
    }
}

該函數(shù)首先檢查 attachEvent 和 addEventListener 屬性,誰可以就用誰,這兩種類型的模型都支持刪除句柄功能,參考下面的 removeEvent 函數(shù)。

function removeEvent(elem, type, fn) {
    if (elem.detachEvent) {
        elem.detachEvent('on' + type, fn);
        return;
    }
    if (elem.removeEventListener) {
        elem.removeEventListener(type, fn, false);
    }
}

你可以這樣使用:

var myIntro = document.getElementById('intro');
addEvent(myIntro, 'click', function () {
    alert('YOU CLICKED ME!!!');
});

注意到我們傳入了一個(gè)匿名函數(shù)作為第三個(gè)參數(shù),JavaScript 運(yùn)行我們定義和執(zhí)行匿名函數(shù),這種匿名函數(shù)特別適合作為參數(shù)傳遞,實(shí)際上我們也可以傳遞有名的函數(shù)(代碼如下),但是你們函數(shù)更容易做。

如果你只想在第一次 click 的時(shí)候觸發(fā)一個(gè)函數(shù),你可以這么做:

// 注意:前提是我們已經(jīng)定于好了addEvent/removeEvent函數(shù)
// (定義好了才能使用哦)  
var myIntro = document.getElementById('intro');
addEvent(myIntro, 'click', oneClickOnly);
function oneClickOnly() {
    alert('WOW!');
    removeEvent(myIntro, 'click', oneClickOnly);
} 

當(dāng)?shù)谝淮斡|發(fā)以后,我們就立即刪除該句柄,但是有匿名函數(shù)的話卻很難將自身的引用刪除,不過實(shí)際上可以通過如下的形式來做(只不過有點(diǎn)麻煩):

addEvent(myIntro, 'click', function () {
    alert('WOW!');
    removeEvent(myIntro, 'click', arguments.callee);
});

這里我們是有了 arguments 對(duì)象的 callee 屬性,arguments 對(duì)象包含了所有傳遞進(jìn)來的參數(shù)以及該函數(shù)自身(callee),這樣我們就可以放心地刪除自身的引用了。

關(guān)于 W3C 和微軟模型還有其他的少許差異,比如 this,在觸發(fā)事件的時(shí)候函數(shù)中的 this 一般都是該元素上下文,,也就說 this 引用該元素自身,在基本事件注冊(cè)和 W3C 模型中都沒有問題,但在微軟模型的實(shí)現(xiàn)里卻可能出錯(cuò),請(qǐng)參考如下代碼:

function myEventHandler() {
    this.style.display = 'none';
}
// 正常工作,this是代表該元素
myIntro.onclick = myEventHandler;
// 正常工作,this是代表該元素
myIntro.addEventListener('click', myEventHandler, false);
// 不正常,這時(shí)候的this是代表Window對(duì)象
myIntro.attachEvent('onclick', myEventHandler);

這里有一些方式可以避免這個(gè)問題,最簡單的方式是使用前面的基本事件注冊(cè)方式,或者是再做一個(gè)通用的 addEvent,通用代碼請(qǐng)參考 John ResigDean Edward 的文章。

Event 對(duì)象

另外一個(gè)非常重要的內(nèi)容是 Event 對(duì)象,當(dāng)事件發(fā)生的時(shí)候出發(fā)某個(gè)函數(shù),該 Event 對(duì)象將自動(dòng)在函數(shù)內(nèi)可用,該對(duì)象包含了很多事件觸發(fā)時(shí)候的信息,但I(xiàn)E卻沒有這么實(shí)現(xiàn),而是自己實(shí)現(xiàn)的,IE 瀏覽器是通過全局對(duì)象 window 下的 event 屬性來包含這些信息,雖然不是大問題,但我們也需要注意一下,下面的代碼是兼容性的:

function myEventHandler(e) {
    // 注意參數(shù)e
    // 該函數(shù)調(diào)用的時(shí)候e是event對(duì)象(W3C實(shí)現(xiàn))
    // 兼容IE的代碼
    e = e || window.event;
    // 現(xiàn)在e就可以兼容各種瀏覽器了
}
// 這里可以自由地綁定事件了

這里判斷 e 對(duì)象(Event 對(duì)象)是否存在我們使用了 OR 操作符:如果 e 不存在(為 null,undefined,0 等)的時(shí)候,將 window.event 賦值給 e,否則的話繼續(xù)使用 e。通過這方式很快就能在多瀏覽器里得到真正的 Event 對(duì)象,如果你不喜歡這種方式的話,你可以使用 if 語句來處理:

if (!e) {
    e = window.event;
} // 沒有else語句,因?yàn)閑在其它瀏覽器已經(jīng)定義了

另外 Event 對(duì)象下的命令和屬性都很有用,遺憾的是不不能全兼容瀏覽器,例如當(dāng)你想取消默認(rèn)的行為的時(shí)候你可以使用 Event 對(duì)象里的 preventDefault()方法,但 IE 里不得不使用對(duì)象的 returnValue 屬性值來控制,兼容代碼如下:

function myEventHandler(e) {
    e = e || window.event;
    // 防止默認(rèn)行為
    if (e.preventDefault) {
        e.preventDefault();
    } else {
        e.returnValue = false;
    }
}

例如,當(dāng)你點(diǎn)擊一個(gè)連接的時(shí)候,默認(rèn)行為是導(dǎo)航到 href 里定義的地址,但有時(shí)候你想禁用這個(gè)默認(rèn)行為,通過 returnValue 和 preventDefault 就可以實(shí)現(xiàn),Event 對(duì)象里的很多屬性在瀏覽器里都不兼容,所以很多時(shí)候需要處理這些兼容性代碼。

注意:現(xiàn)在很多 JS 類庫都已經(jīng)封裝好了 e.preventDefault 代碼,也就是說在 IE 里可用了,但是原理上依然是使用 returnValue 來實(shí)現(xiàn)的。

事件冒泡

事件冒泡,就是事件觸發(fā)的時(shí)候通過 DOM 向上冒泡,首先要知道不是所有的事件都有冒泡。事件在一個(gè)目標(biāo)元素上觸發(fā)的時(shí)候,該事件將觸發(fā)一一觸發(fā)祖先節(jié)點(diǎn)元素,直到最頂層的元素:

http://wiki.jikexueyuan.com/project/javascript-depth-understanding/images/16.png" alt="" />

如圖所示,如果 a 連接被點(diǎn)擊,觸發(fā)觸發(fā)連接的 click 事件,然后觸發(fā) p 的 click 事件,以此再觸發(fā) div 和 body 的 click 事件。順序不變,而且不一定是在同時(shí)觸發(fā)的。

這樣你就可以利用該特性去處理自己的邏輯了,并且再任何時(shí)候都可以停止冒泡,比如,如果你只想冒泡到文本節(jié)點(diǎn)上,而不再進(jìn)一步冒泡,你可以在 p 的 click 事件處理函數(shù)里丁停止冒泡:

function myParagraphEventHandler(e) {
    e = e || window.event;
    // 停止向上冒泡
    if (e.stopPropagation) {
        // W3C實(shí)現(xiàn)  
        e.stopPropagation();
    } else {
        // IE實(shí)現(xiàn)  
        e.cancelBubble = true;
    }
}
// 使用我們自定義的addEvent函數(shù)將myParagraphEventHandler綁定到click事件上:  
addEvent(document.getElementsByTagName('p')[0], 'click', myParagraphEventHandler);

事件委托

舉例來說,如果你有一個(gè)很多行的大表格,在每個(gè) <tr> 上綁定點(diǎn)擊事件是個(gè)非常危險(xiǎn)的想法,因?yàn)樾阅苁莻€(gè)大問題。流行的做法是使用事件委托。事件委托描述的是將事件綁定在容器元素上,然后通過判斷點(diǎn)擊的 target 子元素的類型來觸發(fā)相應(yīng)的事件。

var myTable = document.getElementById('my-table');
myTable.onclick = function () {
    // 處理瀏覽器兼容
    e = e || window.event;
    var targetNode = e.target || e.srcElement;
    // 測(cè)試如果點(diǎn)擊的是TR就觸發(fā)
    if (targetNode.nodeName.toLowerCase() === 'tr') {
        alert('You clicked a table row!');
    }
}

事件委托依賴于事件冒泡,如果事件冒泡到 table 之前被禁用的話,那上面的代碼就無法工作了。

總結(jié)

本章我們覆蓋到了 DOM 元素的操作以及相關(guān)的瀏覽器事件模型,希望大家能對(duì) DOM 有了進(jìn)一步的了解。