简单实现vue3相关功能,带你探索它的奥秘(基本按照源码名称和流程)
下面我一步一步带大家执行一遍代码,让大家有一个清楚的认知:
页面初始化vue3一般都是通过createApp函数去创建Vue实例的,而该函数会去调用ensureRenderer函数返回的createApp函数
createApp又是从哪里来的呢,它是通过createRenderer
函数返回的,
这个函数在vue3中叫自定义渲染器,可以通过这个函数自定义自己的渲染逻辑,比如小程序,app。
从上图中发现createApp还包装了一层函数,名叫createAppAPI,该函数会返回一个创建Vue实例
的函数,当调用mount函数时,会执行渲染页面的相关dom操作,renderComponentRoot生产vnode,通过副作用监听数据更新,每次更新响应式数据
,重新执行render函数,render函数中的patch函数比较最小差异进行更新,这里比vue2
做的好的地方是对动态节点的标记
生成虚拟dom的地方在renderComponentRoot函数中,这里我在index.html文件中是通过h函数
返回的虚拟dom,所以调用setup返回值是一个返回虚拟dom的函数
,在我的代码中叫getVnode,这个是我自己命名的,源码中并没有这个名字
当执行h函数时,会根据第三个实参(字符串模板)进行渲染,这里我投机取巧,通过eval和Function实现的,当执行new Function生成的函数时,会触发attrs.props(obj.a)的get,而h函数是在watchEffect函数(副作用)中执行的,所以会被收集到targetsMap里,这样数据进行set的时候,页面就会重新渲染了
既然vue是通过副作用去监听数据变化的,那么下面我们看一看watchEffect是咋实现的
watchEffect将函数进行了包装,在触发传入的fn的时候会触发fn内响应式数据
的get,从而触发track方法收集副作用函数
当副作用依赖的响应式数据
变化的时候,触发set,从而触发trigger,trigger搜寻被这个响应式数据
以来的所有副作用并执行它们。
最后我们说说Vue响应式是怎么做到的,上面我说了触发get,set,那get,set是什么呢,其实就是Vue通过ES6的Proxy类代理了传给reactive函数的对象,当查询该对象下的数据时会触发get,
当改变对象下的数据时会触发set,这就是响应式的具体含义