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

資訊專欄INFORMATION COLUMN

少俠請留步,來一起實現個MVVM!

lily_wang / 1469人閱讀

摘要:一起來實現一個框架最近手癢,當然也是為了近階段的跳槽做準備,利用周五時光,仿照用法,實現一下的雙向綁定數據代理大胡子模板指令,等。

一起來實現一個mvvm框架

最近手癢,當然也是為了近階段的跳槽做準備,利用周五時光,仿照vue用法,實現一下mvvm的雙向綁定、數據代理、大胡子{{}}模板、指令v-on,v-bind等。當然由于時間緊迫,里面的編碼細節沒有做優化,還請各位看官多多包涵!看招:

實現原理

數據的劫持觀察(observe)

觀察者模式(watcher)

使用es6的類class實現(當然,沒有考慮到兼容性,只是為了實現而已)

代碼:

數據劫持

_observe(obj){
        // 遞歸遍歷
        // let value;
        for (const key in obj) {
          let value;
          if (obj.hasOwnProperty(key)){
            // 利用原理 劫持數據---發布訂閱

            value = obj[key];
            if (typeof value === "object") {
              console.log("value", value)
              this._observe(value)
            }

            // 訂閱(key)數據
            if (!this._binding[key]) {this._binding[key]= []};
            let binding = this._binding[key]
            // 重寫getter, setter
            Object.defineProperty(obj, key, {
              enumerable: true,
              configurable: true,
              get() {
                return value
              },
              set(newVal) {
                if (value === newVal) return false;
                value = newVal
                console.log("newvalue", value)
                // 主要value更新,就發布通知(監聽這個key的所有的)watcher更新(改變dom)
                binding.forEach(watcher => {
                  console.log("watcher", watcher)
                  watcher.update()
                });
              }
            })
          }
        }
      }

實例代理數據

_proxyData(data, vm) {
        // data身上的所有屬性全部掛載到vm實例上
        for (const key in data) {
          // let val = data[key];
          // ctx.key = val;
          Object.defineProperty(vm, key, {
            configurable: true,
            enumerable: true,
            get() {
              return data[key];
            },
            set(newVal) {
              data[key] = newVal;
              vm._observe(newVal)
            }
          })
        }
      }

模板編譯,添加發布訂閱

_compile(root){
        // 獲取所有節點
        let nodes = root.childNodes
        
        // 遞歸編譯
        Array.from(nodes).forEach(node => {
          // 針對每一個節點進行處理

          // 元素節點
          if (node.nodeType === 1) {//只考慮綁定了一個指令
            // 獲取節點的屬性集合
            
            const attributes = Array.from(node.attributes);

            // 指令進行編譯
            if (hasDirective(attributes, "v-bind")) {
              const attrVal = getDirectiveValue(node, attributes, "v-bind");
              const exp = getDirectiveParams(attributes, "v-bind");
              // const 
              node.setAttribute(exp, this.$data[attrVal])
              this._binding[attrVal].push(new watcher({
                vm: this, 
                el: node,
                exp,
                attr: attrVal
              }))
            }
            if (hasDirective(attributes, "v-on")) {
              const eventName = getDirectiveParams(attributes, "v-on");
              node.addEventListener(eventName, (e) => {
                this.$methods[getDirectiveValue(node, attributes, "v-on")].call(this)
              })
            }
            if (node.hasAttribute("v-model") && node.tagName === "INPUT" || node.tagName === "TEXTAREA") {
              let attrVal = node.getAttribute("v-model");
              this._binding[attrVal].push(new Watcher({
                  vm: this,
                  el: node,
                  attr: attrVal,
                  name: "v-model"
                }))
              node.addEventListener("input", e=> {
                this.$data[attrVal] = node.value;
              })
              node.value = this.$data[attrVal]
            }

            // 遞歸接著處理
            if (node.hasChildNodes()) {
              this._compile(node)
            }
          }

          // 文本節點
          if (node.nodeType === 3) {
            let text = node.textContent;

            let keyArr = [];
            // 獲取{{變量}},用正則去匹配;watcher去觀察{{變量}}(包裹元素),
            let newText = text.replace(/{{(w+)}}/g, (match, p0)=> {
              keyArr = [...keyArr, p0];
              // 替換屬性為真正的屬性值
              return this.$data[p0]
            })
            node.textContent = newText;

            // 把整個文本節點進行監控{{v1}}-----{{v2}};添加到訂閱到數組里等待通知
            keyArr.forEach(key => {
              // !this._binding[key] && (this._binding[key] = [])
              this._binding[key].push(new Watcher({
                vm: this,
                el: node,
                attr: text
              }))
            })
          }
        })
      }

