이 기사에서는 Vue 응답성의 원리가 무엇인지 설명합니다. Vue의 반응성 원칙에 대한 분석은 특정 참고 가치가 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
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 인스턴스에 소품과 메서드가 있는지 확인 , 데이터, 계산, 해당 초기화 함수 호출
주요 작업은 DefineProperty를 호출하여 마운트를 얻는 것입니다. 각각의 속성(이 후크가 트리거되면 현재 속성의 dep 인스턴스가 현재 감시자의 deps, 즉 구독하는 종속성인 현재 Dep.target으로 푸시됩니다. Dep.target은 다음과 같습니다. 그리고 dep 인스턴스는 현재 감시자(즉, 관찰자가 subs 배열로 푸시됨)와 set 메서드(종속 하위의 모든 관찰자에게 업데이트 메서드를 호출하도록 알립니다)도 푸시합니다.
이 함수의 기능은 계산된 객체의 모든 속성을 탐색하고 속성에 새로운 계산된 감시자를 제공하는 것입니다(계산된 속성에서). 계산된 속성을 사용해야 하는 감시자를 구독하도록 종속성 종속성이 정의됩니다. 또한 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.evaluate(), 이 메서드는 감시자의 get 메서드를 호출하는 것입니다. 감시자의 get 메서드는 pushTarget을 호출하여 이전 Dep.target 인스턴스를 스택에 푸시하고 계산할 Dep.target을 설정한다는 점에 유의해야 합니다.
watcher, 계산된 속성이 의존하는 반응형 속성은
감시자는 하위 항목으로 푸시되므로 종속 응답 속성이 변경되면 이를 구독하는 계산된 감시자에게 알림이 전송됩니다.
그런 다음 계산된 속성을 구독하는 감시자에게 업데이트 메서드를 호출하도록 알리고 get 메서드에서 계산된 속성 키에 바인딩된 핸들러 함수를 호출하여 값을 계산합니다.
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() } }
$mount 주요 작업: 새로운 렌더링 생성 Watcher, 그리고 updateCompent를 콜백으로 전달하고
updateComponent = () => { vm._update(vm._render(), hydrating) } new Watcher(vm, updateComponent, noop, { before () { if (vm._isMounted) { callHook(vm, 'beforeUpdate') } } }, true /* isRenderWatcher */)
<div id="app"> <div>{{a}}</div> <div>{{b}}</div> </div> new Vue({ el: "#app", data() { return { a:1, } }, computed:{ b() { return a+1 } }, })
$mount: 새로운 렌더링 감시자(감시자의 get 메소드는 렌더링 감시자를 Dep.target에 할당함)가 vm._update(vm._render(), hydrating)를 트리거합니다. 렌더링 시 html에 사용된 응답 속성이 먼저 사용된 다음 a의 get 후크가 트리거됩니다. 여기서 dep.dependent()는 현재 렌더링 감시자를 In으로 푸시합니다. 속성의 dep의 subs 배열입니다.
계산된 감시자에 대해 방금 언급한 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 응답성 원리 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!