博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue.js 源代码学习笔记 ----- codegen.js
阅读量:4331 次
发布时间:2019-06-06

本文共 8666 字,大约阅读时间需要 28 分钟。

/* @flow */import { genHandlers } from './events'import { baseWarn, pluckModuleFunction } from '../helpers'import baseDirectives from '../directives/index'import { camelize } from 'shared/util'// configurable statelet warnlet transformslet dataGenFnslet platformDirectiveslet staticRenderFnslet onceCountlet currentOptionsexport function generate (  ast: ASTElement | void,  options: CompilerOptions): {  render: string,  staticRenderFns: Array
} { // save previous staticRenderFns so generate calls can be nested const prevStaticRenderFns: Array
= staticRenderFns const currentStaticRenderFns: Array
= staticRenderFns = [] const prevOnceCount = onceCount onceCount = 0 currentOptions = options warn = options.warn || baseWarn transforms = pluckModuleFunction(options.modules, 'transformCode') dataGenFns = pluckModuleFunction(options.modules, 'genData') platformDirectives = options.directives || {} const code = ast ? genElement(ast) : '_h("div")' staticRenderFns = prevStaticRenderFns onceCount = prevOnceCount return { render: `with(this){
return ${code}}`, staticRenderFns: currentStaticRenderFns }}function genElement (el: ASTElement): string { if (el.staticRoot && !el.staticProcessed) { return genStatic(el) } else if (el.once && !el.onceProcessed) { return genOnce(el) } else if (el.for && !el.forProcessed) { return genFor(el) } else if (el.if && !el.ifProcessed) { return genIf(el) } else if (el.tag === 'template' && !el.slotTarget) { return genChildren(el) || 'void 0' } else if (el.tag === 'slot') { return genSlot(el) } else { // component or element let code if (el.component) { code = genComponent(el.component, el) } else { const data = el.plain ? undefined : genData(el) const children = el.inlineTemplate ? null : genChildren(el) code = `_h('${el.tag}'${ data ? `,${data}` : '' // data }${ children ? `,${children}` : '' // children })` } // module transforms for (let i = 0; i < transforms.length; i++) { code = transforms[i](el, code) } return code }}// hoist static sub-trees outfunction genStatic (el: ASTElement): string { el.staticProcessed = true staticRenderFns.push(`with(this){
return ${genElement(el)}}`) return `_m(${staticRenderFns.length - 1}${el.staticInFor ? ',true' : ''})`}// v-oncefunction genOnce (el: ASTElement): string { el.onceProcessed = true if (el.if && !el.ifProcessed) { return genIf(el) } else if (el.staticInFor) { let key = '' let parent = el.parent while (parent) { if (parent.for) { key = parent.key break } parent = parent.parent } if (!key) { process.env.NODE_ENV !== 'production' && warn( `v-once can only be used inside v-for that is keyed. ` ) return genElement(el) } return `_o(${genElement(el)},${onceCount++}${key ? `,${key}` : ``})` } else { return genStatic(el) }}function genIf (el: any): string { el.ifProcessed = true // avoid recursion return genIfConditions(el.conditions)}function genIfConditions (conditions: ASTIfConditions): string { if (!conditions.length) { return '_e()' } var condition = conditions.shift() if (condition.exp) { return `(${condition.exp})?${genTernaryExp(condition.block)}:${genIfConditions(conditions)}` } else { return `${genTernaryExp(condition.block)}` } // v-if with v-once shuold generate code like (a)?_m(0):_m(1) function genTernaryExp (el) { return el.once ? genOnce(el) : genElement(el) }}function genFor (el: any): string { const exp = el.for const alias = el.alias const iterator1 = el.iterator1 ? `,${el.iterator1}` : '' const iterator2 = el.iterator2 ? `,${el.iterator2}` : '' el.forProcessed = true // avoid recursion return `_l((${exp}),` + `function(${alias}${iterator1}${iterator2}){` + `return ${genElement(el)}` + '})'}function genData (el: ASTElement): string { let data = '{' // directives first. // directives may mutate the el's other properties before they are generated. const dirs = genDirectives(el) if (dirs) data += dirs + ',' // key if (el.key) { data += `key:${el.key},` } // ref if (el.ref) { data += `ref:${el.ref},` } if (el.refInFor) { data += `refInFor:true,` } // record original tag name for components using "is" attribute if (el.component) { data += `tag:"${el.tag}",` } // module data generation functions for (let i = 0; i < dataGenFns.length; i++) { data += dataGenFns[i](el) } // attributes if (el.attrs) { data += `attrs:{${genProps(el.attrs)}},` } // DOM props if (el.props) { data += `domProps:{${genProps(el.props)}},` } // event handlers if (el.events) { data += `${genHandlers(el.events)},` } if (el.nativeEvents) { data += `${genHandlers(el.nativeEvents, true)},` } // slot target if (el.slotTarget) { data += `slot:${el.slotTarget},` } // scoped slots if (el.scopedSlots) { data += `${genScopedSlots(el.scopedSlots)},` } // inline-template if (el.inlineTemplate) { const inlineTemplate = genInlineTemplate(el) if (inlineTemplate) { data += `${inlineTemplate},` } } data = data.replace(/,$/, '') + '}' // v-bind data wrap if (el.wrapData) { data = el.wrapData(data) } return data}function genDirectives (el: ASTElement): string | void { const dirs = el.directives if (!dirs) return let res = 'directives:[' let hasRuntime = false let i, l, dir, needRuntime for (i = 0, l = dirs.length; i < l; i++) { dir = dirs[i] needRuntime = true const gen = platformDirectives[dir.name] || baseDirectives[dir.name] if (gen) { // compile-time directive that manipulates AST. // returns true if it also needs a runtime counterpart. needRuntime = !!gen(el, dir, warn) } if (needRuntime) { hasRuntime = true res += `{name:"${dir.name}",rawName:"${dir.rawName}"${ dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : '' }${ dir.arg ? `,arg:"${dir.arg}"` : '' }${ dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : '' }},` } } if (hasRuntime) { return res.slice(0, -1) + ']' }}function genInlineTemplate (el: ASTElement): ?string { const ast = el.children[0] if (process.env.NODE_ENV !== 'production' && ( el.children.length > 1 || ast.type !== 1 )) { warn('Inline-template components must have exactly one child element.') } if (ast.type === 1) { const inlineRenderFns = generate(ast, currentOptions) return `inlineTemplate:{render:function(){${ inlineRenderFns.render }},staticRenderFns:[${ inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',') }]}` }}function genScopedSlots (slots) { return `scopedSlots:{${ Object.keys(slots).map(key => genScopedSlot(key, slots[key])).join(',') }}`}function genScopedSlot (key: string, el: ASTElement) { return `${key}:function(${String(el.attrsMap.scope)}){` + `return ${el.tag === 'template' ? genChildren(el) || 'void 0' : genElement(el) }}`}function genChildren (el: ASTElement): string | void { if (el.children.length) { return '[' + el.children.map(genNode).join(',') + ']' }}function genNode (node: ASTNode) { if (node.type === 1) { return genElement(node) } else { return genText(node) }}function genText (text: ASTText | ASTExpression): string { return text.type === 2 ? text.expression // no need for () because already wrapped in _s() : transformSpecialNewlines(JSON.stringify(text.text))}function genSlot (el: ASTElement): string { const slotName = el.slotName || '"default"' const children = genChildren(el) return `_t(${slotName}${ children ? `,${children}` : '' }${ el.attrs ? `${children ? '' : ',null'},{${ el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',') }}` : '' })`}// componentName is el.component, take it as argument to shun flow's pessimistic refinementfunction genComponent (componentName, el): string { const children = el.inlineTemplate ? null : genChildren(el) return `_h(${componentName},${genData(el)}${ children ? `,${children}` : '' })`}function genProps (props: Array<{ name: string, value: string }>): string { let res = '' for (let i = 0; i < props.length; i++) { const prop = props[i] res += `"${prop.name}":${transformSpecialNewlines(prop.value)},` } return res.slice(0, -1)}// #3895, #4268function transformSpecialNewlines (text: string): string { return text .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029')}

 

转载于:https://www.cnblogs.com/dhsz/p/7245879.html

你可能感兴趣的文章
调用一个类中私有或受保护的方法或属性
查看>>
ASCII码
查看>>
mac上安装mysql
查看>>
Solr(搜索引擎)简单介绍(不一定要会用但是要知道)
查看>>
(1)LPC2106 基本信息、ISP、JTAG、时钟计算.
查看>>
5.对话框处理与登录测试
查看>>
与芝麻信用等业务展开合作
查看>>
如何使用SecureCRT让Vim有颜色?
查看>>
GitHub账号
查看>>
我要过四级
查看>>
动态改变对话框的位置和大小
查看>>
div绝对定位针对手机浏览器的区别
查看>>
sql
查看>>
How to intall and configure Haproxy on Centos
查看>>
poj 2311 Cutting Game 博弈论
查看>>
Python3中的SocketServer
查看>>
Web.config配置configSections学习
查看>>
复合数据类型,英文词频统计
查看>>
【leetcode】Remove Duplicates from Sorted Array II
查看>>
java中面向对象的理解
查看>>