当前位置: 首页 > news >正文

免费的建网站软件网站做不做备案有什么区别

免费的建网站软件,网站做不做备案有什么区别,登录入口网址,清远网站关键字优化文章目录 一、编译流程1. 解读入口文件 packgages/vue/index.ts2. compile函数的运行流程 二、AST 解析器1. ast 的生成2. 创建ast的根节点3. 解析子节点 parseChildren#xff08;关键#xff09;4. 解析模版元素 Element模版元素解析-举例分析 一、编译流程 1. 解读入口文… 文章目录 一、编译流程1. 解读入口文件 packgages/vue/index.ts2. compile函数的运行流程 二、AST 解析器1. ast 的生成2. 创建ast的根节点3. 解析子节点 parseChildren关键4. 解析模版元素 Element模版元素解析-举例分析 一、编译流程 1. 解读入口文件 packgages/vue/index.ts 首先从Vue对象的入口开始packgages/vue/index.ts文件中只有compileToFunction函数 依赖注入编译函数至runtimeregisterRuntimeCompiler(compileToFunction)runtime 调用编译函数compileToFunction返回包含code的编译结果将code作为参数传入Function 的构造函数将生成函数赋值给render变量。将render函数作为编译结果返回 下面这个简单的模版 templatedivHello World/div /template经过编译后code返回的字符串为 const _Vue Vue return function render(_ctx, _cache) {with(_ctx) {const {openBlock: _openBlock, createBlock:_createBlock} _Vue;return (_openBlock(), _createBlock(div, null, Hello World)) } }拿到这个代码字符串的结果后第25行声明了一个render变量并将生成的代码字符串code 作为参数传入了new Function 构造函数生成了render函数。可以将上面的code字符串格式化。这里的render显而易见是一个柯里化的函数返回了一个函数函数内部通过with来扩展作用域链。最后入口文件返回了render变量并顺手缓存了render函数。在第一行入口文件创建了一个compileCache 对象用以缓存compileToFunction 函数生成的render 函数将template 参数作为缓存的key并在11行进行if分支做缓存判断如果该模版之前被缓存过则不再进行编译直接返回缓存中的render函数以此提高性能。 2. compile函数的运行流程 compile函数涉及到compile-dom 和compile-core 两个模块。 compile的运行流程 baseCompile命名理由因为compile-core是编译的核心模块接收外部的参数来按照规则完成编译而compile-dom是专门处理浏览器场景下的编译在这个模块下导出的compile函数是入口文件真正接收的编译函数。而compile-dom中的compile函数相对baseCompile也是一个更高阶的编译器。例如当Vue在weex或iOS或Android这些Native App中工作时compile-dom可能会被相关的移动端编译库来取代。baseCompile函数 从函数声明中看baseCompile接收template模版以及上层高阶编译器处理过的options编译选项最终返回一个CodegenResult类型的编译结果。 export interface CodegenResult {code: stringpreamble: stringast: RootNodemap?: RawSourceMap }看上方源码的第12行判断template模版是否为字符串如果是的话则会对字符串进行解析否则直接将template作为AST。我们平时写的vue代码都是以字符串的形式传递进去的。然后是第16行调用了transform函数以及传入了指令转换、节点等工具函数对由模版生成的AST进行转换。最后32行将转换好的ast传入进generate生成CodegenResult类型的返回结果。 二、AST 解析器 1. ast 的生成 ast的生成有一个三目运算符的判断如果传进来的template模版是一个字符串那么则调用baseParse解析模版字符串否则直接将template作为ast对象。 baseParse 函数 export function baseParse(content: string,options: ParserOptions {} ): RootNode {const context createParserContext(content, options) // 创建解析的上下文对象const start getCursor(context) // 生成记录解析过程的游标信息return createRoot( // 生成并返回 root 根节点parseChildren(context, TextModes.DATA, []), // 解析子节点作为 root 根节点的 children 属性getSelection(context, start)) }首先会创建解析的上下文根据上下文获取游标信息由于还未进行解析所以游标中的column、line、offset属性对应的都是template的起始位置。之后就是创建根节点并返回根节点至此ast树生成解析完成。 2. 创建ast的根节点 export function createRoot(children: TemplateChildNode[],loc locStub ): RootNode {return {type: NodeTypes.ROOT,children,helpers: [],components: [],directives: [],hoists: [],imports: [],cached: 0,temps: 0,codegenNode: undefined,loc} }该函数返回了一个RootNode类型的根节点对象其中我们传入的children参数会被作为根节点的children参数。 3. 解析子节点 parseChildren关键 function parseChildren(context: ParserContext,mode: TextModes,ancestors: ElementNode[] ): TemplateChildNode[] {const parent last(ancestors) // 获取当前节点的父节点const ns parent ? parent.ns : Namespaces.HTMLconst nodes: TemplateChildNode[] [] // 存储解析后的节点// 当标签未闭合时解析对应节点while (!isEnd(context, mode, ancestors)) {/* 忽略逻辑 */}// 处理空白字符提高输出效率let removedWhitespace falseif (mode ! TextModes.RAWTEXT mode ! TextModes.RCDATA) {/* 忽略逻辑 */}// 移除空白字符返回解析后的节点数组return removedWhitespace ? nodes.filter(Boolean) : nodes }parseChildren函数接收三个参数context解析器上下文mode文本数据类型ancestors祖先节点数据。函数执行首先会从祖先节点中获取当前节点的父节点确定命名空间以及创建一个空数组用来存储解析后的节点。之后会有一个while循环判断是否到达了标签的关闭位置如果不是需要关闭的标签则在循环体内对源模版字符串进行分类解析。之后会有一段处理空白字符的逻辑处理完成后返回解析好的nodes数组。 while循环内的逻辑函数的核心 在while中会判断文本数据的类型只有当TextModes为DATA或RCDATA时会继续往下解析。 第一种情况就是判断是否需要解析Vue模版语法中的Mustache语法如果当前上下文中没有v-pre指令来跳过表达式并且源模版字符串是以我们指定的分隔符开头的就会进行双大括号的解析。接下来会判断如果第一个字符是并且第二个字符是! 会尝试解析注释标签!DOCTYPE和!CDATA这三种情况对于DOCTYPE会进行忽略解析成注释。之后会判断当第二个字符是/的情况/已经满足了一个闭合标签的条件了所以会尝试匹配闭合标签。当第三个标签是缺少了标签名字会报错并让解析器的进度前进三个字符跳过/。如果是/并且第三个字符是小写英文字符解析器会解析结束标签。如果源模版字符串的第一个字符是第二个字符是小写英文字符开头会调用parseElement函数来解析对应的标签。当这个判断字符串字符的分支条件结束并且没有解析出任何node节点则会将node作为文本类型调用parseText进行解析。最后将生成的节点添加进nodes数组在函数结束时返回。 while循环的源码如下 while (!isEnd(context, mode, ancestors)) {const s context.sourcelet node: TemplateChildNode | TemplateChildNode[] | undefined undefinedif (mode TextModes.DATA || mode TextModes.RCDATA) {if (!context.inVPre startsWith(s, context.options.delimiters[0])) {/* 如果标签没有 v-pre 指令源模板字符串以双大括号 {{ 开头按双大括号语法解析 */node parseInterpolation(context, mode)} else if (mode TextModes.DATA s[0] ) {// 如果源模板字符串的第以个字符位置是 !if (s[1] !) {// 如果以 !-- 开头按注释解析if (startsWith(s, !--)) {node parseComment(context)} else if (startsWith(s, !DOCTYPE)) {// 如果以 !DOCTYPE 开头忽略 DOCTYPE当做伪注释解析node parseBogusComment(context)} else if (startsWith(s, ![CDATA[)) {// 如果以 ![CDATA[ 开头又在 HTML 环境中解析 CDATAif (ns ! Namespaces.HTML) {node parseCDATA(context, ancestors)}}// 如果源模板字符串的第二个字符位置是 /} else if (s[1] /) {// 如果源模板字符串的第三个字符位置是 那么就是自闭合标签前进三个字符的扫描位置if (s[2] ) {emitError(context, ErrorCodes.MISSING_END_TAG_NAME, 2)advanceBy(context, 3)continue// 如果第三个字符位置是英文字符解析结束标签} else if (/[a-z]/i.test(s[2])) {parseTag(context, TagType.End, parent)continue} else {// 如果不是上述情况则当做伪注释解析node parseBogusComment(context)}// 如果标签的第二个字符是小写英文字符则当做元素标签解析} else if (/[a-z]/i.test(s[1])) {node parseElement(context, ancestors)// 如果第二个字符是 ?当做伪注释解析} else if (s[1] ?) {node parseBogusComment(context)} else {// 都不是这些情况则报出第一个字符不是合法标签字符的错误。emitError(context, ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME, 1)}}}// 如果上述的情况解析完毕后没有创建对应的节点则当做文本来解析if (!node) {node parseText(context, mode)}// 如果节点是数组则遍历添加进 nodes 数组中否则直接添加if (isArray(node)) {for (let i 0; i node.length; i) {pushNode(nodes, node[i])}} else {pushNode(nodes, node)} }4. 解析模版元素 Element parseElement精简源码如下 function parseElement(context: ParserContext,ancestors: ElementNode[] ): ElementNode | undefined {// 解析起始标签const parent last(ancestors)const element parseTag(context, TagType.Start, parent)// 如果是自闭合的标签或者是空标签则直接返回。voidTag例如 img, br, hrif (element.isSelfClosing || context.options.isVoidTag(element.tag)) {return element}// 递归的解析子节点ancestors.push(element)const mode context.options.getTextMode(element, parent)const children parseChildren(context, mode, ancestors)ancestors.pop()element.children children// 解析结束标签if (startsWithEndTagOpen(context.source, element.tag)) {parseTag(context, TagType.End, parent)} else {emitError(context, ErrorCodes.X_MISSING_END_TAG, 0, element.loc.start)if (context.source.length 0 element.tag.toLowerCase() script) {const first children[0]if (first startsWith(first.loc.source, !--)) {emitError(context, ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT)}}}// 获取标签位置对象element.loc getSelection(context, element.loc.start)return element }首先会获取当前节点的父节点再调用parseTag()函数解析。 parseTag()函数执行流程 匹配标签名解析元素中的attribute属性存储至props属性检测是否存在v-pre属性如果存在则修改context上下文中的inVPre属性为true。检测自闭合标签如果是自闭合则将isSelfClosing属性置为true。判断tagType是Element还是component组件或slot插槽。返回生成的element对象 获取到 element对象后会判断element是否是自闭合标签或空标签例如img、br、hr如果是这种情况直接返回element对象。然后解析element的子节点把element压入栈中然后递归调用parseChildren来解析子节点。 const parent last(ancestors) 在将element入栈后拿到的父节点就是当前节点。 解析完毕后调用ancestors.pop()让当前解析完子节点的element对象出栈将解析后的children对象赋值给element的children属性完成element的子节点解析。最后匹配结束标签设置element的Ioc位置信息返回解析完毕的 element 对象。 模版元素解析-举例分析 divpHello World/p /div
http://www.zqtcl.cn/news/244756/

