国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

看Zepto如何實現(xiàn)增刪改查DOM

lookSomeone / 1951人閱讀

摘要:先看下圖,我們以刪除元素,插入元素復(fù)制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。

前言

dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復(fù)制,替換和刪除等操作。但是zepto在其基礎(chǔ)上再次封裝,給以我們更加便捷的操作方式。先看下圖,我們以刪除元素插入元素,復(fù)制元素包裹元素替換元素幾個模塊分別探究zepto如何一一將其實現(xiàn)。

原文鏈接

github項目地址

刪除元素 remove

當父節(jié)點存在時,從其父節(jié)點中刪除當前集合中的元素。

remove: function () {
  return this.each(function () {
    if (this.parentNode != null)
      this.parentNode.removeChild(this)
  })
}

遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用removeChild刪除該元素。

detach

功能和remove一樣,都是刪除元素。

$.fn.detach = $.fn.remove

可以看到就是在$的原型上添加了一個指向remove函數(shù)的方法detach

empty

清空對象集合中每個元素的DOM內(nèi)容

empty: function () {
  return this.each(function () { this.innerHTML = "" })
},

遍歷當前集合中的元素,然后將元素的innerHTML屬性設(shè)置為空。也就達到了清除DOM內(nèi)容的目的。

插入元素

插入元素的相關(guān)api比較多,我們先來重溫部分api的使用用法和比較一下他們之間的區(qū)別。

append, prepend, after, before
  • 1
