>웹 프론트엔드 >JS 튜토리얼 >Vue 데이터 응답성 원리 분석

Vue 데이터 응답성 원리 분석

php中世界最好的语言
php中世界最好的语言원래의
2018-05-12 11:23:141662검색

이번에는 Vue 데이터 응답성의 원리에 대한 분석을 가져오겠습니다. Vue 데이터 응답성의 노트는 무엇인가요?

Foreword

Vue의 데이터 응답은 주로 Object.defineProperty()에 의존하는데, 전체 프로세스는 어떤가요? 우리 자신의 아이디어로 Vue의 길을 걷는다는 것은 실제로 Vue의 원칙을 최종점으로 삼는 것을 의미합니다.

이 문서의 코드는 모두 로우 프로파일 버전이며 많은 부분이 엄격하지 않습니다. 예를 들어 if(typeof obj === 'object')는 obj가 객체일 수도 있지만 obj가 객체인지 여부를 결정하는 것입니다. array 및 기타 유형. 그러나 단순화를 위해 이 기사에서는 판단 대상을 나타내기 위해 직접 작성합니다. Array.isArray()를 사용합니다.

데이터 변환

먼저 객체를 변환하는 함수를 작성해 보겠습니다.

왜 이 함수를 먼저 작성해야 할까요? 데이터 변환은 가장 기본적이고 중요한 단계이므로 이후의 모든 단계는 이 단계에 따라 달라집니다.

// 代码 1.1
function defineReactive (obj,key,val) {
 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   return val;
  },
  set: function (newVal) {
   //判断新值与旧值是否相等
   //判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身
   if(newVal === val || (newVal !== newVal && value !== value)){
    return ;
   }
   val = newVal;
  }
 });
}
예를 들어, const obj = {}, 그리고 나서 defineReactive(obj,'a',2) 메서드를 호출합니다. 이때 함수 ​​내에서 val=2, 그리고 obj.a의 값이 나올 때마다. obj.a를 설정할 때 val 값도 설정됩니다. (defineReactive가 호출될 때마다 val 값을 저장하기 위해 클로저가 생성됩니다.)

Process Discussion

검증 결과 실제로 이 함수를 사용할 수 있는 것으로 확인되었습니다. 그런 다음 응답 프로세스에 대해 논의해 보겠습니다.

데이터 입력

  1. 데이터 변환(defineReactive())

  2. 데이터가 변경되면 => 이벤트 트리거

  3. 세 번째 단계를 살펴보겠습니다. 1, 데이터 변경이 후속 이벤트를 어떻게 트리거합니까? 데이터를 변경하려면 먼저 데이터를 설정해야 합니다. 그런 다음 set()에 메서드를 추가하기만 하면 괜찮을 것입니다.

  4. 그리고 또 다른 중요한 질문이 있습니다.

Dependency Collection

데이터 변경 후 어떤 이벤트가 트리거될지 어떻게 알 수 있나요? Vue에서: 데이터 사용 => 뷰를 렌더링하는 데 데이터가 사용되므로 데이터를 얻을 때 종속성을 수집하는 것이 가장 좋습니다. Vue는 종속성을 수집하기 위해 데이터 속성을 변환할 때 Dep 인스턴스를 생성합니다.

// 代码 1.2
class Dep {
 constructor(){
  //订阅的信息
  this.subs = [];
 }
 addSub(sub){
  this.subs.push(sub);
 }
 removeSub (sub) {
  remove(this.subs, sub);
 }
 //此方法的作用等同于 this.subs.push(Watcher);
 depend(){
  if (Dep.target) {
   Dep.target.addDep(this);
  }
 }
 //这个方法就是发布通知了 告诉你 有改变啦
 notify(){
  const subs = this.subs.slice()
  for (let i = 0, l = subs.length; i < l; i++) {
   subs[i].update();
  }
 }
}
Dep.target = null;

