<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實現 MVVM 類 Vue 迷你框架(五)

          共 3539字,需瀏覽 8分鐘

           ·

          2021-03-29 21:11

          如何實現 MVVM 類 Vue 迷你框架(五)

          上面幾節(jié)課我們已經把數據代理,響應式處理搞完了,接下來需要做什么呢?當然是最難的一部分了,就是我們的編譯模板。

          使用到的dom編程方法

          • element.childNodes - 返回元素子節(jié)點的 NodeList(可直接使用forEach遍歷),換行和空格會被識別成文本節(jié)點。
          • element.nodeType - 返回元素的節(jié)點類型,元素節(jié)點為 1,文本節(jié)點為 3
          • element.nodeName - 返回元素的名稱,例如**“DIV”**
          • element.textContent - 設置或返回節(jié)點及其后代的文本內容
          • element.attributes - 指定節(jié)點的屬性Attr(含有name和value屬性)合 NamedNodeMap(不可直接遍歷)

          我們需要做什么呢?

          • 拿到我們需要的 DOM 元素
          • 然后需要解析 {{}} 模板插值
          • 解析 m-text 指令
          • 解析 m-html 指令

          所以我們需要一個編譯模板 Compile 類:

          class Compile {
           constructor(el, vm) {
               this.$el = document.querySelector(el);
                this.$vm = vm;
             // 判斷是否存在 el
                if(this.$el) {
                  this.compile(this.$el);
                }
             }
          }

          判斷節(jié)點是不是具有 {{}} 文本節(jié)點

          class Compile {
           constructor{
               // ...
             }
             isInter(node) {
               return node.nodeType === 3 && /{{.*}}/.test(node.textContent);
             }
          }

          接下來我們封裝一個用于更新指令的公用方法:

          update(node, key, dir) {
           const fn = this[dir+'Updater']; // 查找指令方法
             fn && fn(node, this.$vm[key];
             
             // 更新
             new Watcher(this.$vm, key, val => {
               fn && fn(node, key)
             })
          }

          如果是文本內容我們就只更新文本:

          textUpdater(node, val) {
           node.textContent = val
          }

          text(node, key) {
           this.update(node, key, 'text')
          }

          如果是 html 內容就只更新 htm 內容:

          htmlUpdater(node, val) {
           node.innerHTML = val
          }

          html(node, key) {
           this.update(node, key, 'html');
          }

          模板插值解析:

          compileText(node) {
           this.update(node, RegExp.$1'text')
          }

          最后就是實現 compile(node) 方法:

          // 遞歸傳入節(jié)點,根據節(jié)點類型做不同操作
              compile(el) {
                  // 拿到子節(jié)點
                  const childNodes = el.childNodes;
                  childNodes.forEach(node => {
                      if (node.nodeType === 1) {
                          console.log('元素節(jié)點', node.nodeName);
                      } else if (this.isInter(node)) {
                          this.compileText(node);
                          console.log('文本節(jié)點', node.textContent);
                      }

                      if (node.childNodes) {
                          this.compile(node);
                      }
                  });
              }


          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情性爱视频网站 | 成人在线免费观看三级片 | 久久久久久亚洲成人电影 | 精品人妻一区二区三区视频在线 | 亚洲人妻AV在线 |