bd商务合作网站系统源码分享 商务bd怎么开展业务

今天给各位分享bd商务合作网站系统源码分享的知识,其中也会对商务bd怎么开展业务进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

vue中有这样一张响应式系统的流程图,vue会将模板语法编译成render函数,通过render函数渲染生成Virtualdom,但是官方并没有对模板编译有详细的介绍,这篇文章带大家一起学习下vue的模板编译。

为了更好理解vue的模板编译这里我整理了一份模板编译的整体流程,如下所示,下面将用源码解读的方式来找到模板编译中的几个核心步骤,进行详细说明:

1、起步

这里我使用webpack来打包vue文件,来分析vue在模板编译中的具体流程,如下所示,下面是搭建的项目结构和文件内容:

项目结构

├─package-lock.json\n├─package.json\n├─src\n|├─App.vue\n|└index.js\n├─dist\n|└main.js\n├─config\n|└webpack.config.js\n

App.vue

<template>\n<divid=&34;>\n{{count}}\n</div>\n</template>\n\n<script>\nexportdefault{\nprops:{},\ndata(){\nreturn{\ncount:0\n}\n}\n}\n</script>\n\n<stylescoped>\n39;vue-loader&39;development&39;vue-loader&39;babel-loader&39;vue-style-loader&39;css-loader&34;./src/App.vue&34;default&34;./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true&&34;./src/App.vue?vue&type=script&lang=js&&34;./node_modules/vue-loader/lib/runtime/componentNormalizer.js&34;default&34;default&34;7ba5bd90&39;<template>\\n&39;<divid=&34;>\\n&39;{{count}}\\n&39;</div>\\n&39;</template>\\n&39;\\n&39;<script>\\n&39;exportdefault{\\n&39;props:{},\\n&39;data(){\\n&39;return{\\n&39;count:0\\n&39;}\\n&39;}\\n&39;}\\n&39;</script>\\n&39;\\n&39;<style>\\n&39;39;+\n&39;+\n&39;+\n&39;,\nfilename:&39;,\ntemplate:{\ntype:&39;,\ncontent:&34;box&39;,\nstart:10,\nend:53,\nattrs:{}\n},\nscript:{\ntype:&39;,\ncontent:&39;+\n&39;+\n&39;+\n&39;+\n&39;+\n&39;+\n&39;+\n&39;+\n&39;,\nstart:74,\nend:156,\nattrs:{}\n},\n….\n}\n

template-loader

template-loader的作用是将import{render,staticRenderFns}from&34;模块编译成render函数并导出,以下是编译产物:

//编译前\n<divid=&34;>\n{{count}}\n</div>\n\n//编译后\nvarrender=functionrender(){\nvar_vm=this,\n_c=_vm._self._c\nreturn_c(&34;,{attrs:{id:&34;}},[\n_vm._v(&34;+_vm._s(_vm.count)+&34;),\n])\n}\nvarstaticRenderFns=[]\nrender._withStripped=true\n\nexport{render,staticRenderFns}\n

template-loader核心原理是通过vue/compiler-sfc将模板转换成为render函数,并返回template编译产物

