Vue에서 this를 남용하여 데이터의 데이터를 읽는 것을 피하다

8575 단어 vuethisdata데이터

앞말


Vue에서 데이터 옵션은 좋은 것입니다. 데이터를 안으로 잃어버리면 Vue 구성 요소 중 어느 곳에서든this를 통해 데이터의 데이터를 읽을 수 있습니다.그러나this를 남용하여 데이터의 데이터를 읽는 것을 피해야 한다. 어디에 남용을 피해야 하는지, 남용이 어떤 결과를 초래할지 본 칼럼은 하나하나 밝힐 것이다.

1,this로 데이터의 데이터를 읽는 과정


Vue 원본에서 데이터에 getter 함수와setter 함수를 추가하여 응답식으로 변환합니다.getter 함수 코드는 다음과 같습니다.

function reactiveGetter() {
 var value = getter ? getter.call(obj) : val;
 if (Dep.target) {
  dep.depend();
  if (childOb) {
   childOb.dep.depend();
   if (Array.isArray(value)) {
    dependArray(value);
   }
  }
 }
 return value
}
this로 데이터의 데이터를 읽을 때 getter 함수를 터치하여 var value = getter ? getter.call(obj) : val;를 통해 값을 얻은 후 실행return value하여 데이터를 읽는 목적을 실현합니다.
여기에서 Dep.target이 존재할 때,this를 사용하여 데이터의 데이터를 읽을 때 의존을 수집한다는 결론을 얻을 수 있다.만약this를 남용하여 데이터의 데이터를 읽으면 여러 번 반복적으로 의존을 수집하여 성능 문제가 발생할 수 있습니다.

2. Dep.target은 언제 존재합니까


Dep.target은 종속 값입니다.의존은 Watcher 또는 구독자라고도 합니다.Vue에는 세 가지 의존이 있는데 그 중 두 가지는 흔히 볼 수 있는 것이 바로 watch(탐지기)와computed(계산 속성)이다.템플릿을 처음 렌더링하는 과정에서 만들어진 숨겨진 의존도 있다.
Dep.target은 생성에 의존할 때 값을 부여하고, 의존은 구조 함수인 Watcher로 생성합니다.

function Watcher(vm, expOrFn, cb, options, isRenderWatcher) {
 //...
 if (typeof expOrFn === 'function') {
  this.getter = expOrFn;
 } else {
  this.getter = parsePath(expOrFn);
 }
 this.value = this.lazy ? undefined : this.get();
};
Watcher.prototype.get = function get() {
 pushTarget(this);
 try {
  value = this.getter.call(vm, vm);
 } catch (e) {
  
 }
 return value
};
Dep.target = null;
var targetStack = [];
function pushTarget(target) {
 targetStack.push(target);
 Dep.target = target;
}
구조 함수인 Watcher에서 마지막으로 실례 방법get을 실행하고, 실례 방법get에서 실행pushTarget(this)에서 Dep.target에 값을 부여합니다.
종속성은 Vue 페이지나 구성 요소가 처음 렌더링될 때 만들어지기 때문에 성능 문제는 처음 렌더링이 너무 느린 문제입니다.

3. 데이터의 데이터를 읽기 위해this를 남용하는 곳


