Vue 응답성의 원리는 무엇입니까? Vue 응답성 원리 분석

不言
풀어 주다: 2018-09-10 15:33:51
원래의
2660명이 탐색했습니다.

이 기사에서는 Vue 응답성의 원리가 무엇인지 설명합니다. Vue의 반응성 원칙에 대한 분석은 특정 참고 가치가 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

initState

new Vue() => _init() => initState:

function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}
로그인 후 복사

Vue 인스턴스에 소품과 메서드가 있는지 확인 , 데이터, 계산, 해당 초기화 함수 호출

initProps 및 initData

주요 작업은 DefineProperty를 호출하여 마운트를 얻는 것입니다. 각각의 속성(이 후크가 트리거되면 현재 속성의 dep 인스턴스가 현재 감시자의 deps, 즉 구독하는 종속성인 현재 Dep.target으로 푸시됩니다. Dep.target은 다음과 같습니다. 그리고 dep 인스턴스는 현재 감시자(즉, 관찰자가 subs 배열로 푸시됨)와 set 메서드(종속 하위의 모든 관찰자에게 업데이트 메서드를 호출하도록 알립니다)도 푸시합니다.

initCompulated

이 함수의 기능은 계산된 객체의 모든 속성을 탐색하고 속성에 새로운 계산된 감시자를 제공하는 것입니다(계산된 속성에서). 계산된 속성을 사용해야 하는 감시자를 구독하도록 종속성 종속성이 정의됩니다. 또한 DefineProperty를 호출하여 계산할 get(get 메소드) 및 set 메소드를 마운트합니다(set 메소드는 전달 여부를 결정하고 전달되지 않으면 noop 빈 함수로 설정됩니다) #🎜 🎜#계산된 속성의 get 메서드는 다음 함수의 반환입니다. 값 함수

function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      watcher.depend()
      return watcher.evaluate()
    }
  }
}
로그인 후 복사
watcher.dependent()에 주의하세요. 이 메서드를 사용하면 이 속성을 사용하는 감시자 관찰자가 계산된 속성 감시자는 이를 구독하는 감시자를 자신의 하위 항목으로 푸시합니다(계산된 속성 값이 변경되면 이를 구독하는 감시자 관찰자에게 알림이 전송됩니다)

watcher.evaluate(), 이 메서드는 감시자의 get 메서드를 호출하는 것입니다. 감시자의 get 메서드는 pushTarget을 호출하여 이전 Dep.target 인스턴스를 스택에 푸시하고 계산할 Dep.target을 설정한다는 점에 유의해야 합니다. watcher, 계산된 속성이 의존하는 반응형 속성은 감시자는 하위 항목으로 푸시되므로 종속 응답 속성이 변경되면 이를 구독하는 계산된 감시자에게 알림이 전송됩니다. 그런 다음 계산된 속성을 구독하는 감시자에게 업데이트 메서드를 호출하도록 알리고 get 메서드에서 계산된 속성 키에 바인딩된 핸들러 함수를 호출하여 값을 계산합니다.

initWatch

감시자는 사용자 감시자입니다(구성 요소에서 개발자가 사용자 정의함).

initWatch의 기능은 watch의 속성을 순회하고 정의된 $watch를 호출하는 것입니다

Vue.prototype.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true // 代表该watcher是用户自定义watcher
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      cb.call(vm, watcher.value)
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }
로그인 후 복사
코드에서 새 Watcher가 호출되면 render watcher와 동일합니다. watcher의 get 메소드를 호출하고 pushTarget을 호출하여 현재 사용자 감시자를 Dep.target에 할당합니다. get()의 명령문 value = this.getter.call(vm, vm)은 사용자 정의 감시자가 모니터링하는 응답 속성 가져오기를 트리거합니다. 방법을 사용하고 현재 사용자를 변경합니다. watcher는 이 속성이 의존하는 하위 항목에 푸시하므로 사용자가 감시자가 모니터링하는 속성 집합이 트리거된 후 종속성을 구독하는 감시자는 업데이트를 트리거하라는 알림을 받습니다. 즉, 감시에 바인딩된 키에 해당하는 핸들러가 트리거됩니다. 그런 다음 popTarget을 호출하여 스택을 팝하고 Dep.target에 할당합니다.

$mount

initState 초기화 작업은 대략 여기까지 하고, $mount 를 실행하여 렌더링 작업을 시작합니다

$mount 주요 작업: 새로운 렌더링 생성 Watcher, 그리고 updateCompent를 콜백으로 전달하고

updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }
new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
로그인 후 복사
을 실행합니다. 세 감시자 중 새로운 감시자가 있으면 계산된 감시자만 처음에 get() 메서드를 실행하지 않습니다. $mount의 새 렌더링 감시자는 get() 메서드와 pushTarget을 호출하여 현재 렌더링 감시자를 Dep.target에 할당합니다. 다음으로 vm._update(vm._render(), hydrating)를 실행하는 updateComponent를 호출하는 하이라이트가 나옵니다. 여기서 렌더링 함수는 HTML에 사용되는 반응형 속성의 get 후크를 트리거합니다. get 후크는 반응형 속성의 종속 인스턴스 dep가 현재 렌더링을 변환하도록 합니다. 감시자는 하위 배열로 푸시되므로 종속 응답 속성이 변경되면 하위를 순회하여 구독한 감시자에게 update()를 호출하도록 알립니다.

