**DOM**:Document Object Model
[[mozilla.org]](https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction)
文檔對象模型 (DOM) 是HTML和XML文檔的編程接口。它提供了對文檔的結構化的表述,并定義了一種方式可以使從程序中對該結構進行訪問,從而改變文檔的結構,樣式和內容。DOM 將文檔解析為一個由節點和對象(包含屬性和方法的對象)組成的結構集合。簡言之,它會將web頁面和腳本或程序語言連接起來。
一個web頁面是一個文檔。這個文檔可以在瀏覽器窗口或作為HTML源碼顯示出來。但上述兩個情況中都是同一份文檔。文檔對象模型(DOM)提供了對同一份文檔的另一種表現,存儲和操作的方式。 DOM是web頁面的完全的面向對象表述,它能夠使用如 JavaScript等腳本語言進行修改。
所有操作和創建web頁面的屬性,方法和事件都會被組織成對象的形式(例如, ``document`` 對象表示文檔本身, ``table`` 對象實現了特定的 ``HTMLTableElement`` DOM 接口來訪問HTML 表格等)。下述介紹基于 Gecko瀏覽器的 DOM 面向對象引用。
----
目錄:
[TOC]
----
## DOM 和 JavaScript
DOM 并不是一個編程語言,但如果沒有DOM, JavaScript 語言也不會有任何網頁,XML頁面以及涉及到的元素的概念或模型。在文檔中的每個元素— 包括整個文檔,文檔頭部, 文檔中的表格,表頭,表格中的文本 — 都是文檔所屬于的文檔對象模型(DOM)的一部分,因此它們可以使用DOM和一個腳本語言如 JavaScript,來訪問和處理。
開始的時候,JavaScript和DOM是交織在一起的,但它們最終演變成了兩個獨立的實體。JavaScript可以訪問和操作存儲在DOM中的內容,因此我們可以寫成這個近似的等式:
>[info] API (web 或 XML 頁面) = DOM + JS (腳本語言)
DOM 被設計成與特定編程語言相獨立,使文檔的結構化表述可以通過單一,一致的API獲得。盡管我們在本參考文檔中會專注于使用JavaScript, 但DOM 也可以使用其他的語言來實現, 以Python為例,代碼如下:
~~~Python
# Python DOM example
import xml.dom.minidom as m
doc = m.parse("C:\\Projects\\Py\\chap1.xml");
doc.nodeName # DOM property of document object;
p_list = doc.getElementsByTagName("para");
~~~
獲取更多在網頁上使用JavaScript的信息,可以參考 [JavaScript technologies overview](https://developer.mozilla.org/zh-CN/docs/%E4%BD%BF%E7%94%A8Javascript%E5%92%8CDOM_Interfaces%E6%9D%A5%E5%A4%84%E7%90%86HTML).
## 如何訪問 DOM?
每個web瀏覽器都會使用一些文檔對象模型,從而使頁面可以被腳本語言訪問。
當您在創建一個腳本時-無論是使用內嵌 ``<script>``元素或者使用在web頁面腳本加載的方法— 您都可以使用`` document`` 或 ``window ``元素的API來操作文檔本身或獲取文檔的子類(web頁面中的各種元素)。
## 重要的數據類型
需要注意在API中傳入的不同的數據類型。在API參考文檔中的語法實例通常會使用``element(s) ``指代節點,使用``nodeList(s)``或 element(s)來指代節點數組,使用 ``attribute(s)``來指代屬性節點。
下面的表格簡單則描述了這些數據類型。
名稱 | 說明 |
------------| --------
``document`` | 當一個成員返回 ``document``對象 (例如,元素的 ownerDocument 屬性返回它所屬于的 ``document``) ,這個對象就是``document``對象本身。 [DOM document Reference](https://developer.mozilla.org/en-US/docs/Web/API/document) 一章對 document 對象進行了描述。
``element`` | ``element`` 是指由 DOM API 中成員返回的類型為 element 的一個元素或節點。 例如, ``document.createElement()`` 方法會返回一個 ``node`` 的對象引用,也就是說這個方法返回了在DOM中創建的``element``。 ``element`` 對象實現了 DOM ``Element`` 接口以及更基本的 ``Node`` 接口。
``nodeList`` | ``nodeList`` 是一個元素的數組,如從`` document.getElementsByTagName()``方法返回的就是這種類型。 ``nodeList`` 中的條目由通過下標有兩種方式進行訪問:<br>- list.item(1) <br>- list[1] <br>兩種方式是等價的,第一種方式中 ``item()`` 是 ``nodeList`` 對象中的單獨方法。 后面的方式則使用了經典的數組語法來獲取列表中的第二個條目。
``attribute`` | 當 ``attribute`` 通過成員函數 (例如,通過`` createAttribute()``方法) 返回時,它是一個為屬性暴露出專門接口的對象引用。DOM中的屬性也是節點,就像元素一樣,只不過可能會很少使用它。
``namedNodeMap`` | ``namedNodeMap`` 和數組類似,但是條目是由name或index訪問的,雖然后一種方式僅僅是為了枚舉方便,因為在 list 中本來就沒有特定的順序。 出于這個目的, ``namedNodeMap`` 有一個 item() 方法,也可以從 `` namedNodeMap`` 添加或移除條目。
## DOM 接口
許多對象會對多個不同的接口進行實現。以table對象舉例:
table對象實現了 HTML Table Element Interface, 其中包括``createCaption`` 和 ``insertRow`` 方法。
table對象同時也是一個HTML元素, table 也實現了 ``Element ``接口。
最后,由于HTML元素對DOM來說也是組成web頁面或XML頁面節點樹中的一個節點, table元素也實現更基本的 ``Node`` 接口, ``Element`` 對象即發源于此接口。
正如下面的代碼,當得到一個 table 對象的引用時,經常會輪流使用對象上的三個不同的接口函數。
~~~JavaScript
var table = document.getElementById("table");
var tableAttrs = table.attributes; // Node/Element interface
for (var i = 0; i < tableAttrs.length; i++) {
// HTMLTableElement interface: border attribute
if(tableAttrs[i].nodeName.toLowerCase() == "border")
table.border = "1";
}
// HTMLTableElement interface: summary attribute
table.summary = "note: increased border";
~~~
**DOM中核心接口**
在DOM編程時,通常使用的最多的就是 Document和 window 對象。
``window`` 對象表示瀏覽器中的內容,而 ``document ``對象是文檔本身的根節點。``Element`` 繼承了通用的 ``Node`` 接口, 將這兩個接口結合后就提供了許多方法和屬性可以供單個元素使用。在處理這些元素所對應的不同類型的數據時,這些元素可能會有專用的接口,如上節中的 table 對象的例子。
下面是在web和XML頁面腳本中使用DOM時,一些常用的API簡要列表:
- window.content
- window.onload
- window.dump()
- window.scrollTo()
- document.getElementById(id)
- document.getElementsByTagName(name)
- document.createElement(name)
- parentNode.appendChild(node)
- element.innerHTML
- element.style.left
- element.setAttribute()
- element.getAttribute()
- element.addEventListener()
## DOM與模板
在網頁的一般開發流程中,我們通常會通過 `JS` 操作 `DOM` (對應 HTML 的描述產生的樹),以引起界面的一些變化響應用戶的行為。
例如,用戶點擊某個按鈕的時候,`JS` 會記錄一些狀態到 `JS` 變量里邊,同時通過 DOM API 操控 `DOM` 的屬性或者行為,進而引起界面一些變化。
但是,當項目越來越大的時候,JS代碼中會充斥著非常多的界面交互邏輯和程序的各種狀態變量,顯然這不是一個很好的開發模式,因此就有了 MVVM 的開發模式(例如 React, Vue),提倡把渲染和邏輯分離。
簡單來說就是不要再讓 JS 直接操控 DOM,JS 只需要管理狀態即可,然后再通過一種模板語法來描述狀態和界面結構的關系即可。
微信小程序的框架就用到了這個思路,如果需要把一個 `Hello World` 的字符串顯示在界面上。
WXML 是這么寫 :
~~~xml
<text>{{msg}}</text>
~~~
JS 只需要管理狀態即可:
~~~javascript
this.setData({ msg: "Hello World" })
~~~
通過 `{{ }}` 的語法把一個變量綁定到界面上,我們稱為數據綁定。僅僅通過數據綁定還不夠完整的描述狀態和界面的關系,還需要 `if/else`, `for`等控制能力,在小程序里邊,這些控制能力都用 `wx:` 開頭的屬性來表達。
- WebAPP
- Linux Command
- 入門
- 處理文件
- 查找文件單詞
- 環境
- 聯網
- Linux
- Linux目錄配置標準:FHS
- Linux文件與目錄管理
- Linux賬號管理與ACL權限設置
- Linux系統資源查看
- 軟件包管理
- Bash
- Daemon/Systemd
- ftp
- Apache
- MySQL
- Command
- Replication
- mysqld
- remote access
- remark
- 限制
- PHP
- String
- Array
- Function
- Class
- File
- JAVA
- Protocals
- http
- mqtt
- IDE
- phpDesigner
- eclipse
- vscode
- Notepad++
- WebAPI
- Javasript
- DOM
- BOM
- Event
- Class
- Module
- Ajax
- Fetch
- Promise
- async/await
- Statements and declarations
- Function
- Framwork
- jQurey
- Types
- Promise
- BootStrap
- v4
- ThinkPHP5
- install
- 定時任務
- CodeIgniter
- React.js
- node.js
- npm
- npm-commands
- npm-folder
- package.json
- Docker and private modules
- module
- webpack.js
- install
- configuration
- package.json
- entry
- modules
- plugins
- Code Splitting
- loaders
- libs
- API
- webpack-cli
- Vue.js
- install
- Compile
- VueAPI
- vuex
- vue-router
- vue-devtools
- vue-cli
- vue-loader
- VDOM
- vue-instance
- components
- template
- Single-File Components
- props
- data
- methods
- computed
- watch
- Event-handling
- Render Func
- remark
- 案例學習
- bootstrap-vue
- modal
- fontAwesome
- Hosting Font Awesome Yourself
- using with jquery
- using with Vue.js
- HTML
- CSS
- plugins
- Chart.js
- D3.js
- phpSpreadSheet
- Guzzle
- Cmder
- Git
- git命令
- git流程
- Postman
- Markdown
- Regular Expressions
- PowerDesigner
- 附錄1-學習資源