Vue中响应式系统实现原理图文讲解

框架

每个组件实例都会对应一个watcher实例,在组件渲染过程中把接触过的数据property记录为依赖。当依赖项的setter触发时,会通知watcher,重新渲染组件

vue实例中的data选项,在初始化时会遍历该对象所有属性,并使用Object.defineProperty转为getter/setter。

组件结构

Observer:主要是将对象转为响应式对象,在getter中,会创建Dep来收集依赖

Dep:用于存放watcher,即副作用函数effectFn

Watcher:观察者,当有数据更新时,会触发update

源码解析

在哪里绑定vue实例与watcher实例

在src/core/instance/lifecycle.ts中的mountComponent中

export function mountComponent(
 vm: Component,
 el: Element | null | undefined,
 hydrating?: boolean
): Component {
 vm.$el = el
 callHook(vm, 'beforeMount')
 let updateComponent
 /* istanbul ignore if */
 updateComponent = () => {
 vm._update(vm._render(), hydrating)
 }
 const watcherOptions: WatcherOptions = {
 before() {
 if (vm._isMounted && !vm._isDestroyed) {
 callHook(vm, 'beforeUpdate')
 }
 }
 }
 // we set this to vm._watcher inside the watcher's constructor
 // since the watcher's initial patch may call $forceUpdate (e.g. inside child
 // component's mounted hook), which relies on vm._watcher being already defined
 new Watcher(
 vm,
 updateComponent,
 noop,
 watcherOptions,
 true /* isRenderWatcher */
 )
 hydrating = false
 // flush buffer for flush: "pre" watchers queued in setup()
 const preWatchers = vm._preWatchers
 if (preWatchers) {
 for (let i = 0; i < preWatchers.length; i++) {
 preWatchers[i].run()
 }
 }
 // manually mounted instance, call mounted on self
 // mounted is called for render-created child components in its inserted hook
 if (vm.$vnode == null) {
 vm._isMounted = true
 callHook(vm, 'mounted')
 }
 return vm
}

vue实例中的data响应式初始化

在src/core/instance/state.ts/initData中,主要是observe(data)这个

function initData(vm: Component) {
 let data: any = vm.$options.data
 data = vm._data = isFunction(data) ? getData(data, vm) : data || {}
 if (!isPlainObject(data)) {
 data = {}
 }
 // proxy data on instance
 const keys = Object.keys(data)
 const props = vm.$options.props
 const methods = vm.$options.methods
 let i = keys.length
 while (i--) {
 const key = keys[i]
 if (props && hasOwn(props, key)) {
 
 } else if (!isReserved(key)) {
 proxy(vm, `_data`, key)
 }
 }
 // observe data
 const ob = observe(data)
 ob && ob.vmCount++
}

对Object的变化监测

Observer只追踪数据是否被修改,无法追踪新增和删除属性

Vue提供了Vue.prototype.$set和Vue.prototype.$delete,内部也是调用Observer的方法

import {
 set,
 del
} from '../observer/index'
Vue.prototype.$set = set
Vue.prototype.$delete = del
作者:kgduu原文地址:https://blog.csdn.net/xiexingshishu/article/details/129612230

%s 个评论

要回复文章请先登录注册