English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Vue.js 원리 분석 중 observer 모듈 자세히 설명

소개

observer는 Vue의 핵심 모듈 중 가장 중요한 모듈 중 하나로(개인 의견), 뷰와 데이터의 반응형 업데이트를 구현할 수 있으며, 하위는 observer의 지원에 의존합니다.

주의사항:이 문서는 Vue@에 대한 것입니다2.1.8분석해 보겠습니다

observer 모듈은 Vue 프로젝트에서 src에 위치합니다/코어/observer는 모듈이 이러한 몇 가지 부분으로 나뉩니다:

  1. Observer: 데이터의 관찰자, 데이터 객체의 읽기와 쓰기 작업이 자신의 감독 아래에 있습니다
  2. Watcher: 데이터의 구독자, 데이터의 변경이 Watcher로 알려지고, Watcher에 의해相应的 작업이 수행됩니다. 예를 들어, 뷰 업데이트
  3. Dep: Observer와 Watcher의 연결고리, 데이터가 변경될 때 Observer에 의해 관찰되고, Dep에 의해 Watcher로 알려집니다

아래는 시각화입니다:

Observer

Observer 클래스는 src에 정의되어 있습니다/코어/관찰자/index.js에서 Observer의 생성자를 먼저 보겠습니다

constructor (value: any) {
 this.value = value
 this.dep = new Dep()
 this.vmCount = 0
 def(value, '__ob__', this)
 if (Array.isArray(value)) {
 const augment = hasProto
 ? protoAugment
 : copyAugment
 augment(value, arrayMethods, arrayKeys)
 this.observeArray(value)
 }
 this.walk(value)
 }
}

value는 관찰되어야 할 데이터 객체입니다. 생성자에서 value에 __ob__ 속성을 추가하여 데이터가 Observer에 관찰되었음을 표시합니다. value가 배열이면 observeArray를 사용하여 value를 순회하며 value의 각 요소에 respectively observe를 호출하여 관찰합니다. value가 객체이면 walk를 사용하여 value의 각 key를 순회하며 각 key에 defineReactive를 호출하여 해당 key의 set을 얻습니다./get 권한을 얻습니다.

위에서 사용한 몇 가지 함수의 기능을 설명해 보겠습니다:

  • observeArray: 배열을 순회하며 배열의 각 요소에 observe를 호출합니다.
  • observe: 객체에 __ob__ 속성이 있는지 확인합니다. 있으면, 해당 객체가 Observer의 관찰 중에 있다는 것을 의미합니다. 없으면, Observer를 새로 생성하여 객체를 관찰합니다(실제로는 몇 가지 추가적인 판단 로직이 있습니다. 이해하기 쉽게 설명하기 위해 생략합니다)
  • walk: 객체의 각 key를 순회하며, 객체의 각 key에 대한 데이터에 defineReactive를 호출합니다
  • defineReactive: Object.defineProperty을 통해 객체의 key 속성을 설정하여 해당 속성 값의 set을 캡처할 수 있습니다/get 동작. 일반적으로 Watcher의 인스턴스가 get 작업을 수행하며, 이 때 Watcher의 인스턴스가 자동으로 Dep 인스턴스의 의존성 배열에 추가됩니다. 외부에서 set이 트리거될 때, Dep 인스턴스의 notify를 통해 모든 의존된 watcher에게 업데이트를 알림을 전달합니다

위의 텍스트 설명이 이해가 잘 되지 않다면 다음 그림을 보세요:

Dep

Dep는 Observer와 Watcher 간의 중간체로, Observer에 서비스하는 구독 시스템으로도 생각할 수 있습니다. Watcher는 Observer의 Dep를 구독하며, Observer가 관찰하는 데이터가 변경될 때마다 Dep를 통해 모든 구독된 Watcher에게 알림을 전달합니다

Dep는 몇 가지 인터페이스를 제공합니다:

  • addSub: 전달받는 매개변수는 Watcher 인스턴스이며, Watcher 인스턴스를 의존성을 기록하는 배열에 저장합니다
  • removeSub: addSub과 상응하여, Watcher 인스턴스를 의존성을 기록하는 배열에서 제거합니다
  • depend: Dep.target에 현재 처리할 필요가 있는 Watcher 인스턴스를 저장합니다. depend를 호출하면 Watcher 인스턴스의 addDep 메서드를 호출합니다. addDep의 기능은 다음에 설명됩니다
  • notify: 의존성 배열에 있는 모든 watcher를 업데이트 작업을 위해 알림

