<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>

          同事問了這樣一句話,我驚了。

          共 14982字,需瀏覽 30分鐘

           ·

          2021-03-31 21:26

          聽說關注我的公眾號的小伙伴,點贊,在看,轉(zhuǎn)發(fā)三連擊的小伙伴鹽值都不錯


          今天吃完飯,同事問了我一句話,相當讓我驚訝,你有什么想做卻沒有做的?我說沒有啊,我一直在探索啊,而且我也一直在做我想做的事情,假如我想到了,我可能會花時間去探索,然后如果感覺不適合我,我就放棄。


          所以我寫了關于這一系列的 Vue 迷你源碼系列,今天終于是最后一講了,我也不知道是什么樣的動力讓我堅持這么久,我覺得有兩點吧。


          第一點:我確實很喜歡寫東西,我小時候就特喜歡寫東西。

          第二點:就是為粉絲們做點什么,不能別人關注我,得出一些干貨


          喜歡你們多多點贊,關注我,謝謝,如果有需要了解的,可以在后臺跟我留言,或者加我微信跟我探討下,因為微信公眾號不能留言,只能自己自言自語,也不能跟我的粉絲們互動,所以如果有什么想了解的,可后臺留言,平時不忙的話,會回復的。


          好了今天就來總結一下之前的所有代碼吧

          實現(xiàn) MVVM 類 Vue 迷你框架(七)

          實現(xiàn) MVVM 類 Vue 迷你框架(六)

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

          實現(xiàn) MVVM 類 Vue 迷你框架(四)

          實現(xiàn) MVVM 類 Vue 迷你框架(三)

          實現(xiàn) MVVM 類 Vue 迷你框架(二)

          實現(xiàn) MVVM 類 Vue 迷你框架(一)

          MVVM 類 Vue 迷你框架(完結撒花)

          • 處理數(shù)據(jù)響應式,分為
          • 代理數(shù)據(jù)
          • 依賴收集
          • 觸發(fā)更新
          • 魔板編譯,解析插值,解析指令,解析事件

          完整的代碼如下:

          // 數(shù)組響應式處理
          // push, pop, reverse, shift, sort, splice, unshift
          const arrayMethods = ["push""pop""reverse""shift""unshift""sort""splice"];
          const originProto = Array.prototype;
          const arrayCopyProto = Object.create(originProto);

          arrayMethods.forEach(method => {
              arrayCopyProto[method] = function ({
                  // 原始操作
                  originProto[method].apply(thisarguments);

                  // 通知更新操作
              }
          })

          // 響應式數(shù)據(jù)
          function defineReactive(obj, key, val{
              observe(val); // 遞歸遍歷
              const dep = new Dep(); // 每個key對應創(chuàng)建一個Dep實例
              let curVal = val;
              Object.defineProperty(obj, key, {
                  get() {
                      Dep.target && dep.addDep(Dep.target); // 建立watcher與dep的映射關系
                      console.log(`get:${key}-${curVal}`);
                      return curVal;
                  },
                  set(newVal) {
                      if (newVal !== curVal) {
                          observe(newVal);
                          console.log(`set:${key}-${newVal}`);
                          curVal = newVal;
                          dep.notify(); // 通知更新
                      }
                  }
              })
          }


          function observe(obj{
              new Observer(obj);
          }

          // 屬性代理

          function proxy(vm{
              Object.keys(vm.$data).forEach(key => {
                  Object.defineProperty(vm, key, {
                      get() {
                          return vm.$data[key]
                      },
                      set(val) {
                          vm.$data[key] = val
                      }
                  })
              })
          }

          // MVue 類
          class MVue {
              constructor(options) {
                  this.$options = options;
                  this.$data = options.data(); // 這里 data 是函數(shù), 所以要執(zhí)行取返回值

                  // 對 data 選項做響應式處理
                  observe(this.$data);

                  // 代理數(shù)據(jù)
                  proxy(this);

                  // 編譯模板
                  new Compile(options.el, this);
              }
          }

          // Observer 用于管理 Watcher

          class Observer {
              constructor(value) {
                  this.$value = value
                  if (Array.isArray(value)) {
                      // 處理數(shù)組
                      // array 覆蓋原型,替換變更操作
                      value.__proto__ = arrayCopyProto;

                      // 對數(shù)組內(nèi)容元素執(zhí)行響應式
                      value.forEach(item => observe(item));
                  }
                  if (typeof value === 'object') {
                      // 處理對象
                      this.walk(value);
                  }
              }
              // 遍歷對象,響應式處理
              walk(obj) {
                  Object.keys(obj).forEach(key => defineReactive(obj, key, obj[key]));
              }
          }

          // Compile 編譯類

          class Compile {
              // 宿主元素
              constructor(el, vm) {
                  this.$el = document.querySelector(el);
                  this.$vm = vm;

                  if (this.$el) {
                      this.compile(this.$el);
                  }
              }
              // 判斷節(jié)點是不是含有 {{}} 的文本節(jié)點
              isInter(node) {
                  return node.nodeType === 3 && /{{.+}}/.test(node.textContent);
              }
              update = (node, key, dir) => {
                  const fn = this[dir + 'Updater']; // 查找指令
                  fn && fn(node, this.$vm[key]);

                  // 更新函數(shù)
                  new Watcher(this.$vm, key, (val) => {
                      fn && fn(node, val);
                  });
              }
              textUpdater(node, val) {
                  node.textContent = val;
              }
              htmlUpdater(node, val) {
                  node.innerHTML = val;
              }
              // 插值語法編譯
              compileText = (node) => {
                  let res = /{{(.+)}}/.exec(node.textContent)
                  console.log("res===>", res)
                  this.update(node, res[1], 'text');
              }

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

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


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

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

              // 節(jié)點元素的編譯
              compileElement(node) {
                  const nodeAttrs = Array.from(node.attributes);
                  nodeAttrs.forEach(attr => {
                      const { name, value } = attr;
                      // 指令處理
                      if (name.startsWith('m-')) {
                          const dir = this[name.slice(2)]; // 找出指令方法
                          dir && dir(node, value);
                      }
                      // 事件處理
                      if (name.startsWith('@')) {
                          // 找出開頭是 @ 的指令,例如 @click
                          const dir = name.slice(1);
                          // 事件監(jiān)聽
                          this.eventHandler(node, value, dir);
                      }
                  })
              }

              // 綁定監(jiān)聽函數(shù)
              eventHandler = (node, value, dir) => {
                  const { methods } = this.$vm.$options;
                  const fn = methods && methods[value];
                  fn && node.addEventListener(dir, fn.bind(this.$vm));
              }

              // 解析 model
              modelUpdater(node, val) {
                  node.value = val;
              }
              model = (node, key) => {
                  this.update(node, key, 'model');
                  node.addEventListener('input', e => {
                      this.$vm[key] = e.target.value
                  });
              }
          }

          // Watcher 類
          // 檢測數(shù)據(jù)變化

          class Watcher {
              constructor(vm, key, updater) {
                  this.$vm = vm;
                  this.$key = key;
                  this.$updater = updater;

                  Dep.target = this// 將當前實例指定在Dep的靜態(tài)屬性上
                  vm[key]; // 讀一下觸發(fā)get
                  Dep.target = null// 置空
              }

              // 未來更新 dom 的函數(shù),由 dep 調(diào)用
              update = () => {
                  this.$updater.call(this.$vm, this.$vm[this.$key])
              }
          }

          // 依賴收集

          class Dep {
              constructor() {
                  this.deps = [];
              }
              addDep = (watcher) => {
                  this.deps.push(watcher);
              }

              notify = () => {
                  this.deps.forEach(watcher => watcher.update())
              }
          }



          瀏覽 60
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  婷婷操精品 | 在线视频亚洲 | 水密桃视频网站 | 蜜乳一区二区三区有限公司 | 精品久久久久久中文字幕无码专区 |