vue3优点很多,它不仅拥有vue的响应式数据
,还借鉴了react的hooks,更加接近函数式编程
,在使用模板语法下,对于静态节点
和动态节点
的捕捉优化也非常到位,接下来我想简单实现一下vue3相关的一些功能带大家了解一下它
首先了解一下项目结构:
在这里,我主要用到了四数:
h:通过参数生成虚拟dom节点
createApp:用于页面初始化时,执行的方法,会根据传入的options挂载到mount定义的标签上
reative:将传入的对象进行响应式处理,当触发get,set,delete,执行内部相应的函数
watchEffect:一个立即执行的副作用,当调用该函数时,会将传入的函数里面的响应式数据
进行收集并在数据改变的时候触发函数再次执行
下面我一步一步带大家执行一遍代码,让大家有一个清楚的认知:
页面初始化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,这就是响应式的具体含义