整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          面試官:你能基于React/Vue手寫一個(gè)全局提示(Message)組件嗎?

          本文是我寫組件設(shè)計(jì)的第十一篇文章, 今天帶大家實(shí)現(xiàn)一個(gè)同樣比較特殊的組件——全局提示(Message)組件。 我們看到的組件效果可能是這樣的:

          由于全局提示組件的設(shè)計(jì)原理和我上一篇寫的精通React/Vue系列之手把手帶你實(shí)現(xiàn)一個(gè)功能強(qiáng)大的通知提醒框(Notification)是類似的,區(qū)別主要是布局和配置參數(shù),所以說(shuō)細(xì)節(jié)和實(shí)現(xiàn)原理部分就不在這篇文章介紹了,本文主要介紹設(shè)計(jì)思路和設(shè)計(jì)的方法。

          基礎(chǔ)組件庫(kù)主要按以下分類來(lái)劃分

          • 通用型組件: 比如Button, Icon等.
          • 布局型組件: 比如Grid, Layout布局等.
          • 導(dǎo)航型組件: 比如面包屑Breadcrumb, 下拉菜單Dropdown, 菜單Menu等.
          • 數(shù)據(jù)錄入型組件: 比如form表單, Switch開(kāi)關(guān), Upload文件上傳等.
          • 數(shù)據(jù)展示型組件: 比如Avator頭像, Table表格, List列表等.
          • 反饋型組件: 比如Progress進(jìn)度條, Drawer抽屜, Modal對(duì)話框等.
          • 其他業(yè)務(wù)類型

          熟悉以上分類法是設(shè)計(jì)任何組件系統(tǒng)的前提,不管你是從零到一開(kāi)發(fā)前端團(tuán)隊(duì)的UI庫(kù),還是基于已有組件庫(kù)二次開(kāi)發(fā)業(yè)務(wù)組件,以上分類法則同樣適用。

          本文將會(huì)使用React來(lái)開(kāi)發(fā)該組件,也會(huì)使用到Javascript中常用的一些設(shè)計(jì)模式,比如單例模式,但是不管你使用什么框架來(lái)實(shí)現(xiàn),原理都是通用的,如果感興趣的朋友可以用vue也實(shí)現(xiàn)一下。如果對(duì)設(shè)計(jì)模式不是很了解,可以參考我往前的文章。

          正文

          在開(kāi)始組件設(shè)計(jì)之前希望大家對(duì)css3和js有一定的基礎(chǔ),并了解基本的react/vue語(yǔ)法.我們先來(lái)解構(gòu)一下Message組件, 一個(gè)Message分為以下幾個(gè)部分:


          每一個(gè)區(qū)塊都可以自定義配置, 也可以組合其他組件.我們還可以配置全局提示出現(xiàn)在頂部的偏移量,類似于antd的組件一樣。并且我們都知道,antd或者element這種組件庫(kù),會(huì)自帶一些主題狀態(tài),來(lái)提高用戶的使用效率,比如會(huì)有success(成功狀態(tài)),warning(警告狀態(tài)),error(錯(cuò)誤狀態(tài)),info(通知狀態(tài))等,那么我們自己實(shí)現(xiàn)的全局提示(Message)組件也因該具備這些功能。

          以下是筆者使用React實(shí)現(xiàn)后的Message組件效果:


          接下來(lái)我們來(lái)看看通知提醒框(Message)的具體設(shè)計(jì)思路。

          1. Message組件設(shè)計(jì)思路

          按照之前筆者總結(jié)的組件設(shè)計(jì)原則,我們第一步是要確認(rèn)需求. 通知提醒框(Message)組件一般會(huì)有如下需求點(diǎn):

          • 能控制Message自動(dòng)關(guān)閉的時(shí)間
          • 能配置Message渲染節(jié)點(diǎn)的輸出位置
          • 能自定義關(guān)閉圖標(biāo)
          • 可以手動(dòng)選擇全局提示類型
          • 能自定義全局提示的偏移量
          • 能設(shè)置全局提示的信息文本
          • 能自定義全局提示的Icon
          • 全局提示點(diǎn)擊時(shí)提供回調(diào)函數(shù)
          • 全局提示關(guān)閉時(shí)提供回調(diào)函數(shù)
          • 能手動(dòng)銷毀通知框

          需求收集好之后,作為一個(gè)有追求的程序員, 會(huì)得出如下線框圖:

          具體的設(shè)計(jì)細(xì)節(jié)可以參考我的上一篇Notification組件設(shè)計(jì)的文章。

          2. 基于react實(shí)現(xiàn)一個(gè)全局提示(Message)組件

          組件的核心部分我們還是采用React Notification的模式。

          2.1 搭建通知提醒框(Notification)的基本骨架

          首先按照筆者的代碼風(fēng)格,一般會(huì)考慮組件設(shè)計(jì)的框架,然后再一步步往里面填充內(nèi)容和邏輯。通過(guò)這種漸進(jìn)式的設(shè)計(jì)思路,能讓我們邏輯更嚴(yán)謹(jǐn),更清晰。具體代碼如下:

          import Notification from 'rc-notification'
          import './index.less'
          
          const xMessage = (function() {
            let message = null
            /**
               * notice類型彈窗
               * @param {config}  object 提示框配置屬性
               *   @param {type} string 提示窗類型
               *   @param {btn}  ReactNode 自定義關(guān)閉按鈕
               *   @param {className}  string 自定義 CSS class
               *   @param {duration}  number 默認(rèn) 4.5 秒后自動(dòng)關(guān)閉,配置為 null 則不自動(dòng)關(guān)閉
               *   @param {getContainer}  HTMLNode 配置渲染節(jié)點(diǎn)的輸出位置
               *   @param {icon}  ReactNode 自定義圖標(biāo)
               *   @param {key}  string 當(dāng)前提示唯一標(biāo)志
               *   @param {content}  string|ReactNode 提示標(biāo)題,必選
               *   @param {onClose}  func 點(diǎn)擊默認(rèn)關(guān)閉按鈕時(shí)觸發(fā)的回調(diào)函數(shù)
               *   @param {onClick}  func 點(diǎn)擊提示時(shí)觸發(fā)的回調(diào)函數(shù)
               *   @param {top}  number 消息從頂部彈出時(shí),距離頂部的位置,單位像素
               *   @param {closeIcon}  ReactNode 自定義關(guān)閉圖標(biāo)
               */
            const pop = (config) => {
              const {
                type, className,
                duration = 4.5,
                getContainer = () => document.body,
                icon, key, content, onClose, onClick,
                top, closable = true, closeIcon
              } = config
              message.notice({
                content: <div className={classnames('xMessage', className )}>
                  <div className={classnames('iconWrap', type)}>
                      <Icon type={iconType[type]} />
                    </div>
                  <div className="xNoticeTit">
                    { content }
                  </div>
                </div>,
                key, closable, getContainer,
                onClose() {
                  onClose && onClose()
                },
                onClick() {
                  onClick && onClick()
                },
                closeIcon, duration, style: { top }
              })
            }
          
            /**
               * 提示提示組件, 全局參數(shù)
               * @param {duration} number 默認(rèn)自動(dòng)關(guān)閉延時(shí),單位秒
               * @param {getContainer} HTMLNode 配置渲染節(jié)點(diǎn)的輸出位置,默認(rèn)document.body
               * @param {closeIcon} HTMLNode 自定義關(guān)閉圖標(biāo)
            */
            const config = (config) => {}
            const remove = (key) => {}
            const destroy = () => {}
          
            if(message) {
              return {
                config, pop, remove, destroy
              }
            }
            // 如果為創(chuàng)建實(shí)例,則創(chuàng)建默認(rèn)實(shí)例
            Notification.newInstance({}, (notice) => message = notice)
          
            return {
              config, pop, remove, destroy
            }
          })()
          
          export default xMessage

          首先我們根據(jù)需求把屬性羅列出來(lái), 通過(guò)分析我們因該對(duì)外提供四個(gè)接口供開(kāi)發(fā)者使用,分別為: config —— Message全局配置,用來(lái)控制全局的偏移量,樣式,渲染容器等; pop —— 用來(lái)創(chuàng)建全局提示實(shí)例的方法,同時(shí)可以控制實(shí)例的屬性 remove —— 用來(lái)刪除指定實(shí)例 destroy —— 用來(lái)銷毀全局的Message

          首先我們來(lái)實(shí)現(xiàn)一下config:

          const config = (config) => {
            const { duration, getContainer, closeIcon } = config
          
            Notification.newInstance({
              getContainer: getContainer,
              duration: duration || 4.5,
              closeIcon
            }, (notice) => message = notice)
          }
          

          當(dāng)然我們還可以根據(jù)自己的需求去自定義擴(kuò)展。

          pop方法的實(shí)現(xiàn):

          const pop = (config) => {
              const {
                type,
                className,
                duration = 4.5,
                getContainer = () => document.body,
                icon,
                key,
                content,
                onClose,
                onClick,
                top,
                closable = true,
                closeIcon
              } = config
              message.notice({
                content: <div className={classnames('xMessage', className )}>
                  {
                    (icon || ['info', 'success', 'error', 'warning'].indexOf(type) > -1) &&
                    <div className={classnames('iconWrap', type)}>
                      {
                        icon ? icon : <Icon type={iconType[type]} />
                      }
                    </div>
                  }
                  <div className="xNoticeTit">
                    { content }
                  </div>
                </div>,
                key,
                closable,
                getContainer,
                onClose() {
                  onClose && onClose()
                },
                onClick() {
                  onClick && onClick()
                },
                closeIcon,
                duration,
                style: { top }
              })
            }
          

          該方法主要用來(lái)自定義創(chuàng)建全局消息的實(shí)例,我們可以這么調(diào)用:

          xNotification.pop({type: 'success', content: '你的請(qǐng)求被審批通過(guò)啦!'})
          

          實(shí)際效果如下:


          antd同樣的方式會(huì)這么調(diào)用:

          // antd
          Notification.info({//...})
          

          筆者之所以會(huì)這么做是因?yàn)閕nfo,success,warning這樣的狀態(tài)其實(shí)dom結(jié)構(gòu)完全可以復(fù)用,所以通過(guò)配置方式可以極大的減少冗余代碼。

          remove和destroy方法都比較簡(jiǎn)單,我們直接上代碼:

          const remove = (key) => {
              message.removeNotice(key)
            }
          
          const destroy = () => {
            message.destroy()
          }
          

          由上可以看出他們的實(shí)現(xiàn)都是基于message實(shí)例自帶的API。

          2.2 實(shí)現(xiàn)通知框類型type和自定義icon

          首先我們先定義一個(gè)類型和icon的映射關(guān)系:

          const iconType = {
              success: 'FaRegCheckCircle',
              warning: 'FaRegMeh',
              info: 'FaRegLightbulb',
              error: 'FaRegTimesCircle'
           }
          

          這四種類型對(duì)應(yīng)著不同的icon圖標(biāo)類型,那么我們就可以根據(jù)用戶傳入的類型來(lái)展示不同icon圖標(biāo)了:

          <div className={classnames('iconWrap', type)}>
              <Icon type={iconType[type]} />
          </div>

          不過(guò)我們還需要考慮的一點(diǎn)就是如果用戶傳入了自定義的icon,我們理論上應(yīng)該展示自定義icon,所以type因該和icon這兩個(gè)屬性是有聯(lián)系的。還有一種情況就是如果用戶即沒(méi)有配置type,有沒(méi)有傳入icon,那么實(shí)際上是不需要顯示icon的,綜合考慮之后我們的代碼如下:

          {
            (icon || ['info', 'success', 'error', 'warning'].indexOf(type) > -1) &&
            <div className={classnames('iconWrap', type)}>
              {
                icon ? icon : <Icon type={iconType[type]} />
              }
            </div>
          }

          實(shí)現(xiàn)效果如下圖:

          通過(guò)以上步驟, 全局提示(Message)組件就完成了.實(shí)現(xiàn)方式和Notification組件有很多相似點(diǎn),如果不懂的可以在評(píng)論區(qū)提問(wèn),筆者看到后會(huì)第一時(shí)間解答.

          2.3 使用全局提示(Message)組件

          我們可以通過(guò)如下方式使用它:

          <Button type="warning" onClick={
                  () => {
                      message.pop({
                          type: 'error',
                          content: '趣談前端學(xué)習(xí)打卡'
                      })
                  }
              }>錯(cuò)誤信息通知(error)</Button>

          配置全局屬性:

          import { message } from '@alex_xu/xui'
          
          message.config({ duration: 6 })
          

          筆者已經(jīng)將實(shí)現(xiàn)過(guò)的組件發(fā)布到npm上了,大家如果感興趣可以直接用npm安裝后使用,方式如下:

          npm i @alex_xu/xui
          
          // 導(dǎo)入xui
          import { 
            Button, Skeleton, Empty, Progress,
            Message, Tag, Switch, Drawer, Badge, Alert
          } from '@alex_xu/xui'
          

          該組件庫(kù)支持按需導(dǎo)入,我們只需要在項(xiàng)目里配置babel-plugin-import即可,具體配置如下:

          // .babelrc
          "plugins": [
            ["import", { "libraryName": "@alex_xu/xui", "style": true }]
          ]
          

          npm庫(kù)截圖如下:


          最后

          后續(xù)我將會(huì)繼續(xù)實(shí)現(xiàn)

          • table(表格),
            tooltip(工具提示條),
          • Skeleton(骨架屏),
          • form(form表單),
          • switch(開(kāi)關(guān)), 日期/日歷, *
          • 二維碼識(shí)別器組件

          等來(lái)復(fù)盤多年的組件化之旅.

          如果對(duì)于react/vue組件設(shè)計(jì)原理不熟悉的,可以參考我的之前寫的組件設(shè)計(jì)系列文章.

          筆我已經(jīng)將組件庫(kù)發(fā)布到npm上了, 大家可以通過(guò)npm安裝的方式體驗(yàn)組件.

          如果想獲取組件設(shè)計(jì)系列完整源碼, 或者想學(xué)習(xí)更多H5游戲, webpack,node,gulpcss3javascript,nodeJS,canvas數(shù)據(jù)可視化等前端知識(shí)和實(shí)戰(zhàn),歡迎在《趣談前端》學(xué)習(xí)討論,共同探索前端的邊界。

          時(shí)的工作中常會(huì)遇到一些系統(tǒng)集成的需求,需要在軟件平臺(tái)集成視頻監(jiān)控系統(tǒng)。而軟件開(kāi)發(fā)者往往不懂安防弱電系統(tǒng),不知道如何在自己的軟件界面中集成一些監(jiān)控的實(shí)時(shí)畫面。而監(jiān)控廠家提供的SDK比較復(fù)雜,很難在短時(shí)間完成集成的任務(wù)。最終導(dǎo)致軟件平臺(tái)的一些功能無(wú)法實(shí)現(xiàn),影響項(xiàng)目的質(zhì)量。

          本文提供的方法主要基于VLC播放器的ActiveX插件,通過(guò)這個(gè)插件,在網(wǎng)頁(yè)中調(diào)用攝像機(jī)的RTSP流,實(shí)現(xiàn)圖像的實(shí)時(shí)預(yù)覽,音頻的監(jiān)聽(tīng)等等功能。文章以海康的IP網(wǎng)絡(luò)攝像機(jī)為例給出具體的調(diào)用方法,供大家學(xué)習(xí)參照。

          VLC軟件下載

          登錄VLC官網(wǎng) https://www.videolan.org/,選擇windows(32位)版本下載。

          下載VLC軟件

          VLC軟件安裝(務(wù)必勾選插件)

          運(yùn)行安裝文件

          選擇軟件安裝位置

          一定記得要勾選網(wǎng)頁(yè)瀏覽器插件

          完成安裝

          網(wǎng)頁(yè)編輯

          可選用記事本(notepad)或?qū)I(yè)的編輯器,輸入如下代碼,保存為html網(wǎng)頁(yè)文件。

          <html>
          <body>
          
          <title>TESTVDEIO-1-TEST</title>
          <head>
          <table>
                      <tbody>
                      <caption>視頻監(jiān)控演示</caption>
                  <tr>
                      <td>
                      <object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
              <param name='mrl' value='rtsp://admin:q66668888@172.16.200.88:554/h264/ch1/main/av_stream' />
              <param name='volume' value='50' />
              <param name='autoplay' value='true' />
              <param name='loop' value='false' />
              <param name='fullscreen' value='false' />
              <param name='controls' value='false' />
                      </td>
                      <td>
                      <object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
              <param name='mrl' value='rtsp://admin:q66668888@172.16.200.89:554/h264/ch1/main/av_stream' />
              <param name='volume' value='50' />
              <param name='autoplay' value='true' />
              <param name='loop' value='false' />
              <param name='fullscreen' value='false' />
              <param name='controls' value='false' />
                      </td>
                  </tr>
                   <tr>
                      <td>
                      <object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
              <param name='mrl' value='rtsp://admin:q66668888@172.16.200.89:554/h264/ch1/main/av_stream' />
              <param name='volume' value='50' />
              <param name='autoplay' value='true' />
              <param name='loop' value='false' />
              <param name='fullscreen' value='false' />
              <param name='controls' value='false' />
                      </td>
                      <td>
                      <object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
              <param name='mrl' value='rtsp://admin:q66668888@172.16.200.88:554/h264/ch1/main/av_stream' />
              <param name='volume' value='50' />
              <param name='autoplay' value='true' />
              <param name='loop' value='false' />
              <param name='fullscreen' value='false' />
              <param name='controls' value='false' />
                      </td>
                  </tr>
              </tbody>
          </table>
                      </object>
          </body>
          </html>

          代碼編輯截圖

          ??低昍TSP調(diào)用格式


          具體請(qǐng)參看海康專業(yè)文檔

          瀏覽器測(cè)試

          先用Google Chrome瀏覽器測(cè)試,提示插件不支持。

          Chrome瀏覽器提示插件不受支持

          用微軟IE測(cè)試,需要安裝插件。

          IE瀏覽器提示要安裝ActiveX插件

          確認(rèn)安裝插件

          瀏覽器只顯示了第一個(gè)畫面。

          IE瀏覽器顯示不完整

          用編輯器測(cè)試,2種內(nèi)核都能正常顯示。

          編輯器里測(cè)試效果

          改用360瀏覽器,呈現(xiàn)2X2的畫面,實(shí)現(xiàn)最終的顯示效果。

          360瀏覽器顯示的最終效果圖

          結(jié)語(yǔ)

          本文參考了一些專業(yè)文章,就不一 一列出了,在這一并謝過(guò)!

          由于本人水平有限,有不對(duì)的地方敬請(qǐng)指正。文章旨在拋磚引玉,通過(guò)討論,相互學(xué)習(xí),共同進(jìn)步。


          我是WoNew弱電蝸牛,一名從業(yè)多年的弱電工程師,在頭條傳播弱電專業(yè)知識(shí)和行業(yè)信息,分享工作中的經(jīng)驗(yàn)和心得。
          喜歡我的文章或視頻,歡迎點(diǎn)贊和轉(zhuǎn)發(fā)。有疑問(wèn)或建議,也歡迎留言,我會(huì)盡力解答。

          內(nèi)容是《Web前端開(kāi)發(fā)之Javascript視頻》的課件,請(qǐng)配合大師哥《Javascript》視頻課程學(xué)習(xí)。

          Document 接口描述了任何類型的文檔的通用屬性與方法,根據(jù)不同的文檔類型(例如HTML、XML)提供了不同的API,比如,使用 "text/html" 作為內(nèi)容類型的HTML文檔,實(shí)現(xiàn)了 HTMLDocument,而XML文檔則實(shí)現(xiàn)了XMLDocument,HTMLDocument和XMLDocument接口都是繼承自Document接口;

          Javascript通過(guò)Document類型表示文檔;在瀏覽器中,document對(duì)象是Document的一個(gè)實(shí)例,更具體一點(diǎn),是HTMLDocument的一個(gè)實(shí)例,其表示整個(gè)HTML頁(yè)面;并且document對(duì)象也是window對(duì)象的一個(gè)屬性,可以將其作為全局對(duì)象來(lái)訪問(wèn);因此document對(duì)象,既屬于BOM又屬于DOM的對(duì)象;

          Document節(jié)點(diǎn)的特征:

          • nodeType的值為9
          • nodeName的值為#document
          • nodeValue的值為null
          • parentNode的值為null

          其子節(jié)點(diǎn)可能是一個(gè)DocumentType(最多一個(gè))、Element(最多一個(gè),即html)、ProcessingInstruction或Comment;

          console.log(document);  // 在FF控制臺(tái)可以看出是屬于HTMLDocument類型
          console.log(document.nodeType); // 0
          console.log(document.nodeName); // #document
          console.log(document.nodeValue);  // null
          console.log(document.parentNode);  // null
          console.log(document.childNodes.length);  // 2

          文檔的子節(jié)點(diǎn):

          DOM標(biāo)準(zhǔn)規(guī)定Document節(jié)點(diǎn)的子節(jié)點(diǎn)可以是DocumentType、Element、ProcessingInstruction或Comment;

          <!-- 這是一個(gè)comment -->
          <html lang="en">
          <head>
              <title>Document</title>
          </head>
          <body>
          <script>
          console.log(document.childNodes); // 使用FF查看 NodeList(3)
          </script>
          </body>
          </html>

          documentElement屬性:

          返回文檔直接子節(jié)點(diǎn),始終指向HTML頁(yè)面中的<html>元素,也就是文檔的根元素,并且它一定是文檔的根元素;

          // 注意:在HTML中的第二行有可能是注釋
          console.log(document.childNodes[2]);  // <html>
          console.log(document.documentElement);  // <html>
          console.log(document.lastChild);  // <html>

          借助這個(gè)只讀屬性,能方便地獲取到任意文檔的根元素;

          body屬性:

          作為HTMLDocument的實(shí)例,document對(duì)象還有一個(gè)body屬性,直接指向<body>;

          console.log(document.body);

          對(duì)于一個(gè)擁有<frameset>元素的文檔來(lái)說(shuō),返回的是最外層的<frameset>元素;

          另外,該屬性是可寫的,且為該屬性賦的值必須是一個(gè)<body>元素;

          // 如果HTML結(jié)構(gòu)為body id="oldBody",則:
          console.log(document.body.id);  // oldBody
          var newBody = document.createElement("body");
          newBody.id = "newBody";
          document.body = newBody;
          console.log(document.body.id);  // newBody

          head屬性:

          指向<head>元素,這個(gè)Document對(duì)象擴(kuò)展的一個(gè)屬性,類型為HTMLHeadElement;

          如果有多個(gè)<head>元素,則返回第一個(gè);

          document.head 是個(gè)只讀屬性,為該屬性賦值只會(huì)靜默失敗,如果在嚴(yán)格模式中,則會(huì)拋出TypeError異常;

          需要注意的是,如果文檔源代碼中未顯式的包含<head>和<body>元素,瀏覽器將隱式的創(chuàng)建它們;

          doctype屬性:

          該屬性是DocumentType 類型,表示了一個(gè)包含文檔類型的節(jié)點(diǎn)對(duì)象,指向<!DOCTYPE>標(biāo)簽;

          文檔當(dāng)中最多只有一個(gè)DocumentType元素;

          console.log(document.doctype);  // <!DOCTYPE html>
          console.log(document.doctype.nextSibling); // <html>
          console.log(document.childNodes[0]); // <!DOCTYPE html>

          如果存在文檔聲明,則將其作為document的第一個(gè)子節(jié)點(diǎn),解析DOCUMENTTYPE_NODE類型,如果沒(méi)有聲明,則為null;

          注:DocumentType對(duì)象不能動(dòng)態(tài)創(chuàng)建,它是只讀的;

          查找元素(選取文檔元素):

          在DOM中,取得特定的某個(gè)或某組元素,并執(zhí)行一些操作,這是最重要的應(yīng)用了;

          為了獲取文檔中的這些元素Element對(duì)象,DOM定義了許多方式,如:用指定的id屬性、name屬性、標(biāo)簽名、CSS類或CSS選擇器;

          取得元素的操作可以使用document對(duì)象的幾個(gè)方法來(lái)完成;Document類型為此提供了兩個(gè)方法;

          getElementById()方法:

          該方法接收一個(gè)參數(shù),即要獲取的元素的ID;如果找到就返回這個(gè)元素,類型是HTMLElement,如果不存在,則返回null;該參數(shù)ID是區(qū)分大小寫的;

          如果頁(yè)面中多個(gè)元素的ID值相同,只返回文檔中第一次出現(xiàn)的元素;

          var mydiv = document.getElementById("mydiv");
          console.log(mydiv);
          可以封裝一個(gè)通過(guò)ID查找多個(gè)元素的函數(shù),如:
          /**
          * 函數(shù)接受任意多的字符串參數(shù)
          * 返回一個(gè)對(duì)象
          * 如果一個(gè)id對(duì)應(yīng)的元素未定義,則拋出錯(cuò)誤
          */
          function getElements(/*ids...*/){
              var elements = {};  // 一個(gè)空map映射對(duì)象
              for(var i=0; i<arguments.length; i++){
                  var id = arguments[i];
                  var elt = document.getElementById(id);
                  if(elt == null)
                      throw new Error("No element with id:" + id);
                  elements[id] = elt;
              }
              return elements;
          }
          console.log(getElements("mydiv","mylist"));
          console.log(getElements("mydiv","mylist")["mydiv"]);

          getElementById方法不會(huì)搜索不在文檔中的元素;當(dāng)創(chuàng)建一個(gè)元素,并且分配ID后,必須要使用appendChild、insertBefore等方法把元素插入到文檔中,之后才能使用getElementById()方法獲取到;

          var elt = document.createElement("div");
          elt.id = "myelt";
          document.body.appendChild(elt);  // myelt,添加到文檔對(duì)后,才能被獲取到到
          var el = document.getElementById("myelt");
          console.log(el);  // null

          getElementsByName()方法:

          返回給定name 屬性的所有元素NodeList集合對(duì)象;

          var mytexts = document.getElementsByName("mytext");
          console.log(mytexts); // dom2.html:17 NodeList(2) [p, div]

          該方法定義在HTMLDocument類中,而不在Document類中,所以它只針對(duì)HTML文檔可用,也就是只有HTMLDocument類型才有的方法,在XML文檔中不可用;

          <fieldset>
              <legend>選擇你最喜歡的城市</legend>
              <ul>
                  <li><input type="radio" value="北京" name="city" id="beijing" />
                      <label for="beijing">北京</label></li>
                  <li><input type="radio" value="南京" name="city" id="nanjing" />
                      <label for="nanjing">南京</label></li>
                  <li><input type="radio" value="蚌埠" name="city" id="bengbu" />
                      <label for="bengbu">蚌埠</label></li>
              </ul>
          </fieldset>
          <script>
          var citys = document.getElementsByName("city");
          console.log(citys);
          </script>

          該方法返回的是NodeList對(duì)象,在NodeList中返回的元素按照在文檔中的順序排序的,所以可以使用方括號(hào)語(yǔ)法來(lái)取得每個(gè)元素;

          console.log(document.getElementsByName("city")[0]);

          但I(xiàn)E與Edge返回的是HTMLCollection;但namedItem()方法是屬于HTMLCollection類型的,所以,非IE調(diào)用namedItem()方法會(huì)拋出異常;并且在IE中namedItem()只會(huì)返回第一項(xiàng),因?yàn)槊恳豁?xiàng)的name特性都是相同的;

          console.log(citys.namedItem("city"));

          為某些HTML元素設(shè)置name屬性,將自動(dòng)在windows對(duì)象中創(chuàng)建對(duì)應(yīng)的屬性,對(duì)Document對(duì)象也是類似的;比如,為<form>、<img>、<iframe>、<applet>、<embed>或<object>元素設(shè)置name屬性,即在Document對(duì)象中創(chuàng)建以此name屬性值為名字的屬性;

          <form name="myform"></form>
          <script>
          console.log(document.myform);
          </script>

          即使如此,建議不要用這種方式來(lái)獲取元素,最好還是顯式的使用getElementsByName()方法;

          getElementsByTagName()方法:

          該方法是通過(guò)標(biāo)簽名來(lái)獲取元素,其接收一個(gè)參數(shù),即要取得元素的標(biāo)簽名;返回?fù)碛辛銈€(gè)或多個(gè)元素的HTMLCollection集合對(duì)象,其是動(dòng)態(tài)集合,與NodeList非常類似;;

          var spans = document.getElementsByTagName("span");
          console.log(spans); // HTMLCollection

          其擁有l(wèi)ength屬性,可以通過(guò)方括號(hào)或者item()方法來(lái)訪問(wèn)HTMLCollection對(duì)象中的項(xiàng);還擁有一個(gè)namedItem()方法,該方法可以通過(guò)元素的name屬性取得集合中的項(xiàng),但可以簡(jiǎn)寫為使用方括號(hào)訪問(wèn);即如果是數(shù)值,則調(diào)用item(),如果是字符串索引,就調(diào)用namedItem();

          var divs = document.getElementsByTagName("div");
          console.log(divs);
          console.log(divs[0]);
          console.log(divs.item(1));
          console.log(divs.namedItem("innerDiv"));
          console.log(divs["innerDiv"]);
          console.log(images[0].src);
          images.item(1).src = "images/3.jpg";

          如果傳入“*”,則取得頁(yè)面中所有元素;(在JS和CSS中,*就是匹配所有的通配符);

          var nodes = document.getElementsByTagName("*");
          console.log(nodes);

          會(huì)打印出頁(yè)面中所有的元素,按照它們出現(xiàn)的順序(沒(méi)有層次之分);

          在HTML中,該方法參數(shù)不需要區(qū)分大小寫,而在XML中,區(qū)分大小寫;

          Element類也定義了getElementsByTagName()方法,其原理和Document一樣,但是它只選取調(diào)用該方法的元素的后代元素;

          var mydiv = document.getElementById("mydiv");
          // 也可以通過(guò)getElementsByTagName來(lái)獲取
          // var mydiv = document.getElementsByTagName("div")[0];
          var spans = mydiv.getElementsByTagName("span");
          console.log(spans);

          文檔信息:

          作為HTMLDocument的一個(gè)實(shí)例,document對(duì)象還有一些標(biāo)準(zhǔn)的Document對(duì)象所沒(méi)有的屬性;這些屬性提供了document對(duì)象所表現(xiàn)的網(wǎng)頁(yè)的一些信息;

          從BOM角度來(lái)看document對(duì)象是window對(duì)象的屬性,由一系列集合構(gòu)成,這些集合可以訪問(wèn)文檔的各個(gè)部分,并提供頁(yè)面自身的信息,可以認(rèn)為document即為加載的html文檔;

          document.title:包含著<title>元素中的文本,通過(guò)它,可以獲取或修改當(dāng)前頁(yè)面的標(biāo)題;

          var originalTitle = document.title;
          console.log(originalTitle);
          document.title = "zeronetwork title";
          // 標(biāo)題跑馬燈效果
          var str="北京零點(diǎn)網(wǎng)絡(luò)科技有限公司-";
          document.title = str;
          function titleMove(){
              str = str.substring(1,str.length) + str.substring(0,1);
              document.title = str;
          }
          setInterval("titleMove()",1000);

          lastModified:返回文檔被最后修改的日期和時(shí)間;

          cookie:允許Javascript讀寫的HTTP cookie的特殊屬性;

          location:與window對(duì)象的location屬性引用同一個(gè)Location對(duì)象;

          URL:包含頁(yè)面完整的URL;一般情況下,該屬性的值與location.href 屬性相同;但不包含Location對(duì)象的動(dòng)態(tài)變化,即在 URL 重定向發(fā)生的時(shí)候,這個(gè)URL屬性保存了文檔的實(shí)際URL,不會(huì)發(fā)生變化,而 location.href會(huì)發(fā)生變化;location.href 是可寫的,document.URL是只讀的;

          console.log(document.URL);
          console.log(location.href);
          document.URL = "demo.html";  // 無(wú)效
          console.log(document.URL);
          // location.href = "demo1.html";  // 跳轉(zhuǎn)

          referrer:來(lái)源頁(yè)面的URL(鏈接到當(dāng)前頁(yè)面的那個(gè)頁(yè)面),如果沒(méi)有來(lái)源,referrer為空字符串;該屬性是只讀的;

          console.log(document.referrer);

          這個(gè)屬性在分析網(wǎng)站SEO數(shù)據(jù)時(shí)特別有用;

          var referrer = document.referrer;
          var origin = location.origin;
          console.log(referrer);
          console.log(origin);
          if(referrer){
              if(referrer.indexOf(origin) == 0){
                  document.write("站內(nèi)瀏覽");
              }else{
                  document.write("從外鏈:" + referrer + "進(jìn)入");
              }
          }else{
              document.write("直接打開(kāi)");
          }

          查找搜索關(guān)鍵詞:

          var ref = document.referrer;
          console.log(ref);
          if(ref.indexOf("http://127.0.0.1:5500/search.html?") == 0){
              var args = ref.substring(ref.indexOf("?") + 1).split("&");
              for(var i=0; i<args.length; i++){
                  if(args[i].substring(0,2) == "q="){
                      document.write("<h2>搜索的是:</h2>");
                      keys = args[i].substring(2).split("+");
                      for(var k in keys){
                          document.write(decodeURIComponent(keys[k]) + "<br>");
                      }
                      break;
                  }
              }
          }

          domain屬性:獲取或設(shè)置當(dāng)前文檔的域名;

          該屬性允許當(dāng)Web頁(yè)面之間交互時(shí),相同域名下互相信任的Web服務(wù)器之間協(xié)作放寬同源策略安全限制,其是可讀的,但有安全限制,即不能為domain賦任意值;

          不能將該屬性設(shè)置為URL中不包含的域;

          // FF提示“The operation is insecure.”,Chrome提示不是127.0.0.1的子域名
          // document.domain = "www.zeronetwork.cn";  // 異常
          console.log(document.domain);

          document對(duì)象的集合:

          除了屬性和方法,document對(duì)象還有一些特殊的集合;這些集合都是HTMLCollection對(duì)象,為訪問(wèn)文檔的常用部分提供了快捷方式,包括:

          document.anchors:包含文檔中所有帶name特性的<a>元素;這個(gè)屬性已經(jīng)從Web標(biāo)準(zhǔn)中刪除了,但瀏覽器還支持,所以盡量不要再使用;

          <!-- link.html頁(yè)面 -->
          <h1>零點(diǎn)程序員</h1>
          <h2><a name="one">Web前端開(kāi)發(fā)</a></h2>
          <div style="height: 1000px;background-color: purple;">DIV</div>
          <h2><a name="two">后端開(kāi)發(fā)</a></h2>
          <div style="height: 1000px;background-color: green;">DIV</div>
          <h2><a name="three">蘋果開(kāi)發(fā)</a></h2>
          <div style="height: 1000px;background-color: blue;">DIV</div>
          <!-- 主頁(yè)面 -->
          <p>
              <input type="button" value="Web前端開(kāi)發(fā)" onclick="jump('one')" />
              <input type="button" value="后端開(kāi)發(fā)" onclick="jump('two')" />
              <input type="button" value="蘋果開(kāi)發(fā)" onclick="jump('three')" />
          </p>
          <script>
          var win = window.open("link.html","newWin","width=250,height=150");
          function jump(name) {
              console.log(name);
              if(win.document.anchors[name]){
                  win.location.hash = name;
                  win.focus();
              }else{
                  alert("錨不存在")
              }
          }
          </script>

          document.links:包含文檔中所有帶href特性的<a>元素或<area>元素;

          var mydiv = document.getElementById("mydiv");
          var links = document.links;
          for(var i=0,len=links.length; i<len; i++){
              var aNode = document.createElement("a");
              aNode.href = links[i].href;
              var href = document.createTextNode(links[i].innerText);
              aNode.appendChild(href);
              mydiv.appendChild(aNode);
          }

          打開(kāi)外鏈進(jìn)行提醒:

          var links = document.links;
          for(var i=0,len=links.length; i<len; i++){
              var link = links[i];
              link.addEventListener("click",function(e){
                  e.preventDefault();
                  if(e.target.host !== location.host)
                      jump(e.target.innerText, e.target.href);
                  else
                      location.href = e.target.href;
                      
              },false);
          }
          function jump(title,href){
              var div = document.createElement("div");
              div.id = "jumpDiv";
              document.body.appendChild(div);
              var str = document.createTextNode("你要訪問(wèn)的:" + href + "不屬于本網(wǎng)站,你要繼續(xù)訪問(wèn)嗎?");
              div.appendChild(str);
              var aGo = document.createElement("a");
              aGo.href = href;
              aGo.target = "_blank";
              aGo.appendChild(document.createTextNode("繼續(xù)"));
              div.appendChild(aGo);
              var aBack = document.createElement("a");
              aBack.href = "Javascript:void(0);";
              aBack.appendChild(document.createTextNode("關(guān)閉"));
              aBack.onclick = closeJumpDiv;
              div.appendChild(aBack);
          }
          function closeJumpDiv(){
              var jumpDiv = document.getElementById("jumpDiv");
              if(jumpDiv)
                  jumpDiv.parentNode.removeChild(jumpDiv);
          }

          document.applets:包含文檔中所有的<applet>元素;

          document.forms:包含文檔中所有的<form>元素,與document.getElementsByTagName(“form”)得到的結(jié)果是相同的;

          <form name="myform">
              <!-- id也可為以-->
              <input type="text" id="username" />
          </form>
          <form name="yourform"></form>
          <script>
          console.log(document.forms); // HtmlCollection
          console.log(document.forms.myform);
          console.log(document.forms[0]);
          console.log(document.forms["myform"]);
          console.log(document.forms.myform.username);
          </script>

          document.embeds:包含文檔中所有的<embeds>元素;

          document.plugins:包含文檔中所有的插件;注意和navigator.plugins的區(qū)別;

          console.log(document.plugins);  // HTMLCollection
          console.log(navigator.plugins);  // pluginArray

          document.images:包含文檔中所有的<img>元素實(shí)時(shí)集合,集合中的每個(gè)元素代表了一個(gè)image元素的HTMLImageElement,與document.getElementsByTagName(“img”)得到的結(jié)果是相同的;

          document.scripts:返回一個(gè)HTMLCollection對(duì)象,包含了當(dāng)前文檔中所有<script>元素的集合;

          document.all:只讀屬性,返回一個(gè)HTMLAllCollection,包含了頁(yè)面上的所有元素;已從Web標(biāo)準(zhǔn)中刪除,但是瀏覽器都支持,但建議不要使用;與document.getElementsByTagName(“*”)得到的結(jié)果基本相同的;

          console.log(document.all);  // HTMLAllCollection
          console.log(document.getElementsByTagName("*"));  // HTMLCollection
          console.log(document.all[9]);
          document.all[9].innerHTML = "零點(diǎn)程序員";
          // id或name為"mydiv"的元素,但是有區(qū)別的,為name的元素只是插入text
          document.all["mydiv"].innerHTML = "<h2>零點(diǎn)程序員</h2>"; 

          以上這些集合始終都可以通過(guò)HTMLDocument對(duì)象訪問(wèn)到,而且,它們都是動(dòng)態(tài)的;但現(xiàn)在已經(jīng)被 document.getElementsByTagName()所取代,部分已經(jīng)廢棄不應(yīng)該再使用,但是仍然常常被使用,因?yàn)樗麄兪褂闷饋?lái)很方便;

          文檔寫入:

          document對(duì)象,可以將文本字符串寫入文檔流中;

          write()與writeln()方法:

          這兩個(gè)都接受一個(gè)字符串參數(shù),即要寫入到輸出流中的文本;write()會(huì)原樣寫入,writeln()則會(huì)在字符串的末尾添加一個(gè)換行符(\n);

          這兩個(gè)方法會(huì)將其字符串參數(shù)連接起來(lái),然后將結(jié)果字符串插入到文檔中調(diào)用它們的腳本元素的位置;

          document.write("<h1>" + document.title + "</h1>");
          document.write("<strong>" + (new Date()).toString() + "</strong>");

          不光輸出內(nèi)容,還會(huì)解析為DOM元素;

          參數(shù)可以是多種形式,如:

          // 部分替換為writeln()方法
          var username = "wangwei";
          document.write("我的名字:" + username + "<br/>");
          document.write("sum:" + (5 + 4));
          document.write("<ul>");
          document.write("<li>HTML</li>","<li>CSS</li>","<li>Javasc </li>");
          document.write("</ul>")
          var arr = ["<p>zeronetwork</p>","<p>wangwei</p>","<p>web</p>"];
          document.write(arr.join(""));
          function func(){
              return "func";
          }
          document.write(func + "<br>");
          document.write(function(){
              return "Happy";
          }());

          只有在解析文檔時(shí)才能使用write()方法輸出HTML到當(dāng)前文本,如果把write()方法放到一個(gè)函數(shù)內(nèi)或者在文檔加載結(jié)束后再調(diào)用document.write(),那么輸出的內(nèi)容將會(huì)重寫整個(gè)頁(yè)面;如:

          window.onload = function(){
              document.write("零點(diǎn)程序員");
          }

          這里有個(gè)問(wèn)題,理論上來(lái)說(shuō),重寫了整個(gè)頁(yè)面后,原頁(yè)面中的所有變量和值都應(yīng)該被清除,但事實(shí)卻不是這樣的,IE是這樣的行為,但其他瀏覽器會(huì)保留原內(nèi)容中的變量和值;

          var num = 10;
          function fun(){
              document.write("fun");
          }
          var mydiv = document.getElementById("mydiv");
          window.onload = function(){
              document.write("重寫了整個(gè)頁(yè)面");
              console.log(num);
              fun();
              document.body.appendChild(mydiv);
          }
          正因?yàn)樗鼈儾患嫒荩圆灰谛挛臋n流中調(diào)用原內(nèi)容中的變量和值;

          open()與close()方法:

          可以使用write()方法在其他的窗口或框架頁(yè)中來(lái)創(chuàng)建整個(gè)全新文檔,但一般會(huì)配合close和open方法一起使用;

          open()和close()分別用于打開(kāi)和關(guān)閉網(wǎng)頁(yè)的輸出流;如果是在頁(yè)面加載期間使用write()或writeln()方法,則不需要用到這兩個(gè)方法,因?yàn)槲臋n此時(shí)是打開(kāi)狀態(tài);向一個(gè)已經(jīng)加載完成的文檔寫入數(shù)據(jù)時(shí),會(huì)自動(dòng)調(diào)用 document.open,并且會(huì)擦除該文檔的所有內(nèi)容,因?yàn)橐呀?jīng)加載完成的文檔,它的文檔流已經(jīng)關(guān)閉,就是已經(jīng)自動(dòng)調(diào)用了document.close();

          可以多次調(diào)用write()來(lái)逐步建立新文檔的內(nèi)容;傳遞給write的內(nèi)容可能緩存起來(lái),所以一旦完成了數(shù)據(jù)寫入,建議調(diào)用 document.close()來(lái)結(jié)束該寫序列,以告訴HTML解析器,文檔已經(jīng)達(dá)到了文件的末尾,寫入的數(shù)據(jù)會(huì)被解析到文檔結(jié)構(gòu)模型(DOM)里,此時(shí)應(yīng)該結(jié)束解析并顯示新文檔;

          btn.onclick = function(){
              document.open();  // 可以省略
          document.write("重寫了整個(gè)頁(yè)面");
              document.close();
          }

          此時(shí),如果在close()方法后,再調(diào)用write()方法就會(huì)重寫整個(gè)新窗口的內(nèi)容,如:

          // 在onclick事件處理函數(shù)中繼續(xù)添加
          document.write("文檔又被重寫了");

          注意:無(wú)法關(guān)閉系統(tǒng)創(chuàng)建的文檔流,如果,我們?cè)谌汁h(huán)境中直接執(zhí)行close()方法,會(huì)發(fā)現(xiàn)沒(méi)有效果,原因就是無(wú)法關(guān)閉系統(tǒng)創(chuàng)建的文檔流,我們只能關(guān)閉自己打開(kāi)的文檔流;

          在新窗口也是同樣的道理;

          var oNewWin=window.open("about:blank","newwindow","width=400,width=200");
          oNewWin.document.open();
          oNewWin.document.write("<h1>新窗</h1>");
          oNewWin.document.write("<div>這是一個(gè)新窗口</div>");
          oNewWin.document.close();

          在使用write()方法時(shí),最好一次性寫入;

          <input type="button" id="btn" value="寫入">
          <script>
          var newWin = null;
          function makeNewWin(){
              newWin = window.open("about:blank","newWin","width=400,height=300");
          }
          var btn = document.getElementById("btn");
          btn.onclick = function(){
              // 如果newWin不存在或已關(guān)閉,再次打開(kāi)
              if(!newWin || newWin.closed)
                  makeNewWin();
              newWin.focus();
              var title = "零點(diǎn)程序員";
              var newStr = "<!DOCTYPE html>";
              newStr += "<html><head>";
              newStr += "<title>" + title + "</title></head>";
              newStr += "<body>";
              newStr += "<h1>零點(diǎn)程序員</h1>";
              newStr += "<div>這是內(nèi)容</div>";
              // 把body拆分成</b和ody>,否則會(huì)拋出異常
              newStr += "</b" + "ody></html>"; 
              newWin.document.write(newStr);
              newWin.document.close();
          }
          </script>

          document.open()另類的用法:

          2個(gè)參數(shù)的open()方法,語(yǔ)法為document.open(type, replace),如:

          document.open("text/html","replace");

          type指定了所需寫入的數(shù)據(jù)的MIME類型,默認(rèn)值為”text/html”,replace(如有設(shè)置,值為一個(gè)字符串“replace”)指定了新文檔從父文檔繼承歷史條目;

          使用open()方法,在IE中會(huì)產(chǎn)生歷史條目,其他瀏覽器不會(huì)產(chǎn)生,因此這種用法只會(huì)在IE中有效果;而如果指定了replace參數(shù),IE就不會(huì)產(chǎn)生歷史條目,也就是父文檔的記錄被覆蓋了;

          這種形式現(xiàn)在已經(jīng)棄用;

          3個(gè)參數(shù)的open()方法,是Window.open()的一個(gè)別名;

          var doc = document.open("https://www.zeronetwork.cn/","","width=400;");// 打開(kāi)新窗口
          console.log(doc);  // Window
          doc.document.write("<h1>零點(diǎn)程序員</h1>");  // 重寫
          doc.document.close();
          // doc.close();  // 會(huì)關(guān)閉窗口

          動(dòng)態(tài)加載外部資源:

          使用write()和writeln()兩個(gè)方法,還可以動(dòng)態(tài)加載外部資源,如Javascript文件等,但要注意,不能直接包含字符串“</script>”,因?yàn)闀?huì)導(dǎo)致代碼不能正確的解析;

          document.write("<script type=\"text/javascript\" src=\"file.js\">" + "<\/script>");
          // 或者
          document.write("<script type=\"text/javascript\" src=\"file.js\">" + "</scr" + "ipt>");

          這種方法經(jīng)常在廣告和統(tǒng)計(jì)功能的第三方中使用;

          為什么不直接使用<script>標(biāo)簽,而直接使用動(dòng)態(tài)載入呢?原因有兩個(gè):

          一是腳本的URL不能寫死,比如要?jiǎng)討B(tài)添加一些參數(shù),用戶設(shè)備的分辨率啊,當(dāng)前頁(yè)面 URL 啊,防止緩存的時(shí)間戳之類的,這些參數(shù)只能先用 JS 獲取到,再比如國(guó)內(nèi)常見(jiàn)的網(wǎng)站統(tǒng)計(jì)代碼:

          <script>
          var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
          document.write(unescape("%3Cspan id='cnzz_stat_icon_1279580898'%3E%3C/span%3E%3Cscript src='" + 
          cnzz_protocol +  "s9.cnzz.com/stat.php%3Fid%3D1279580898' type='text/javascript'%3E%3C/script%3E"));
          </script>

          它之所以使用write()方法,而不使用<script>元素,就是為了先用 JS 判斷出該用http還是https 協(xié)議;

          另外,有可能需要在腳本里加載另外一個(gè)腳本文件或嵌入的JS內(nèi)容有可能會(huì)修改頁(yè)面內(nèi)容,而這些操作只需要第三方自己維護(hù),不需要自己的網(wǎng)站去維護(hù);

          在實(shí)際開(kāi)發(fā)中,write()并不常用,innerHTML屬性和其他DOM技術(shù)提供了更好的方法來(lái)為文檔增內(nèi)容;比如,可以利用innerHTML來(lái)輸出內(nèi)容:

          var mydiv = document.getElementById("mydiv");
          mydiv.innerHTML = "<h1>零點(diǎn)程序員</h1><p>開(kāi)設(shè)了Web前端課程</p>";
          // 重寫body內(nèi)所有內(nèi)容
          document.body.innerHTML = "<h1>零點(diǎn)程序員</h1><p>開(kāi)設(shè)了Web前端課程</p>";
          包裝一個(gè)對(duì)象,類似于write()和close()方法:
          // 為設(shè)置元素的innerHTML定義簡(jiǎn)單的"流式"API
          function ElementStream(elt){
              if(typeof elt === "string")
                  elt = document.getElementById("elt");
              this.elt = elt;
              this.buffer = "";
          }
          // 連接所有的參數(shù),添加到緩存中
          ElementStream.prototype.write = function(){
              this.buffer += Array.prototype.join.call(arguments, "");
          };
          // 類似write(),只是多增加了換行符
          ElementStream.prototype.writeln = function(){
              this.buffer += Array.prototype.join.call(arguments, "") + "\n";
          };
          // 從緩存設(shè)置元素的內(nèi)容,然后清空緩存
          ElementStream.prototype.close = function(){
              this.elt.innerHTML = this.buffer;
              this.buffer = "";
          }
          var mydiv = document.getElementById("mydiv");
          var elt = new ElementStream(mydiv);
          elt.write("<h1>零點(diǎn)程序員</h1>");
          elt.writeln("<p>王唯</p>");
          elt.close();

          Web前端開(kāi)發(fā)之Javascript-零點(diǎn)程序員-王唯


          主站蜘蛛池模板: 久久久精品人妻一区二区三区| 国产精品一区12p| 污污内射在线观看一区二区少妇| 国产精品熟女视频一区二区| 国产精品亚洲一区二区三区| 国产精品一区二区三区免费| 农村人乱弄一区二区| 亚洲视频一区二区三区| 春暖花开亚洲性无区一区二区| 亚洲国产精品一区二区三区久久| 久久亚洲综合色一区二区三区| 竹菊影视欧美日韩一区二区三区四区五区| 国产大秀视频在线一区二区| 八戒久久精品一区二区三区| 国产午夜精品一区理论片飘花| 亚洲日本久久一区二区va| 少妇人妻精品一区二区| 99精品国产高清一区二区三区| 亚洲一区在线视频观看| 国产福利电影一区二区三区久久老子无码午夜伦不 | 亚洲欧美日韩一区二区三区| 国产精品免费综合一区视频| 国产成人精品无码一区二区三区 | 亚洲性无码一区二区三区| 一区二区三区内射美女毛片| 亚洲一区二区三区夜色| 国产精品亚洲一区二区三区在线观看| 在线精品亚洲一区二区小说| 精品国产一区二区三区www| 国产a∨精品一区二区三区不卡| 风间由美在线亚洲一区| 亚洲国产成人精品无码一区二区| 亚洲一区二区精品视频| 国产福利酱国产一区二区| 亚洲av午夜福利精品一区人妖| 精品一区二区三区视频| 中文字幕无码不卡一区二区三区| 2014AV天堂无码一区| 日韩精品一区二区三区视频| 国产欧美色一区二区三区| 久久精品一区二区三区四区 |