觀察者實例

class Watcher {
      constructor({
        vm,
        name,
        el,
        exp,
        attr,
      }) {
        this.vm = vm;
        this.el = el;
        this.name = name;
        this.exp = exp;
        this.attr = attr;
      }
      // 更新text,或更新屬性
      update() {
        // 改變節點的屬性
        if (this.el.nodeType === 1) {
          // this.el.value = this.vm.$data[this.exp]
          if (this.name === "v-model") {
            console.log("value", this.el)
            this.el.value = this.vm.$data[this.attr]
          }
          this.el[this.attr] = this.vm.$data[this.exp]
        }
        // 文本節點
        else {
          let text = this.attr;
          // 獲取{{變量}},用正則去匹配;watcher去觀察{{變量}}(包裹元素),
          let newText = text.replace(/{{(w+)}}/g, (match, p0)=> {
            // 替換屬性為真正的屬性值
            return this.vm.$data[p0]
          })
          this.el.textContent = newText;
        }
      }
    }

整體代碼



  
  
  
  vue實現
  


  

{{title}}

{{text}}

我點的時候就會變化{{number}}---{{number}}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94277.html

相關文章

  • 少俠留步,圖片預覽術

    摘要:少年,我看你骨骼精奇,是萬中無一的武學奇才,我這有本圖片流秘籍,見與你有緣,就送于你了。文件大小,單位為字節,該屬性只讀。用來讀取或文件數據,基于文件大小不同,讀取的過程為異步。 showImg(https://segmentfault.com/img/remote/1460000016276887); 少年,我看你骨骼精奇,是萬中無一的武學奇才,我這有本《圖片流》秘籍,見與你有緣,就...

    岳光 評論0 收藏0
  • H5手機端開發問題匯總及解決方案

    摘要:方案回退時,跳到頁面頂部。踏坑第九式日期轉換的問題將日期字符串的格式符號替換成。歡迎感興趣的各路武林豪杰加入。 前言 少俠,請留步,相見必是緣分,贈與你一部《踏坑秘籍》 扎馬步 踏坑第一式 ios豎屏拍照上傳,圖片被旋轉問題 解決方案 // 幾個步驟 // 1.通過第三方插件exif-js獲取到圖片的方向 // 2.new一個FileReader對象,加載讀取上傳的圖片 // 3.在f...

    Codeing_ls 評論0 收藏0
  • H5手機端開發問題匯總及解決方案

    摘要:方案回退時,跳到頁面頂部。踏坑第九式日期轉換的問題將日期字符串的格式符號替換成。歡迎感興趣的各路武林豪杰加入。 前言 少俠,請留步,相見必是緣分,贈與你一部《踏坑秘籍》 扎馬步 踏坑第一式 ios豎屏拍照上傳,圖片被旋轉問題 解決方案 // 幾個步驟 // 1.通過第三方插件exif-js獲取到圖片的方向 // 2.new一個FileReader對象,加載讀取上傳的圖片 // 3.在f...

    Jaden 評論0 收藏0

發表評論

0條評論

lily_wang

|高級講師

TA的文章

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