当前位置: 首页 > Web前端 > JavaScript

petite-vue源码分析-从静态视图开始

时间:2023-03-26 23:14:17 JavaScript

代码库结构介绍示例各种使用示例脚本包发布脚本测试测试用例srcdirectivesv-ifapp.tscreateAppfunctionblock.ts等内置指令的实现块对象上下文。ts上下文对象eval.ts提供表达式计算函数如v-if="count===1"scheduler.ts调度器utils.ts工具函数walk.ts模板解析如果要自己构建版本,在里面执行即可控制台npmrunbuild就可以了。深入理解静态视图的渲染过程静态视图是指第一次渲染后,不会因为UI状态改变而触发重新渲染。其中,视图不包含任何UI状态,第一次渲染后不再根据UI状态更新状态。本文将解释前者。示例:

第一次进入它是createApp方法,它的作用是创建根上下文对象(rootcontext)、全局作用域对象(rootscope)并返回mount、unmount和directive方法。然后使用mount方法找到具有[v-scope]属性的子节点(不包括匹配[v-scope][v-scope]的后代节点),并为其创建根块对象。源码如下(基于这个例子,为了方便阅读,我截取了部分源码)://file./src/app.tsexportconstcreateApp=(initialData:any)=>{//创建根上下文objectconstctx=createContext()//全局作用域对象,作用域对象实际上是一个反应对象ctx.scope=reactive(initialData)/*将作用域的函数成员的this绑定到作用域。*如果使用箭头函数给函数成员赋值,则上述操作对该函数成员无效。*/bindContextMethods(ctx.scope)/*根块对象集合*petite-vue支持多个根块对象,但是这里我们可以简化为只支持一个根块对象。*/letrootBlocks:Block[]return{//简化为必须挂载在带有`[v-scope]`的元素下mount(el:Element){letroots=el.hasAttribute('v-scope')?[el]:[]//创建根块对象rootBlocks=roots.map(el=>newBlock(el,ctx,true))returnthis},unmount(){//当节点被卸载(removeChild)时执行块对象清理。注意:该动作不会在界面刷新时触发。rootBlocks.forEach(block=>block.teardown())}}}虽然代码很短,但是引出了三个核心对象:上下文对象(context)、作用域(scope)和块对象(block)。它们之间的关系是:上下文对象(context)和作用域(scope)是1对1的关系;上下文对象(context)和块对象(block)是多对多的关系,其中块对象(block)指向当前的上下文对象(context),并通过指向父上下文对象(context)父Ctx;作用域(scope)和块对象(block)是一对多的关系。具体结论是:根上下文对象(context)可以通过ctx被多个根块对象引用;当创建块对象(block)时,会在当前上下文对象(context)的基础上创建一个新的上下文对象(context),并由parentCtx指向原来的上下文对象(context);在解析过程中,v-scope会在当前作用域对象的基础上构建一个新的作用域对象,并复制当前的上下文对象(context),形成一个新的上下文对象(context),供子节点解析和渲染,但不影响当前块对象指向的上下文。下面我们一一了解。作用域(scope)这里的作用域与我们写JavaScript时所说的作用域是一致的。用于限制函数和变量的可用范围,减少命名冲突。它具有以下特点:作用域之间存在父子关系和兄弟关系,整体形成一棵作用域树;子作用域中的变量或属性可以覆盖祖先作用域中具有相同名称的变量或属性的可访问性;如果只有祖先作用域存在对变量或属性的赋值,将赋值给祖先作用域的变量或属性。//全局范围varglobalVariable='hello'varmessage1='there'varmessage2='bye'(()=>{//局部范围Aletmessage1='localscopeA'message2='seeyou'console.log(globalVariable,message1,message2)})()//echo:hellolocalscopeAseeyou(()=>{//localscopeBconsole.log(globalVariable,message1,message2)})()//Echo:你好,看到你了,范围是附加到上下文的,所以范围的创建和销毁自然位于上下文的实现中(./src/context.ts)。另外,petite-vue中的scope并不是普通的JavaScript对象,而是经过@vue/reactivity处理的响应式对象。目的是一旦作用域成员被修改,触发相关副作用函数的执行,从而重新渲染界面。块对象(block)作用域(scope)用于管理JavaScript变量和函数的可用作用域,而块对象(block)用于管理DOM对象。//文件./src/block.ts//基于示例,我截断了代码exportclassBlock{template:Element|DocumentFragment//不是指向$template,而是当前解析的模板元素ctx:Context//有一个块对象创建的上下文对象parentCtx?:Context//当前块对象所属的上下文对象,根块objecthasnocontextobject//基于上面的例子,没有使用