相关文章:

  • 门户网站的设计常见的管理信息系统有哪些
  • 网站添加悬浮二维码成都游戏网站开发
  • 用jquery做网站百度seo排名规则
  • 免备案手机网站室内设计说明
  • 网站被做站公司贩卖怎样将qq空间建设为个人网站
  • 网站开发有哪几类淮安app开发公司
  • 营销网站建设公司哪家好兵团第二师建设环保局网站
  • 做推广最好的网站是哪个深圳办公室装修招标
  • 郑州高端网站制作wordpress那个版本好
  • wordpress屏蔽右键f12奉化首页的关键词优化
  • cn域名做犯法网站做电影网站需要哪些证
  • 官方网站有哪些韶关做网站的公司
  • 商城网站设计公司怎么样网站制作预算
  • 在济南什么人想做网站网站建设后怎么做主页
  • 联合年检怎么做网站上国家备案查询
  • 社交网站wap模板wordpress网址导航插件
  • 沈阳快速建站公司有哪些国外做二手服装网站
  • 手机如何建立网站平台seo比较好的优化
  • 电商网站建设外包禅城南庄网站制作
  • 哈尔滨企业网站开发报价免费php网站源码
  • 东莞市公司网站建设淄博网站制作营销
  • 企业网站无线端怎么做手机网站做成app
  • 让他人建设网站需要提供的材料可在哪些网站做链接
  • 外贸公司做网站3d建模好学吗
  • dedecms新网站 上传到万网的空间上海新媒体运营公司排名
  • 包装东莞网站建设0769三层网络架构
  • 淘客网站自己做固安建站公司
  • 咸阳学校网站建设联系电话网络app开发网站建设价格
  • 没网站怎么做淘宝客网站建设耂首先金手指
  • 网站带做收录排名淘外网站怎么做