module.exports=function(source){\nconstloaderContext=this\n…\n//接收模板编译核心库\nconst{compiler,templateCompiler}=resolveCompiler(ctx,loaderContext)\n\n…\n\n//开启编译\nconstcompiled=compiler.compileTemplate(finalOptions)\n\n…\n\n//编译后产出,code就是render函数\nconst{code}=compiled\n\n//导出template模块\nreturncode+`\\nexport{render,staticRenderFns}`\n}\n

2、模板编译流程

vue/compiler-sfc是模板编译的核心库,在vue2.7版本中使用,而vue2.7以下的版本都是使用vue-template-compiler,本质两个包的功能是一样的,都可以将模板语法编译为JavaScript,接下来我们来解析一下在模板编译过程中使用的方法:

parseHTML阶段

可以将vue文件中的模板语法转义为AST,为后续创建dom结构做预处理

exportfunctionparseHTML(html,options:HTMLParserOptions){\n//存储解析后的标签\nconststack:any[]=[]\nconstexpectHTML=options.expectHTML\nconstisUnaryTag=options.isUnaryTag||no\nconstcanBeLeftOpenTag=options.canBeLeftOpenTag||no\nletindex=0\nletlast,lastTag\n//循环html字符串结构\nwhile(html){\n//记录当前最新html\nlast=html\nif(!lastTag||!isPlainTextElement(lastTag)){\n//获取以<为开始的位置\nlettextEnd=html.indexOf(&39;)\nif(textEnd===0){\n//解析注释\nif(comment.test(html)){\nconstcommentEnd=html.indexOf(&39;)\n\nif(commentEnd>=0){\nif(options.shouldKeepComment&&options.comment){\noptions.comment(\nhtml.substring(4,commentEnd),\nindex,\nindex+commentEnd+3\n)\n}\nadvance(commentEnd+3)\ncontinue\n}\n}\n\n//解析条件注释\nif(conditionalComment.test(html)){\nconstconditionalEnd=html.indexOf(&39;)\n\nif(conditionalEnd>=0){\nadvance(conditionalEnd+2)\ncontinue\n}\n}\n\n//解析Doctype\nconstdoctypeMatch=html.match(doctype)\nif(doctypeMatch){\nadvance(doctypeMatch[0].length)\ncontinue\n}\n\n//解析截取结束标签\nconstendTagMatch=html.match(endTag)\nif(endTagMatch){\nconstcurIndex=index\nadvance(endTagMatch[0].length)\nparseEndTag(endTagMatch[1],curIndex,index)\ncontinue\n}\n\n//解析截取开始标签\nconststartTagMatch=parseStartTag()\nif(startTagMatch){\nhandleStartTag(startTagMatch)\nif(shouldIgnoreFirstNewline(startTagMatch.tagName,html)){\nadvance(1)\n}\ncontinue\n}\n}\n\nlettext,rest,next\nif(textEnd>=0){\nrest=html.slice(textEnd)\nwhile(\n!endTag.test(rest)&&\n!startTagOpen.test(rest)&&\n!comment.test(rest)&&\n!conditionalComment.test(rest)\n){\n//<inplaintext,beforgivingandtreatitastext\nnext=rest.indexOf(&39;,1)\nif(next<0)break\ntextEnd+=next\nrest=html.slice(textEnd)\n}\ntext=html.substring(0,textEnd)\n}\n\n//纯文本节点\nif(textEnd<0){\ntext=html\n}\n\n//截取文本节点\nif(text){\nadvance(text.length)\n}\n\nif(options.chars&&text){\noptions.chars(text,index-text.length,index)\n}\n}else{\nletendTagLength=0\nconststackedTag=lastTag.toLowerCase()\nconstreStackedTag=\nreCache[stackedTag]||\n(reCache[stackedTag]=newRegExp(\n&39;+stackedTag+&39;,\n&39;\n))\nconstrest=html.replace(reStackedTag,function(all,text,endTag){\nendTagLength=endTag.length\nif(!isPlainTextElement(stackedTag)&&stackedTag!==&39;){\ntext=text\n.replace(/<!\\–([\\s\\S]*?)–>/g,&39;)//39;$1&39;&39;p&39;&39;a&39;href&39;br&39;p&39;template&39;void0&39;slot&39;\\n&39;<divid=&34;>\\n&39;{{count}}\\n&39;<button@add=&34;>+</button>\\n&39;</div>\\n&34;div&34;box&34;\\n&34;\\n&34;button&34;+”)]),\n])\n}\nvarstaticRenderFns=[]\nrender._withStripped=true\n

compilerToFunction阶段

将genElement阶段编译的字符串产物,通过newFunction将code转为函数

exportfunctioncreateCompileToFunctionFn(compile:Function):Function{\nconstcache=Object.create(null)\nreturnfunctioncompileToFunctions(\ntemplate:string,\noptions?:CompilerOptions,\nvm?:Component\n):CompiledFunctionResult{\n…\n//编译\nconstcompiled=compile(template,options)\n\n//将genElement阶段的产物转化为function\nfunctioncreateFunction(code,errors){\ntry{\nreturnnewFunction(code)\n}catch(err:any){\nerrors.push({err,code})\nreturnnoop\n}\n}\n\nconstres:any={}\nconstfnGenErrors:any[]=[]\n//将code转化为function\nres.render=createFunction(compiled.render,fnGenErrors)\nres.staticRenderFns=compiled.staticRenderFns.map(code=>{\nreturncreateFunction(code,fnGenErrors)\n})\n…\n}\n}\n

为了方便理解,使用断点调试,来看一下compileTemplate都经历了哪些操作:

首先会判断是否需要预处理,如果需要预处理,则会对template模板进行预处理并返回处理结果,此处跳过预处理,直接进入actuallCompile函数

这里可以看到本身内部还有一层编译函数对template进行编译,这才是最核心的编译方法,而这个compile方法来源于createCompilerCreator

createCompilerCreator返回了两层函数,最终返回值则是compile和compileToFunction,这两个是将template转为render函数的关键,可以看到template会被解析成AST树,最后通过generate方法转义成函数code,接下来我们看一下parse函数中是如何将template转为AST的。

继续向下debug后,会走到parseHTML函数,这个函数是模板编译中用来解析HTML结构的核心方法,通过回调+递归最终遍历整个HTML结构并将其转化为AST树。

parseHTML阶段

使用parseHTML解析成的AST创建render函数和Vdom

genElement阶段

将AST结构解析成为虚拟dom树

最终编译输出为render函数,得到最终打包构建的产物。

3、总结

到此我们应该了解了vue是如何打包构建将模板编译为渲染函数的,有了渲染函数后,只需要将渲染函数的this指向组件实例,即可和组件的响应式数据绑定。vue的每一个组件都会对应一个渲染Watcher,他的本质作用是把响应式数据作为依赖收集,当响应式数据发生变化时,会触发setter执行响应式依赖通知渲染Watcher重新执行render函数做到页面数据的更新。

参考文献

vue2官方文档(https://v2.cn.vuejs.org/)

作者:存远

来源:微信公众号:政采云技术

出处:https://mp.weixin.qq.com/s/NNClYB4swf1cDw0xm6E3sw

bd商务合作网站系统源码分享的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于商务bd怎么开展业务、bd商务合作网站系统源码分享的信息别忘了在本站进行查找哦。

站内搜索