Vue의 반응형 시스템 원리를 연구해 보았고, 이를 기록하고 싶었습니다. 동시에 Vue의 반응형 시스템을 직접 구현해 보기로 했습니다. 그래서 이 글을 작성하게 되었습니다.
개요
Vue 반응형 데이터의 초기화는 initState의 initData에서 이루어집니다. observe 함수를 사용해 vm 객체의 data 속성을 관찰한 후, getter와 setter 속성을 설정합니다.
따라서 최소한 세 가지 함수가 필요합니다: 속성 getter과 setter를 관찰하는 함수, getter과 setter를 트리거하는 监听者, 그리고 속성 의존성을 저장하는 收集框입니다. 저는 각각 observe, watcher, dep로 명명했습니다.
흐름
먼저 observe에서 data의 속성에 getter와 setter을 재귀적으로 추가합니다. 이후 watcher에서 속성 중 하나에 접근할 때, watcher 인스턴스가 getter 인터셉터를 트리거합니다. 그러면 해당 속성의 인터셉터가 watcher 인스턴스를 해당 속성의 클로저 의존성 수집기 dep에 추가합니다. 동시에 이 클로저 의존성 수집기를 watcher에 넣습니다.
이후, 위에서 언급한 속성을 수정할 때 observe에 정의된 setter 인터셉터가 트리거됩니다. 이때 dep의 watcher이 작동하기 시작하여 해당 watcher의 콜백을 실행합니다.
주의사항
getter를 트리거할 때 의존성이 중복 수집되지 않도록 하는 방법은?
watcher이 getter을 트리거할 때, 현재 속성의 의존성 수집기를 watcher의 Set 배열에 추가하여 비교합니다. 중복되는 경우 더 이상 추가하지 않습니다:
1 2 3 4 5 6 7
addDep (dep) { var id = dep.id; if (!this.depIds.has(id)) { // 一次求值时候的去重 this.deps.push(dep); dep.addSubs(this); // 再将 watcher 放到字段的 Dep 的实例 subs 中, 以供值变化的时候 执行 notity, 把 subs 中的 watcher 拉出来挨个执行一遍 } }
setter를 트리거할 때 콜백을 어떻게 실행하나요?
setter을 트리거할 때, 해당 속성에 포함된 watcher 배열을 꺼내어 하나씩 실행합니다:
저는 인생의 중요한 선택의 기로에 섰을 때, 누군가 최선의 방법을 알려주어 소중한 시간을 헛되이 보내지 않기를 바라곤 합니다. 그런 마음으로 저는 자주 블로그를 쓰며, 광활한 인터넷의 이 작은 구석에 제게는 단 한 번뿐인 인생 경험을 기록하여 도움이 필요한 분들에게 도움이 되기를 바랍니다.