Watcher

Watcher는 데이터 변경을 구독하고相应 작업(예: 뷰 업데이트)을 수행하는 데 사용됩니다. Watcher의 생성자 함수는 다음과 같이 정의됩니다:

constructor (vm, expOrFn, cb, options) {
 this.vm = vm
 vm._watchers.push(this)
 // options
 if (options) {
 this.deep = !!options.deep
 this.user = !!options.user
 this.lazy = !!options.lazy
 this.sync = !!options.sync
 }
 this.deep = this.user = this.lazy = this.sync = false
 }
 this.cb = cb
 this.id = ++uid // batching을 위한 uid
 this.active = true
 this.dirty = this.lazy // lazy watchers를 위해
 this.deps = []
 this.newDeps = []
 this.depIds = new Set()
 this.newDepIds = new Set()
 this.expression = process.env.NODE_ENV !== 'production'
 ? expOrFn.toString()
 : ''
 if (typeof expOrFn === 'function') {
 else {
 }
 this.getter = parsePath(expOrFn)
 if (!this.getter) {
 this.getter = function () {}
 process.env.NODE_ENV !== 'production' && warn(
 `Failed watching path: "${expOrFn}" ` +
 'Watcher는 간단한 점(.), 슬래시(/)를 허용합니다.-구분된 경로. ' +
 '전체 제어를 위해 함수를 사용하세요.',
 vm
 )
 }
 }
 this.value = this.lazy
 ? undefined
 : this.get()
}

매개변수에서, vm은 컴포넌트 인스턴스를, expOrFn은 구독할 데이터 필드(예: a.b.c와 같은 문자열) 또는 실행할 함수를, cb는 watcher 실행 후의 콜백 함수를, options는 옵션 객체로 deep, user, lazy 등의 구성을 포함합니다.

watcher 인스턴스에는 다음과 같은 메서드들이 있습니다:

  • get: Dep.target을 현재watcher 인스턴스로 설정하고, 이를 내부에서 this.getter를 호출합니다. 이때 Observer로 관찰된 데이터 객체가 값이 가져지면, 현재watcher 인스턴스가 자동으로 데이터 객체의 Dep 인스턴스를 구독합니다.
  • addDep: 매개변수 dep(Dep 인스턴스)를 받아 현재 watcher가 dep를 구독
  • cleanupDeps: newDepIds와 newDep에 기록된 dep 구독 정보를 지우기
  • update: 즉시 watcher를 실행하거나 watcher를 큐에 추가하여 통합 flush를 기다립니다
  • run: watcher를 실행하고, this.get()를 호출하여 값을 계산한 후 콜백을 트리거
  • evaluate: this.get()를 호출하여 값을 계산
  • depend: this.deps를 순회하며, 현재 watcher 인스턴스가 모든 dep를 구독
  • teardown: 현재 watcher 인스턴스의 모든 구독을 제거

배열 메서드

src/코어/관찰자/array.js에서, Vue 프레임워크는 배열의 push, pop, shift, unshift, sort, splice, reverse 메서드를 개조하여, 이 메서드를 호출할 때 자동으로 dep.notify()를 트리거하여, 배열의 이 메서드 호출 후 업데이트가 트리거되지 않는 문제를 해결합니다.

Vue의 공식 문서에서도 이에 대해 설명이 있습니다: http://cn.vuejs.org/v2/가이드/list.html#변환 메서드

결론

이 문서의 모든 내용이 끝납니다. 이 문서의 내용이 여러분의 학습이나 업무에 도움이 되길 바랍니다. 의문이 있으면 댓글을 남겨 주세요.

선언: 이 문서의 내용은 인터넷에서 가져왔으며, 원작자의 소유물입니다. 내용은 인터넷 사용자가 자발적으로 기여하고 업로드한 것이며, 이 사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다.涉嫌 저작권 내용이 있으면 이메일을 보내 주세요: notice#oldtoolbag.com(이메일을 보내는 경우, #을 @으로 변경하십시오. 신고하고 관련 증거를 제공하시면, 해당 내용이 실제로 위반된 경우, 이 사이트는 즉시 해당 위반 내용을 삭제합니다.)

추천 합니다