Dep.target이 존재할 때this를 남용하여 데이터에 있는 데이터를 읽는 코드를 실행하면 성능 문제가 발생할 수 있기 때문에 이 코드가 어디에 쓰여 실행되는지 알아야 한다. 다시 말하면this를 남용하여 데이터에 있는 데이터를 읽으면 성능 문제가 발생할 수 있는지 알아야 한다.
두 번째 소절에서 Dep.target이 부여된 후 실행됩니다value = this.getter.call(vm, vm). 그중this.getter은 함수입니다. 만약this로 데이터 데이터를 읽으면 의존을 수집하고 남용하면 성능 문제가 발생합니다.this.getter는 의존을 만드는 과정에서 값을 부여하고 의존하는 this.getter마다 다르다.다음은 하나하나 소개하겠습니다.
  • watch(탐지기)가 의존하는 this.getter함수는 parsePath함수이고 그 함수 매개 변수는 탐지의 대상이다.
  • 
    var bailRE = new RegExp(("[^" + (unicodeRegExp.source) + ".$_\\d]"));
    function parsePath(path) {
     if (bailRE.test(path)) {
      return
     }
     var segments = path.split('.');
     return function(obj) {
      for (var i = 0; i < segments.length; i++) {
       if (!obj) {
        return
       }
       obj = obj[segments[i]];
      }
      return obj
     }
    }
    
    아래와 같은 코드의 aa.b.c 은 매개 변수로 전입parsePath 함수는 this.getter 함수에 부여된 값을 되돌려주고, 실행this.getter.call(vm, vm)this.athis.a.b.c 의 값을 얻는다.이 과정에서this를 남용하여 데이터의 데이터를 읽는 장면은 존재하지 않습니다.
    
    watch:{
     a:function(newVal, oldVal){
     // 
     }
    }
    vm.$watch('a.b.c', function (newVal, oldVal) {
     //  
    })
    
  • computed(계산속성)에 의존하는 this.getter는 두 가지가 있는데 계산속성의 값이 함수라면 this.getter 이 함수입니다.속성을 계산하는 값이 대상이라면 this.getter 이 대상의 get 속성 값이고 get 속성 값도 함수입니다.이 함수는this를 남용하여 데이터의 데이터를 읽는 장면이 존재할 수 있습니다. 예를 들어 코드는 다음과 같습니다.
  • 
    computed:{
     d:function(){
      let result = 0;
      for(let key in this.a){
       if(this.a[key].num > 20){
        result += this.a[key].num + this.b + this.c;
       }else{
        result += this.a[key].num + this.e + this.f;
       }
      }
      return result;
     }
    }
    
    계산 속성 d에서this를 남용하여 데이터 데이터를 읽는 것이 존재합니다.그 중에서 this.a는 수조이다. 이때 Dep.target의 값은 계산 속성 d라는 의존이다. 순환this.a에서this를 사용하여 중 a, b, c, e, f의 데이터를 가져와 이 데이터를 일련의 복잡한 논리 연산으로 계산 속성 d라는 의존을 반복적으로 수집한다.계산 속성 d의 값을 가져오는 속도가 느려져 성능 문제가 발생합니다.
  • Watcher를 렌더링하는 this.getter 함수는 다음과 같습니다.
  • 
    updateComponent = function() {
     vm._update(vm._render(), hydrating);
    };
    
    그중vm._render()은template 템플릿에서 생성된 렌더링 함수render를 가상DOM(VNode):vnode = render.call(vm._renderProxy, vm.$createElement);으로 변환합니다. 예를 들어 렌더링 함수render가 무엇인지 설명합니다.
    예를 들어 template 템플릿:
    
    <template>
     <div class="wrap">
     <p>{{a}}<span>{{b}}</span></p>
     </div>
    </template>
    
    다음과 같이 vue-loader를 통해 렌더링 함수 렌더링이 생성됩니다.
    
    (function anonymous() {
     with(this) {
      return _c('div', {
       attrs: {
        "class": "wrap"
       }
      }, [_c('p', [_v(_s(a)), _c('span', [_v(_s(b))])])])
     }
    })
    
    그 중에서 with문장의 역할은 한 개 또는 한 조의 문장에 기본 대상을 지정하는 것이다. 예를 들어 with(this){ a + b }this.a + this.b 와 같다. 그러면 템플릿에서 {{ a }} 를 사용하면 데이타의 a 데이터를 읽을 수 있다.그러므로template 템플릿에서 생성된 렌더링 함수render에서도this를 남용하여 데이터의 데이터를 읽는 장면이 존재할 수 있습니다.예를 들어, 코드는 다음과 같습니다.
    
    <template>
     <div class="wrap">
     <div v-for=item in list>
      <div> {{ arr[item.index]['name'] }} </div>
      <div> {{ obj[item.id]['age'] }} </div>
     </div>
     </div>
    </template>
    
    그 중에서 v-for 순환list 수조를 사용하는 과정에서this로 데이터에서arr,obj의 데이터를 끊임없이 읽고 이 데이터로 하여금 일련의 복잡한 논리 연산을 해서 이 의존을 반복적으로 수집하게 하여 첫 번째 렌더링의 속도가 느려지고 성능 문제가 발생한다.

    넷째,this를 남용하여 데이터의 데이터를 읽는 것을 피하는 방법


    위에서 말한 바와 같이 계산 속성과template 템플릿에서this를 남용하여 데이터의 데이터를 읽으면 여러 차례 반복적으로 의존을 수집하여 성능 문제가 발생할 수 있습니다. 그러면 어떻게 이런 상황을 피해야 합니까?
  • 계산 속성에서 어떻게 피할 것인가
  • ES6 대상의 부호화 값을 사용하여 속성을 계산하는 값은 하나의 함수이고 그 매개 변수는 Vue의 실례화this 대상이며 상기 계산 속성에서this를 남용하는 예에서 이렇게 최적화할 수 있다.
    최적화 이전:
    
    computed:{
     d:function(){
      let result = 0;
      for(let key in this.a){
       if(this.a[key].num > 20){
        result += this.a[key].num + this.b + this.c;
       }else{
        result += this.a[key].num + this.e + this.f;
       }
      }
      return result;
     }
    }
    
    최적화 후:
    
    computed: {
     d({ a, b, c, e, f }) {
     let result = 0;
     for (let key in a) {
      if (a[key].num > 20) {
      result += a[key].num + b + c;
      } else {
      result += a[key].num + e + f;
      }
     }
     return result;
     }
    }
    
    상기 해구부치를 이용하여 데이터 데이터 중의 a, b, c, e, f부치를 대응하는 변수 a, b, c, e, f에 미리 부여한 다음에 계산 속성에서 이러한 변수를 통해 데이터 데이터에 접근할 수 있고 데이터에 대응하는 데이터의 의존 수집을 촉발하지 않는다.이렇게this로만 데이터의 데이터를 한 번 읽었고 한 번만 의존 수집을 촉발하여 여러 번 반복적으로 수집에 의존하여 발생하는 성능 문제를 피했다.
  • template 템플릿에서 피하는 방법
  • v-for 순환에 사용되는 데이터를 미리 처리하고 v-for 순환에서 수조, 대상 유형의 데이터를 읽지 마십시오.상술한template 템플릿에서this를 남용하는 예에서 이렇게 최적화할 수 있습니다.
    가령list,arr,obj는 모두 서버가 되돌아온 데이터이고,arr와obj는 어떠한 모듈 렌더링에도 사용되지 않는다고 가정하면 이렇게 최적화할 수 있다.
    최적화 이전:
    
    <template>
     <div class="wrap">
     <div v-for=item in list>
      <div> {{ arr[item.index]['name'] }} </div>
      <div> {{ obj[item.id]['age'] }} </div>
     </div>
     </div>
    </template>
    
    최적화 후:
    
    <template>
     <div class="wrap">
     <div v-for=item in listData>
      <div{{item.name}} </div>
      <div>{{item.age}}</div>
     </div>
     </div>
    </template>
    <script>
    const arr = [];
    const obj = {}
    export default {
     data() {
     return {
      list: [],
     }
     },
     computed: {
     listData: function ({list}) {
      list.forEach(item => {
      item.name = arr[item.index].name;
      item.age = obj[item.id].age;
      })
      return list;
     }
     },
    }
    </script>
    
    이상은 Vue에서this를 남용하여 데이터의 상세한 내용을 읽는 것을 피하는 것입니다. Vue에서this를 남용하는 것을 피하는 것에 관한 더 많은 자료는 저희 다른 관련 글을 주목해 주십시오!

    좋은 웹페이지 즐겨찾기