let $box = $(".box")
let insertDom = "
  • i am child
  • " // append appendTo // $box.append(insertDom) // $(insertDom).appendTo($box) /*
    • 1
    • i am child
    */ // prepend prependTo // $box.prepend(insertDom) // $(insertDom).prependTo($box) /*
    • i am child
    • 1
    */ // before insertBefore // $box.before(insertDom) // $(insertDom).insertBefore($box) /*
  • i am child
    • 1
    */ // after insertAfter // $box.after(insertDom) // $(insertDom).insertAfter($box) /*
    • 1
  • i am child
  • */

    以上是append,appendTo,prepend,prependTo,after,insertAfter,before,insertBefore八個方法的基本用法,以及用過之后的dom結(jié)構(gòu)。我們總結(jié)一下他們的區(qū)別。

    首先每個方法的入?yún)⒍伎梢詾閔tml字符串,dom節(jié)點,或者節(jié)點組成的數(shù)組。參考自zeptojs_api

    append,appendTo,prepend,prependTo都是在元素內(nèi)部插入內(nèi)容,而after,insertAfter,before,insertBefore則是在元素外部插入內(nèi)容。

    append,appendTo是在元素的末尾插入內(nèi)容,prepend,prependTo是在元素的初始位置插入,after,insertAfter是在元素的后面插入內(nèi)容,before,insertBefore則是在元素的前面插入內(nèi)容

    接下來我們開始學(xué)習(xí)和閱讀實現(xiàn)這8大方法的核心源碼部分

    adjacencyOperators = ["after", "prepend", "before", "append"]
    
    adjacencyOperators.forEach(function(operator, operatorIndex) {
      var inside = operatorIndex % 2
    
      $.fn[operator] = function() {
        // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
        var argType, nodes = $.map(arguments, function(arg) {
          var arr = []
          argType = type(arg)
          if (argType == "array") {
            arg.forEach(function(el) {
              if (el.nodeType !== undefined) return arr.push(el)
              else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())
              arr = arr.concat(zepto.fragment(el))
            })
            return arr
          }
          return argType == "object" || arg == null ?
            arg : zepto.fragment(arg)
        }),
            parent, copyByClone = this.length > 1
        if (nodes.length < 1) return this
    
        return this.each(function(_, target) {
          parent = inside ? target : target.parentNode
    
          // convert all methods to a "before" operation
          target = operatorIndex == 0 ? target.nextSibling :
          operatorIndex == 1 ? target.firstChild :
          operatorIndex == 2 ? target :
          null
    
          var parentInDocument = $.contains(document.documentElement, parent)
    
          nodes.forEach(function(node) {
            if (copyByClone) node = node.cloneNode(true)
            else if (!parent) return $(node).remove()
    
            parent.insertBefore(node, target)
            if (parentInDocument) traverseNode(node, function(el) {
              if (el.nodeName != null && el.nodeName.toUpperCase() === "SCRIPT" &&
                  (!el.type || el.type === "text/javascript") && !el.src) {
                var target = el.ownerDocument ? el.ownerDocument.defaultView : window
                target["eval"].call(target, el.innerHTML)
              }
            })
              })
        })
      }
    

    遍歷adjacencyOperators數(shù)組給$原型添加對應(yīng)的方法

    adjacencyOperators = ["after", "prepend", "before", "append"]
    
    adjacencyOperators.forEach(function(operator, operatorIndex) {
      // xxx
      $.fn[operator] = function() {
        // xxx
      }
      // xxx
    })
    

    可以看到通過循環(huán)遍歷adjacencyOperators從而給$的原型添加對應(yīng)的方法。

    轉(zhuǎn)換node節(jié)點

    var argType, nodes = $.map(arguments, function(arg) {
      var arr = []
      argType = type(arg)
      if (argType == "array") {
        arg.forEach(function(el) {
          if (el.nodeType !== undefined) return arr.push(el)
          else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())
          arr = arr.concat(zepto.fragment(el))
        })
        return arr
      }
      return argType == "object" || arg == null ?
        arg : zepto.fragment(arg)
    })
    

    例子

    // 1 html字符串
    $box.append("hello world")
    // 2 dom節(jié)點
    $box.append(document.createElement("span"))
    // 3 多個參數(shù)
    $box.append("1", "2")
    // 4 數(shù)組
    $box.append(["hello world", document.createElement("span")]) 
    

    因為傳入的內(nèi)容可以為html字符串,dom節(jié)點,或者節(jié)點組成的數(shù)組。這里對可能的情況分類型做了處理。通過內(nèi)部的type函數(shù)判斷每個參數(shù)的數(shù)據(jù)類型并保存在argType中。

    當參數(shù)類型為數(shù)組(類似上面例子中的4)的時候,再對該參數(shù)進行遍歷,如果該參數(shù)中的元素存在nodeType屬性則將該元素推進數(shù)組arr,
    如果該參數(shù)中的元素是一個Zepto對象,則調(diào)用get方法,將arr與返回的原生元素數(shù)組進行合并。

    當參數(shù)類型為object或者null的時候直接返回,否則就是處理字符串形式了,通過調(diào)用zepto.fragment(這個函數(shù)在后面的文章中會詳細講解,現(xiàn)在就其理解為將html字符串處理成dom節(jié)點數(shù)組就可以了)處理并將結(jié)果返回。

    到現(xiàn)在為止,我們已經(jīng)明白了怎么將傳入的content轉(zhuǎn)化為對應(yīng)的dom節(jié)點

    接下來我們來看如何將nodes中創(chuàng)建好的dom節(jié)點插入到目標位置。

    parent, copyByClone = this.length > 1
    
    if (nodes.length < 1) return this
    

    先留意一下parent,以及copyByClone這兩個變量,挺重要的,具體作用下面會詳細說明。并且如果需要插入的元素數(shù)組的長度小于1,那么也就沒有必要繼續(xù)往下走了,直接return this進行鏈式操作。

    return this.each(function(_, target) {
      // xxx
      nodes.forEach(function(node) {
        // xxx 
        // 注意這行,所有的插入操作都通過insertBefore函數(shù)完成
        parent.insertBefore(node, target)
        // xxx
      })
    
    })
    

    整個后續(xù)代碼就是兩層嵌套循環(huán),第一層遍歷當前選中的元素集合,第二層就是需要插入的nodes節(jié)點集合。通過兩個循環(huán)來最終完成元素的插入操作,并且很重要的一點是,不管是append還是after等方法都是通過insertBefore來模擬完成的。

    確定parent節(jié)點以及target目標節(jié)點

    通過上面的分析我們知道通過insertBefore(在當前節(jié)點的某個子節(jié)點之前再插入一個子節(jié)點)來完成節(jié)點的插入,很重要的幾個因素就是

    parentNode.insertBefore(newNode, referenceNode)

    父節(jié)點(parentNode)

    需要插入的新節(jié)點(newNode)

    參考節(jié)點referenceNode

    所以確定以上1和3就顯得極其重要了。怎么確定呢?

    return this.each(function(_, target) {
      parent = inside ? target : target.parentNode
    
      // convert all methods to a "before" operation
      target = operatorIndex == 0 ? target.nextSibling :
      operatorIndex == 1 ? target.firstChild :
      operatorIndex == 2 ? target :
      null
      // xxx
    })
    

    inside是個啥啊!!!,讓我們回到頂部看這段

    adjacencyOperators = ["after", "prepend", "before", "append"]
    adjacencyOperators.forEach(function (operator, operatorIndex) {
      var inside = operatorIndex % 2
      // xxx
    })
    

    所以說當要往$原型上添加的方法是prependappend的時候inside為1也就是真,當為afterbefore的時候為0也就是假。

    因為prependappend都是往當前選中的元素內(nèi)部添加新節(jié)點,所以parent當然就是target本身了,但是afterbefore確是要往選中的元素外部添加新節(jié)點,自然parent就變成了當前選中元素的父節(jié)點。到這里上面的三要素1,已經(jīng)明確了,還有3(target)如何確定呢?

    target = operatorIndex == 0 ? target.nextSibling :
      operatorIndex == 1 ? target.firstChild :
      operatorIndex == 2 ? target :
      null
    

    如果operatorIndex為0,即after方法,node節(jié)點應(yīng)該是插入到目標元素target的后面,也就是target的下一個兄弟節(jié)點的前面

    如果operatorIndex為1,即prepend方法,node應(yīng)該插入到目標元素target的第一個子元素的前面

    如果operatorIndex為2,即before方法,node節(jié)點應(yīng)該插入到target節(jié)點的前面

    否則operatorIndex為4了,即append方法,node節(jié)點應(yīng)該插入到target最后一個子節(jié)點的末尾,insertBefore傳入null,正好與其功能相對應(yīng)

    好啦三要素3頁已經(jīng)明確了,接下來我們把重要放在第二個循環(huán)。

    將新節(jié)點插入到指定位置

    nodes.forEach(function(node) {
      if (copyByClone) node = node.cloneNode(true)
      else if (!parent) return $(node).remove()
    
      parent.insertBefore(node, target)
      // 處理插入script情況
    })
    

    在將節(jié)點插入到指定位置的前有一個判斷,如果copyByClone為真,就將要插入的新節(jié)點復(fù)制一份。為什么要這么做呢?我們來看個例子。

    • 1
    • 2
    • 3
    let $list = document.querySelector(".list")
      let $listLi = document.querySelectorAll(".list li")
      let createEle = (tagName, text) => {
        let ele = document.createElement(tagName)
        ele.innerHTML = text
        return ele
      }
      let $span1 = createEle("span", "span1")
      let $span2 = createEle("span", "span2")
    
      Array.from($listLi).forEach((target) => {
        [$span1, $span2].forEach((node) => {
          // node = node.cloneNode(true)
          $list.insertBefore(node, target)
        })
      })
    

    先將cloneNode那部分給注銷了,我們期望往三個li的前面都插入兩個span,但是結(jié)果會怎么樣呢?只有最后一個節(jié)點前面可以成功地插入兩個span節(jié)點。這樣就不是我們先要的結(jié)果了,根據(jù)insertBefore mdn解釋,如果newElement已經(jīng)在DOM樹中,newElement首先會從DOM樹中移除。,所以當我們需要往多個li中插入同樣類似的兩個節(jié)點的時候,才需要將新節(jié)點克隆一份再插入。

    我們接著回到源碼。

    nodes.forEach(function(node) {
      if (copyByClone) node = node.cloneNode(true)
      else if (!parent) return $(node).remove()
    
      parent.insertBefore(node, target)
      // 處理插入script情況
    })
    

    如果需要(當前選中元素的個數(shù)大于1)克隆節(jié)點的時候,先將新節(jié)點克隆一份,如果沒有找到對應(yīng)的parent節(jié)點,就講要插入的新節(jié)點刪除,最后通過insertBefore方法插入新節(jié)點。

    到了這里我們似乎已經(jīng)完成了從

    創(chuàng)建新節(jié)點 => 將新節(jié)點插入到指定位置的操作了。任務(wù)好像已經(jīng)完成了,但是革命尚未成功,同志仍需努力啊。接下來看最后一點代碼,主要是處理,當插入的節(jié)點是script
    標簽的時候,需要手動去執(zhí)行其包含的js代碼。

    
    var parentInDocument = $.contains(document.documentElement, parent)
    
    if (parentInDocument) traverseNode(node, function(el) {
      if (el.nodeName != null && el.nodeName.toUpperCase() === "SCRIPT" &&
          (!el.type || el.type === "text/javascript") && !el.src) {
        var target = el.ownerDocument ? el.ownerDocument.defaultView : window
        target["eval"].call(target, el.innerHTML)
      }
    })
    

    先提前看一下traverseNode這個函數(shù)的代碼

    function traverseNode(node, fun) {
      fun(node)
      for (var i = 0, len = node.childNodes.length; i < len; i++)
        traverseNode(node.childNodes[i], fun)
    }
    

    這個函數(shù)的主要作用就是將傳入的node節(jié)點作為參數(shù)去調(diào)用傳入的fun函數(shù)。并且遞歸的將node節(jié)點的子節(jié)點,交給fun去處理。

    接下來繼續(xù)看。

    首先通過$.contains方法判斷parent是否在document文檔中,接著需要滿足一下幾個條件才去執(zhí)行后續(xù)操作。

    存在nodeName屬性

    nodeName是script標簽

    type屬性為空或者type屬性為text/javascript

    src屬性為空(即不指定外部腳本)

    確定window對象

    var target = el.ownerDocument ? el.ownerDocument.defaultView : window
    

    新節(jié)點存在ownerDocument mdn則window對象為defaultView mdn,否則使用window對象本身。

    這里主要會考慮node節(jié)點是iframe種的元素情況,才需要做三目處理。

    最后便是調(diào)用target["eval"].call(target, el.innerHTML)去執(zhí)行script中的代碼了。

    到這里我們終于知道了"after", "prepend", "before", "append"實現(xiàn)全過程(偷樂一下?,不容易啊)。

    appendTo, prependTo, insertBefore, insertAfter

    緊接著我們繼續(xù)往前走,前面說了插入操作有很多個方法,其中
    insertAfter,insertBefore,prependTo,appendTo的實現(xiàn)基于上述幾個方法。

    // append   => appendTo
    // prepend  => prependTo
    // before   => insertBefore
    // after    => insertAfter
    
    $.fn[inside ? operator + "To" : "insert" + (operatorIndex ? "Before" : "After")] = function (html) {
      $(html)[operator](this)
      return this
    }
    

    如果是append或者prepend則往$原型上添加appendToprependTo方法,如果是before或者after的時候,便往$的原型上添加insertBeforeinsertAfter方法。因為其兩兩對應(yīng)的方法本質(zhì)上是同樣的功能,只是在使用上有點相反的意思,所以簡單的反向調(diào)用一下就可以了。

    html

    獲取或設(shè)置對象集合中元素的HTML內(nèi)容。當沒有給定content參數(shù)時,返回對象集合中第一個元素的innerHtml。當給定content參數(shù)時,用其替換對象集合中每個元素的內(nèi)容。content可以是append中描述的所有類型 zeptojs_api

    例子

    1. html()   ? string
    
    2. html(content)   ? self
    
    3. html(function(index, oldHtml){ ... })   ? self
    

    源碼實現(xiàn)

    html: function (html) {
      return 0 in arguments ?
        this.each(function (idx) {
          var originHtml = this.innerHTML
          $(this).empty().append(funcArg(this, html, idx, originHtml))
        }) :
        (0 in this ? this[0].innerHTML : null)
    }
    

    當沒有傳html參數(shù)的時候,先判斷當前選中的元素是否存在,存在則讀取第一個元素的innerHTML并返回,否則直接返回null

    (0 in this ? this[0].innerHTML : null)
    

    當傳了html參數(shù)的時候。對當前選中的元素集合進行遍歷設(shè)置,先保存當前元素的innerHTML到originHtml變量中,再將當前元素的innerHTML置空,并將funcArg函數(shù)執(zhí)行之后返回的html插入到當前元素中。

    function funcArg(context, arg, idx, payload) {
      return isFunction(arg) ? arg.call(context, idx, payload) : arg
    }
    

    可以看到funcArg會對傳入arg進行類型判斷,如果是函數(shù),就把對應(yīng)的參數(shù)傳入函數(shù)再將函數(shù)的執(zhí)行結(jié)果返回,不是函數(shù)就直接返回arg。

    text

    獲取或者設(shè)置所有對象集合中元素的文本內(nèi)容。當沒有給定content參數(shù)時,返回當前對象集合中第一個元素的文本內(nèi)容(包含子節(jié)點中的文本內(nèi)容)。當給定content參數(shù)時,使用它替換對象集合中所有元素的文本內(nèi)容。它有待點似 html,與它不同的是它不能用來獲取或設(shè)置 HTML。zeptojs_api

    text: function (text) {
      return 0 in arguments ?
        this.each(function (idx) {
          var newText = funcArg(this, text, idx, this.textContent)
          this.textContent = newText == null ? "" : "" + newText
        }) :
        (0 in this ? this.pluck("textContent").join("") : null)
    }
    

    text實現(xiàn)方法與html比較類似有些不同的是沒有傳參數(shù)的時候,html是獲取第一個元素的innerHTMLtext則是將當前所有元素的textContent拼接起來并返回.

    復(fù)制元素 clone

    通過深度克隆來復(fù)制集合中的所有元素。zeptojs_api

    clone: function () {
      return this.map(function () { return this.cloneNode(true) })
    }
    

    對當前選中的元素集合進行遍歷操作,底層還是用的瀏覽器cloneNode,并傳參為true表示需要進行深度克隆(其實感覺這里是不是將true設(shè)置為可選參數(shù)比較好呢,讓使用者決定是深度克隆與否不是更合理?)

    需要注意的地方是cloneNode方法不會復(fù)制添加到DOM節(jié)點中的Javascript屬性,例如事件處理程序等,這個方法只復(fù)制特性,子節(jié)點,其他一切都不會復(fù)制,IE在此存在一個bug,即他會賦值事件處理程序,所以我們建議在賦值之間最好先移除事件處理程序(摘自《JavaScript高級程序設(shè)計第三版》10.1.1 Node類型小字部分)

    替換元素 replaceWidth

    用給定的內(nèi)容替換所有匹配的元素。(包含元素本身) zeptojs_api

    replaceWith: function(newContent) {
      return this.before(newContent).remove()
    }
    

    源碼實現(xiàn)其實很簡單分兩步,第一步調(diào)用前面我們講的before方法將制定newContent插入到元素的前面,第二部步將當前選中的元素刪除。自然也就達到了替換的目的。

    包裹元素 wrapAll

    在所有匹配元素外面包一個多帶帶的結(jié)構(gòu)。結(jié)構(gòu)可以是單個元素或 幾個嵌套的元素zeptojs_api/#wrapAll

    wrapAll: function (structure) {
      // 如果選中的元素存在
      if (this[0]) {
        // 則將制定structure結(jié)構(gòu)通過before方法,插入到選中的第一個元素的前面
        $(this[0]).before(structure = $(structure))
        var children
        // drill down to the inmost element
        // 獲取structure的最深層次的第一個子元素
        while ((children = structure.children()).length) structure = children.first()
        // 將當前的元素集合通過append方法添加到structure末尾
        $(structure).append(this)
      }
      // 反則直接返回this進行后續(xù)的鏈式操作
      return this
    }
    

    源碼實現(xiàn)直接看注釋就可以了,這里需要注意一下children函數(shù)是獲取對象集合中所有的直接子節(jié)點。而first函數(shù)則是獲取當前集合的第一個元素。

    另外我們看一下下面兩個例子。

    • 1
    • 2
    $(".box").wrapAll(".wrap")
    

    執(zhí)行上述代碼之后dom結(jié)構(gòu)會變成

    • 1
    • 2
    • 1
    • 2
    • 1
    • 2

    可以看到原來ul結(jié)構(gòu)還是存在,仿佛是復(fù)制了一份ul及其子節(jié)點到wrap中被包裹起來。

    接下來再看一個例子,唯一的區(qū)別就在wrap結(jié)構(gòu)中嵌套了基層。

    • 1
    • 2

    但是最后執(zhí)行$(".box").wrapAll(".wrap")得到的dom結(jié)果是。

    • 1
    • 2

    嘿嘿可以看到,ul原來的結(jié)構(gòu)不見了,被移動到了第一個wrap的第一個子節(jié)點here中。具體原因是什么呢?大家可以重新回去看一下append的核心實現(xiàn)。

    wrap

    在每個匹配的元素外層包上一個html元素。structure參數(shù)可以是一個多帶帶的元素或者一些嵌套的元素。也可以是一個html字符串片段或者dom節(jié)點。還可以是一個生成用來包元素的回調(diào)函數(shù),這個函數(shù)返回前兩種類型的包裹片段。zeptojs_api/#wrapAll

    wrap: function (structure) {
      var func = isFunction(structure)
      // 當前選中的元素不為空,并且structure不是一個函數(shù)
      if (this[0] && !func)
        // 就將structure轉(zhuǎn)化后的第一個元素賦值給dom元素
        var dom = $(structure).get(0),
          // 如果dom元素的parentNode存在或者當前選中的元素個數(shù)大于1那么clone為true
          clone = dom.parentNode || this.length > 1
      // 對當前選中元素進行遍歷并且調(diào)用wrapAll方法
      return this.each(function (index) {
        $(this).wrapAll(
          // 如果structure為函數(shù),則將當前的元素和對應(yīng)的索引傳入函數(shù)
          func ? structure.call(this, index) :
            // 如果clone為true,則使用拷貝的副本
            clone ? dom.cloneNode(true) : dom
        )
      })
    }
    
    wrapInner

    將每個元素中的內(nèi)容包裹在一個多帶帶的結(jié)構(gòu)中 zeptojs_api/#wrapInner

    wrapInner: function (structure) {
      // 判斷structure是否為函數(shù)
      var func = isFunction(structure)
      // 對當前元素集合進行遍歷處理
      return this.each(function (index) {
        // contents => 獲取當前元素的所有子節(jié)點(包括元素節(jié)點和文本節(jié)點)
        var self = $(this), contents = self.contents(),
          // structure為函數(shù)則將其執(zhí)行結(jié)果賦值為dom,否則直接將其賦值
          dom = func ? structure.call(this, index) : structure
          // 當前元素的子節(jié)點不為空,則調(diào)用wrapAll,否則直接將dom插入self當前元素即可
        contents.length ? contents.wrapAll(dom) : self.append(dom)
      })
    }
    

    需要注意的是這個函數(shù)和前面的wrapAll和wrap有點不一樣,這里強調(diào)的是將當前元素中的內(nèi)容(包括元素節(jié)點和文本節(jié)點)進行包裹。

    unwrap

    移除集合中每個元素的直接父節(jié)點,并把他們的子元素保留在原來的位置

    unwrap: function () {
      // 通過parent()獲取當前元素集合的所有直接父節(jié)點
      // 將獲取到的父節(jié)點集合進行遍歷
      this.parent().each(function () {
        // 將該父節(jié)點替換為該父節(jié)點的所有子節(jié)點
        $(this).replaceWith($(this).children())
      })
      return this
    },
    
    
    結(jié)尾

    呼呼呼,終于寫完了,快累死了。歡迎大家指正文中的問題。

    參考

    讀Zepto源碼之操作DOM

    Zepto源碼分析-zepto模塊

    ownerDocument

    insertBefore

    innerHTML

    《JavaScript高級程序設(shè)計第三版》

    文章記錄

    form模塊

    zepto源碼分析之form模塊(2017-10-01)

    zepto模塊

    這些Zepto中實用的方法集(2017-08-26)

    Zepto核心模塊之工具方法拾遺 (2017-08-30)

    看zepto如何實現(xiàn)增刪改查DOM (2017-10-2)

    event模塊

    mouseenter與mouseover為何這般糾纏不清?(2017-06-05)

    向zepto.js學(xué)習(xí)如何手動觸發(fā)DOM事件(2017-06-07)

    誰說你只是"會用"jQuery?(2017-06-08)

    ajax模塊

    原來你是這樣的jsonp(原理與具體實現(xiàn)細節(jié))(2017-06-11)

    文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/51348.html

    相關(guān)文章

    • Zepto如何實現(xiàn)刪改DOM

      摘要:先看下圖,我們以刪除元素,插入元素復(fù)制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。 前言 dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復(fù)制...

      Clect 評論0 收藏0
    • Zepto如何實現(xiàn)刪改DOM

      摘要:先看下圖,我們以刪除元素,插入元素復(fù)制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。 前言 dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復(fù)制...

      VioletJack 評論0 收藏0
    • Zepto中數(shù)據(jù)緩存原理與實現(xiàn)

      摘要:有一個模塊,專門用來做數(shù)據(jù)緩存,允許我們存放任何與相關(guān)的數(shù)據(jù)。在匹配元素上存儲任意相關(guān)數(shù)據(jù)或返回匹配的元素集合中的第一個元素的給定名稱的數(shù)據(jù)存儲的值。確定元素是否有與之相關(guān)的數(shù)據(jù)。 前言 以前我們使用Zepto進行開發(fā)的時候,會把一些自定義的數(shù)據(jù)存到dom節(jié)點上,好處是非常直觀和便捷,但是也帶來了例如直接將數(shù)據(jù)暴露出來會出現(xiàn)安全問題,數(shù)據(jù)以html自定義屬性標簽存在,對于瀏覽器本身來說...

      macg0406 評論0 收藏0
    • Zepto學(xué)習(xí)關(guān)于"偏移"的那些事

      摘要:獲得當前元素相對于的位置。返回一個對象含有和當給定一個含有和屬性對象時,使用這些值來對集合中每一個元素進行相對于的定位。獲取對象集合中第一個元素相對于其的位置。結(jié)尾以上就是中與偏移相關(guān)的幾個的解析,歡迎指出其中的問題和有錯誤的地方。 前言 這篇文章主要想說一下Zepto中與偏移相關(guān)的一些事,很久很久以前,我們經(jīng)常會使用offset、position、scrollTop、scrollLe...

      hzx 評論0 收藏0

    發(fā)表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <