VueJS 데이터 구동 및 추적 분석 의존

Vue 데이터 바 인 딩 원리 에 대한 분석 이 있 었 는데,최근 에 되 돌아 볼 필요 가 있어 서 수필 에 올 렸 습 니 다.
이전에 자신의 Mvvm 에서 setter 로 model 을 관찰 하고 인터페이스의 모든 view Model 을 model 에 연결 합 니 다.model 이 바 뀌 면 모든 view Model 을 업데이트 하고 새 값 을 인터페이스 에 렌 더 링 합 니 다.동시에 감청 인터페이스 에서 v-model 로 연 결 된 모든 input 를 감청 하고 addEventListener 이 벤트 를 통 해 새 값 을 model 에 업데이트 하여 양 방향 연결 을 완성 합 니 다.
그러나 그 프로그램 은 define Property 를 이해 하 는 것 외 에는 한 푼 의 가치 도 없다.
  • 컴 파일 노드 가 없습니다
  • 표현 식 의존 처리 가 없습니다
  • 여기 서 표현 식 의존 문 제 를 해결 할 것 입 니 다.vue 템 플 릿 의 컴 파일 은 다음 절 에 소개 하 겠 습 니 다.
    데이터 정의 getter&setter
    
    class Observer {
      constructor(data) {
        this._data = data;
        this.walk(this._data);
      }
    
      walk(data) {
        Object.keys(data).forEach((key) => { this.defineRective(data, key, data[key]) })
      };
      defineRective(vm, key, value) {
        var self = this;
        if (value && typeof value === "object") {
          this.walk(value);
        }
        Object.defineProperty(vm, key, {
          get: function() {
            return value;
          },
          set: function(newVal) {
            if (value != newVal) {
              if (newVal && typeof newVal === "object") {
                self.walk(newVal);
              }
              value = newVal;
            }
          }
        })
      }
    }
    
    module.exports = Observer;
    
    
    이렇게 하면 모든 속성 에 getter 와 setter 를 추가 합 니 다.속성 이 하나의 대상 이 라면 재 귀적 으로 추가 합 니 다.
    속성 값 을 가 져 오 거나 속성 값 을 부여 하면 get 이나 set 를 촉발 합 니 다.set,즉 model 변 화 를 촉발 하면 모든 view Model 업 데 이 트 를 알 리 는 메 시 지 를 발표 할 수 있 습 니 다.
    
    defineRective(vm, key, value) {
      //                  。
      var dep = new Dep();
      var self = this;
      if (value && typeof value === "object") {
        this.walk(value);
      }
      Object.defineProperty(vm, key, {
        get: function() {
          return value;
        },
        set: function(newVal) {
          if (value != newVal) {
            if (newVal && typeof newVal === "object") {
              self.walk(newVal);
            }
            value = newVal;
            //       viewModel   
            dep.notify();
          }
        }
      })
    }
    
    
    그럼 Dep 는 어떻게 정의 하나 요?
    
    class Dep {
      constructor() {
        //     
        this.dependences = [];
      }
      //     
      addDep(watcher) {
        if (watcher) {
          this.dependences.push(watcher);
        }
      }
      //         
      notify() {
        this.dependences.forEach((watcher) => {
          watcher.update();
        })
      }
    }
    
    module.exports = Dep;
    
    
    이곳 의 모든 의존 은 하나의 Watcher 이다.
    Watcher 를 어떻게 정의 하 는 지.
    모든 Watcher 에는 하나의 표현 식 과 반전 함수 가 있 는 유일한 id 번호 가 있 습 니 다.
    예 를 들 어 표현 식 a+b;get 에서 계산 할 때 a 와 b 를 방문 합 니 다.JavaScript 는 단일 스 레 드 이기 때문에 언제든지 한 곳 만 JavaScript 코드 가 실 행 됩 니 다.Dep.target 을 전역 변수 로 현재 Watcher 의 표현 식 을 표시 한 다음 coptute 를 통 해 a,b 를 방문 하여 a 와 b 의 getter 를 촉발 하여 getter 에 Dep.target 을 의존 으로 추가 합 니 다.
    a 와 b 의 set 가 트리거 되면 update 함 수 를 호출 하여 의존 하 는 값 을 업데이트 합 니 다.
    
    var uid = 0;
    class Watcher {
      constructor(viewModel, exp, callback) {
        this.viewModel = viewModel;
        this.id = uid++;
        this.exp = exp;
        this.callback = callback;
        this.oldValue = "";
        this.update();
      }
    
      get() {
        Dep.target = this;
        var res = this.compute(this.viewModel, this.exp);
        Dep.target = null;
        return res;
      }
    
      update() {
        var newValue = this.get();
        if (this.oldValue === newValue) {
          return;
        }
        // callback    Dom      
        this.callback(newValue, this.oldValue);
        this.oldValue = newValue;
      }
    
      compute(viewModel, exp) {
        var res = replaceWith(viewModel, exp);
        return res;
      }
    }
    
    module.exports = Watcher;
    
    
    현재 표현 식 은 현재 model 아래 에서 실행 되 어야 하기 때문에 replace With 함수 로 with 를 대체 합 니 다.구체 적 으로 다른 수필 을 볼 수 있 습 니 다javascript 에서 with 의 대체 문법
    get 으로 의존 도 추가
    
    Object.defineProperty(vm, key, {
      get: function() {
        var watcher = Dep.target;
        if (watcher && !dep.dependences[watcher.id]) {
          dep.addDep(watcher);
        }
        return value;
      },
      set: function(newVal) {
        if (value != newVal) {
          if (newVal && typeof newVal === "object") {
            self.walk(newVal);
          }
          value = newVal;
          dep.notify();
        }
      }
    })
    이런 의존 을 첨가 하 는 방식 은 정말 교묘 하 다.
     여기 제 가 그림 을 하나 그 려 서 설명 을 했 어 요.

    마지막 으로 코드 를 통 해 간단하게 테스트 해 보 겠 습 니 다.
    
    const Observer = require('./Observer.js');
    const Watcher = require('./watcher.js');
    var data = {
      a: 10,
      b: {
        c: 5,
        d: {
          e: 20,
        }
      }
    }
    
    var observe = new Observer(data);
    
    var watcher = new Watcher(data, "a+b.c", function(newValue, oldValue) {
      console.log("new value is " + newValue);
      console.log("oldValue is " + oldValue);
    });
    console.log("\r
    "); console.log("a has changed to 50,then the expr should has value 55"); data.a = 50; console.log("\r
    "); console.log("b.c has changed to 50,then the expr should has value 122"); data.b.c = 72;; console.log("\r
    "); console.log("b.c has reseted an object,then the expr should has value 80"); data.b = { c: 30 }

    OK.대성 공.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기