vue 탐지 데이터 의 변화 에 대한 기본 적 인 실현

10589 단어 vue조사 데이터
1.Object 의 변화 조사
데이터 변 화 를 탐지 하 는 논 리 를 모 의 해 보 겠 습 니 다.
우리 가 해 야 할 일 을 강조 하 자.데이터 변 화 는 외부 에 알 리 고(외부 에서 자신의 논리 적 처 리 를 다시 하 는 것,예 를 들 어 보 기 를 다시 과장 하 는 것).
인 코딩 을 시작 하기 전에 우 리 는 먼저 다음 과 같은 몇 가지 질문 에 대답 해 야 한다.
1.대상 의 변 화 를 어떻게 조사 합 니까?
  • 은 Object.defineProperty()를 사용 합 니 다.데 이 터 를 읽 을 때 getter 를 터치 하고 데 이 터 를 수정 하면 setter 를 터치 합 니 다.
  • 은 대상 의 변 화 를 조사 할 수 있어 야 데이터 가 변화 할 때
  • 에 통 지 를 보 낼 수 있다.
    2.데이터 가 변 할 때 우 리 는 누구 에 게 통지 합 니까?
  • 데 이 터 를 사용 하 는 곳 을 알려 줍 니 다.데 이 터 는 템 플 릿 에 사용 할 수도 있 고 vm.$watch()에 사용 할 수도 있 습 니 다.장소 가 다 르 고 행동 도 다 릅 니 다.예 를 들 어 템 플 릿 을 렌 더 링 하려 면 다른 논 리 를 해 야 합 니 다.그래서 아예 한 가지 유형 을 추상적으로 추정한다.데이터 가 변 할 때 알려 주 고 다른 곳 에 알려 줍 니 다.
  • 이라는 종 류 는 Watcher 라 고 이름 을 지 었 다.중개 야.
  • 3.누구 에 게 의지 하나 요?
  • 통지 하 는 사람 에 게 의지 하고 Watcher 에 의존한다.
  • 4.언제 통지 합 니까?
  • 데이터 수정 할 때setter 에서
  • 을 알 린 거 예요.
    5.언제 수집 의존?
  • 데이터 로 된 곳 을 알려 야 하기 때 문 입 니 다.데이터 로 데 이 터 를 읽 어야 합 니 다.우 리 는 데 이 터 를 읽 을 때 수집 할 수 있 습 니 다.즉,getter 에서
  • 을 수집 할 수 있 습 니 다.
    6.어디로 모 을 까?
  • 은 각 속성 에서 하나의 배열 을 정의 할 수 있 고 이 속성 과 관련 된 의존 도 는 모두 안에
  • 을 넣 을 수 있다.
    인 코딩 은 다음 과 같 습 니 다(직접 실행 가능).
    
    //     ,      
    let globalData = undefined;
    
    //         
    function defineReactive (obj,key,val) {
        //     
        let dependList = []
        Object.defineProperty(obj, key, {
          enumerable: true,
          configurable: true,
          get: function () {
            //     (Watcher)
            globalData && dependList.push(globalData)
            return val
          },
          set: function reactiveSetter (newVal) {
            if(val === newVal){
                return
            }
            //      (Watcher)
            dependList.forEach(w => {
                w.update(newVal, val)
            })
            val = newVal
          }
        });
    }
    
    //   
    class Watcher{
        constructor(data, key, callback){
            this.data = data;
            this.key = key;
            this.callback = callback;
            this.val = this.get();
        }
        //                  
        get(){
            //        globalData
            globalData = this;
            //           
            let value = this.data[this.key]
            globalData = undefined
            return value;
        }
        //          ,        
        update(newVal, oldVal){
            this.callback(newVal, oldVal)
        }
    }
    
    /*         */
    let data = {};
    //   name        
    defineReactive(data, 'age', '88')
    //     age    ,     Watcher,   Watcher      
    new Watcher(data, 'age', (newVal, oldVal) => {
        console.log(`  :newVal = ${newVal} ; oldVal = ${oldVal}`)
    })
    
    data.age -= 1 //      :   :newVal = 87 ; oldVal = 88
    콘 솔 에서 data.age -= 1 을 계속 실행 하면 :newVal = 86 ; oldVal = 87 을 출력 합 니 다.
    Data,defineReactive,dependelist,Watcher 와 외부의 관계 도 를 첨부 합 니 다.

    우선 defineReactive()방법 을 통 해 data 를 응답 식(defineReactive(data, 'age', '88'))으로 전환 합 니 다.
    외부 에 서 는 Watcher 를 통 해 데이터(let value = this.data[this.key])를 읽 고 데이터 의 getter 는 트리거 되 기 때문에 globalData 를 통 해 Watcher 를 수집 합 니 다.
    데이터 가 수정(data.age -= 1)되면 setter 를 터치 하고 의존(dependelist)을 알 리 며 의존 은 Watcher(w.update(newVal, val))에 알 리 고 마지막 으로 Watcher 는 외부 에 알 립 니 다.
    질문
    생각해 보 세 요:위의 예 를 들 어 delete data.age 을 계속 집행 하면 외부 에 알 릴 수 있 습 니까?
    아니요.setter 를 터치 하지 않 기 때 문 입 니 다.이어서 보 세 요.
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id='app'>
            <section>
                {{ p1.name }}
                {{ p1.age }}
            </section>
        </div>
    <script>
    const app = new Vue({
        el: '#app',
        data: {
            p1: {
                name: 'ph',
                age: 18
            }
        }
    })
    </script>
    </body>
    </html>
    실행 하면 페이지 에 ph 18 이 표 시 됩 니 다.데 이 터 를 변경 하면 보기 가 다시 렌 더 링 된다 는 것 을 알 고 콘 솔 에서 delete app.p1.name 을 실행 하 였 으 며 페이지 에 변화 가 없 음 을 발견 하 였 습 니 다.이 는 위의 예제 에서 delete data.age 을 실행 하 는 것 과 마찬가지 로 setter 를 촉발 하지 않 고 외부 에 알 리 지 않 는 다.
    이 문 제 를 해결 하기 위해 Vue 는 두 개의 API 를 제공 합 니 다.vm.$set 와 vm.$delete 입 니 다.app.$delete(app.p1, 'age') 을 계속 실행 하면 페이지 에 아무런 정보 가 없 음 을 발견 할 수 있 습 니 다.
    주:여기 서 app.p1.sex = 'man' 을 실행 하면 데이터 p1 을 사용 하 는 곳 도 알려 지지 않 습 니 다.이 문 제 는 vm.$set 를 통 해 해결 할 수 있 습 니 다.
    3.Array 의 변화 조사
    3.1 배경
    만약 에 데이터 가 let data = {a:1, b:[11, 22]} 이 라면 Object.defineProperty 를 통 해 응답 식 으로 전환 한 후에 우 리 는 데 이 터 를 data.a = 2 으로 수정 하면 외부 에 알 릴 것 입 니 다.이것 은 이해 하기 쉽 습 니 다.마찬가지 로 data.b = [11, 22, 33] 도 외부 에 알 리 지만 다른 방식 으로 데이터 b 를 수정 하면 이렇게 data.b.push(33) 은 외부 에 알 리 지 않 을 것 이다.setter 를 가지 않 았 기 때문이다.예 시 를 보십시오.
    
    function defineReactive(obj, key, val) {
        Object.defineProperty(obj, key, {
          enumerable: true,
          configurable: true,
          get: function () {
            console.log(`get val = ${val}`)
            return val
          },
          set: function reactiveSetter (newVal) {
            if(val === newVal){
                return
            }
            console.log(`set val = ${newVal}; oldVal = ${val}`)
            val = newVal
          }
        });
    }
    
    //         {1}
    let data = {}
    defineReactive(data, 'a', [11,22])
    data.a.push(33)     // get val = 11,22               (     setter)    {2}     
    data.a              // get val = 11,22,33 
    data.a = 1          // set val = 1; oldVal = 11,22,33(   setter)
    push()방법 을 통 해 배열 의 값 을 변경 합 니 다.setter(행{2})를 실행 하지 않 았 거나 외부 에 알 릴 수 없습니다.Object.definePropery()방법 을 통 해 대상 을 응답 식 으로 만 바 꿀 수 있 고 배열 을 응답 식 으로 바 꿀 수 없습니다.
    사실 Object.define Propery()는 배열 을 응답 식 으로 바 꿀 수 있 습 니 다.예 시 를 보십시오.
    
    //        ,     ( {1})  :
    let data = []
    defineReactive(data, '0', 11)
    data[0] = 22    // set val = 22; oldVal = 11
    data.push(33)   //                          {10}
    Object.definePropery()는 배열 을 응답 식 으로 바 꿀 수 있 지만 data.push(33)(행{10})이라는 방식 으로 배열 을 수정 하여 외부 에 알 리 지 않 습 니 다.
    그래서 Vue 에서 데 이 터 를 응답 식 으로 바 꾸 고 두 가지 방식 을 사 용 했 습 니 다.대상 은 Object.defineProperty()를 사용 합 니 다.배열 은 다른 세트 를 사용한다.
    3.2 실현
    es6 에 서 는 프 록 시 로 배열 의 변 화 를 탐지 할 수 있다.예 시 를 보십시오.
    
    let data = [11,22]
    let p = new Proxy(data, {
        set: function(target, prop, value, receiver) {
            target[prop] = value;
            console.log('property set: ' + prop + ' = ' + value);
            return true;
        }
        })
    console.log(p)
    p.push(33)
    /*
      :
    [ 11, 22 ]
    property set: 2 = 33
    property set: length = 3
    */
    es6 예전 부터 좀 귀 찮 았 어 요.차단 기 를 사용 할 수 있어 요.원 리 는 [].push() 을 실행 할 때 배열 원형(Array.prototype)중의 방법 을 호출 하 는 것 이다.[].push()Array.prototype 사이 에 차단 기 를 추가 하고 [].push() 을 호출 할 때 차단기 의 push()방법 을 먼저 실행 합 니 다.차단기 의 push()는 Array.prototype 의 push()방법 을 호출 합 니 다.예 시 를 보십시오.
    
    //     
    let arrayPrototype = Array.prototype
    
    //      
    let interceptor = Object.create(arrayPrototype)
    
    //                 
    ;('push,pop,unshift,shift,splice,sort,reverse').split(',')
    .forEach(method => {
        let origin = arrayPrototype[method];
        Object.defineProperty(interceptor, method, {
            value: function(...args){
                console.log(`   : args = ${args}`)
                return origin.apply(this, args);
            },
            enumerable: false,
            writable: true,
            configurable: true
        })
    });
    
    //   
    let arr1 = ['a']
    let arr2 = [10]
    arr1.push('b')
    //      arr2    
    Object.setPrototypeOf(arr2, interceptor)    // {20}
    arr2.push(11)       //    : args = 11
    arr2.unshift(22)    //    : args = 22
    이 예 는 배열 자체 의 내용 을 바 꿀 수 있 는 7 가지 방법 을 모두 차단기 에 넣 었 다.어떤 배열 의 변 화 를 조사 하려 면 이 배열 의 원형 을 차단기(행{20})로 가리 키 십시오.push 등 7 가지 방법 으로 이 배열 을 수정 하면 차단기 에서 작 동 되 어 외부 에 알 릴 수 있 습 니 다.
    여기까지 우 리 는 배열 의 변 화 를 조사 하 는 임무 만 완수 했다.
    데이터 변 화 를 외부 에 알리다.위의 인 코딩 의 실현 은 Object 데이터 만 을 위 한 것 이 고,여 기 는 Array 데이터 가 필요 합 니 다.
    우리 도 같은 문 제 를 생각해 보 자.
    1.배열 의 변 화 를 어떻게 조사 합 니까?
  • 차단기
  • 2.데이터 가 변 할 때 우 리 는 누구 에 게 통지 합 니까?
  • Watcher
  • 3.누구 에 게 의지 하나 요?
  • Watcher
  • 4.언제 통지 합 니까?
  • 데이터 수정 할 때차단기 에서 알림.
  • 5.언제 수집 의존?
  • 데이터 로 된 곳 을 알려 야 하기 때 문 입 니 다.데이터 로 데 이 터 를 읽 어야 합 니 다.데 이 터 를 읽 을 때 수집 하 다.이것 은 대상 수집 의존 과 같다.
  • {a: [11,22]} 예 를 들 어 우리 가 a 배열 을 사용 하려 면 반드시 방문 대상 의 속성 a 를 사용 해 야 한다.
  • 6.어디로 모 을 까?
  • 대상 은 모든 속성 에서 의존 도 를 수집 하지만,여기 서 배열 이 차단기 에서 의존 도 를 촉발 할 수 있 는 지 를 고려 해 야 합 니 다.위 치 는
  • 을 조정 해 야 할 수도 있 습 니 다.
    여기까지 입 니 다.더 이상 펼 치지 않 겠 습 니 다.다음 글 에서 저 는 vue 에서 데이터 수사 와 관련 된 소스 코드 를 떼 어 내 고 본 고 와 결합 하여 간단하게 분석 하 겠 습 니 다.
    질문
    
    //        vue.js。             
    <div id='app'>
            <section>
                {{ p1[0] }}
                {{ p1[1] }}
            </section>
    </div>
    <script>
    const app = new Vue({
        el: '#app',
        data: {
            p1: ['ph', '18']
        }
    })
    </script>
    실행 후 페이지 에 ph 18 을 표시 합 니 다.콘 솔 에서 app.p1[0] = 'lj' 페이지 를 실행 하면 반응 이 없습니다.배열 은 지정 한 7 가지 방법 을 호출 해 야 차단 기 를 통 해 외부 에 알 릴 수 있 기 때 문 입 니 다.app.$set(app.p1, 0, 'pm') 페이지 를 실행 하면 pm 18 페이지 가 됩 니 다.
    이상 은 vue 수사 데이터 의 변화 에 대한 기본 적 인 실현 에 대한 상세 한 내용 입 니 다.vue 수사 데이터 의 변화 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기