Example

watcher와 dep를 조정하는 방법에 대해 모두가 혼란스러울 수도 있습니다.

<div id="app">
      <div>{{a}}</div>
      <div>{{b}}</div>
    </div>
new Vue({
  el: "#app",
  data() {
    return {
      a:1,
    }
  },
  computed:{
    b() {
      return a+1
    }
  },
})
로그인 후 복사
바로 시작하겠습니다. 렌더링., dep 및 감시자에 대해서만 이야기

$mount: 새로운 렌더링 감시자(감시자의 get 메소드는 렌더링 감시자를 Dep.target에 할당함)가 vm._update(vm._render(), hydrating)를 트리거합니다. 렌더링 시 html에 사용된 응답 속성이 먼저 사용된 다음 a의 get 후크가 트리거됩니다. 여기서 dep.dependent()는 현재 렌더링 감시자를 In으로 푸시합니다. 속성의 dep의 subs 배열입니다.

실행을 계속하고 b(b는 계산된 속성의 값)에 액세스하면 계산된 속성의 get 메서드가 트리거됩니다. 계산된 속성의 get 메서드는 계산된 Getter 함수에서 watcher.dependent()가 실행된 후 계산된 Getter 함수입니다. Watcher의 의존 메소드는 계산용으로만 예약되어 있습니다. 감시자가 사용합니다.

위에서 언급한 것처럼 Compute Watcher 외에 다른 두 Watcher도 New에 있습니다. 그 후, get 메소드가 실행되고 계산됩니다. 새로운 작업이 완료된 후 감시자는 무엇을 합니까? 새로운 dep를 생성할 것입니다.

계산된 감시자에 대해 방금 언급한 watcher.dependent() 메서드로 돌아갑니다. 해당 기능은 this.dep.dependent()를 실행하는 것입니다(여기에서는 계산된 감시자가 정의한 dep가 사용됩니다). this.dep.dependent()는 현재 렌더링 감시자가 계산된 속성 종속성을 구독하도록 합니다. 또한 계산된 속성은 계산된 속성의 값이 수정될 때 렌더링 감시자를 자체 하위 항목으로 푸시합니다. , 업데이트()를 호출하도록 하위의 감시자에게 알리므로 계산된 속성 값이 변경되면 페이지를 새로 고칠 수 있습니다.

앞서 언급한 b의 계산된 속성을 트리거한 get 후크로 돌아갑니다. get 후크는 최종적으로 watcher.evaluate()를 실행하고 watcher.evaluate()는 계산된 watcher의 get() 메서드를 실행합니다.

이 시점에서 중요한 점은 Dep.target(렌더링 감시자)이 targetStack 스택에 푸시되고(나중에 계속 사용하기 위해 꺼낼 수 있도록 저장한 후) 이 계산된 속성의 계산된 감시자입니다. Dep.target에 할당됩니다. get 메소드에서 value = this.getter.call(vm, vm)은 계산된 속성에 바인딩된 핸들러를 실행합니다.

위의 예와 같이 + 1을 반환합니다. a를 사용하면 a의 get 후크가 트리거되고 get 후크는 dep.dependent()를 호출합니다. dep.dependent()는 계산된 감시자가 dep를 deps 배열에 저장하도록 하고 a의 dep는 현재 dep를 저장합니다. Dep.target(계산된 감시자)은 subs 배열에 저장됩니다. 현재 예에서 a의 하위 항목은 [render watcher, 계산된 감시자]이므로 a 값의 변경 사항은 a의 하위 항목에 있는 감시자를 통과합니다. 그리고 update() 메소드를 호출합니다. html에 사용된 a는 계산된 속성 감시자가 update() 메소드를 호출하면 자체 하위에 알립니다([render 감시자]) 렌더링 중 감시자가 업데이트 메소드를 호출하면 HTML에서 사용되는 계산된 속성 b가 dom을 새로 고칩니다. 계산이 완료된 후) 값이 변경되는지 비교하십시오.

계산됨 watcher의 get() 메소드는 마지막으로 popTarget()을 호출하고, 이전에 저장된 렌더 감시자를 스택에서 꺼내 Dep.target에 할당합니다. 이때 제 예제의 targetStack은 빈 배열이 됩니다.

Render watcher의 get 메서드는 실행이 끝나면 스택에서 튀어나오며 이때 Dep.target에 할당된 값은 비어 있게 됩니다.

관련 권장 사항:

Vue 데이터 응답성 원칙 분석

Vue의 응답성 원칙 정보(자세한 튜토리얼)


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

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