Code 1.2는 Dep의 코드의 일부입니다. 당분간은 두 가지 메서드의 기능만 알면 됩니다.

dependent() --- 다른 측면을 수집하는 것으로 이해될 수 있습니다. 고려되지 않으면 이 함수는 addSub ()

  1. notify() --- 이 메서드는 더 직관적이며 모든 종속 update() 메서드를 실행합니다. 나중에 보기를 변경하면 됩니다.

  2. 이 글에서는 주로 데이터 응답 과정을 다루며 Watcher 클래스에 대해서는 심도 깊게 다루지 않으므로 Dep.2에서 메소드의 기능만 알면 됩니다.

  3. 그럼 이제 코드 1.1을 변경할 시간
//代码 1.3
function defineReactive (obj,key,val) {
 const dep = new Dep();
 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   if(Dep.target){
    //收集依赖 等同于 dep.addSub(Dep.target)
    dep.depend()
   }
   return val;
  },
  set: function (newVal) {
   if(newVal === val || (newVal !== newVal && val !== val)){
    return ;
   }
   val = newVal;
   //发布改变
   dep.notify();
  }
 });
}

이 코드에 의문점이 있는데 Dep.target이 무엇인가요? 종속성을 수집하기 위해 Dep.target이 필요한 이유는 무엇입니까?

Dep은 클래스이고 Dep.target은 dep 인스턴스의 속성이 아닌 클래스의 속성입니다.

  1. Dep 클래스는 전역적으로 사용 가능하므로 Dep.target은 전역적으로 액세스할 수 있으며 해당 값을 임의로 변경할 수 있습니다.

  2. get 메소드는 매우 일반적이며 데이터 값을 얻기 위해 사용할 때마다 dep.dependent()를 호출하는 것은 불가능합니다.

  3. dep.dependent()는 실제로 dep.addSub(Dep.target)입니다.

  4. 그럼 가장 좋은 방법은 사용하기 전에 Dep.target을 객체로 설정하고 구독이 완료된 후에 Dep.target = null을 설정하는 것입니다.

  5. 검증

이제 코드 웨이브의 사용성을 검증할 시간입니다

//代码 1.4
const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}};
//低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了)
const watcher = {
 addDep:function (dep) {
  dep.addSub(this);
 },
 update:function(){
  html();
 }
}
//假装这个是渲染页面的
function html () {
 document.querySelector('body').innerHTML = obj.html;
}
defineReactive(obj,'html','how are you');//定义响应式的数据
Dep.target = watcher;
html();//第一次渲染界面
Dep.target = null;

此时浏览器上的界面是这样的

然后在下打开了控制台开始调试,输入:

obj.html = 'I am fine thank you'

然后就发现,按下回车的那一瞬间,奇迹发生了,页面变成了

结尾

Vue数据响应的设计模式和订阅发布模式有一点像,但是不同,每一个dep实例就是一个订阅中心,每一次发布都会把所有的订阅全部发布出去。

Vue的响应式原理其实还有很大一部分,本文主要讨论了Vue是如何让数据进行响应,但是实际上,一般的数据都是很多的,一个数据被多处使用,改变数据之后观察新值,如何观察、如何订阅、如何调度,都还有很大一部分没有讨论。主要的三个类Dep(收集依赖)、Observer(观察数据)、Watcher(订阅者,若数据有变化通知订阅者),都只提了一点点。

之前写有一篇Vue响应式----数组变异方法,针对Vue中对数组的改造进行讨论。当然之后有更多其他的文章,整个数据响应流程还有很多内容,三个主要的类都还没有讨论完。

其实阅读源码不仅仅是为了知道源码是如何工作的,更重要的是学习作者的思路与方法,我写的文章都不长,希望自己能够每次专注一个点,能够真真实实领悟到这一个点的原理。当然也想控制阅读时间,免得大家看到一半就关闭了。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

React Form组件封装步骤详解

JS跨域POST实现步骤详解

위 내용은 Vue 데이터 응답성 원리 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.