index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { genHandlers } from './events'
  2. import { genDirectives } from './directives/index'
  3. import { isReservedTag } from '../../runtime/util/dom'
  4. export function generate (ast) {
  5. const code = ast ? genElement(ast) : '__h__("div")'
  6. return `with (this) { return ${code}}`
  7. }
  8. function genElement (el) {
  9. if (el.for) {
  10. return genFor(el)
  11. } else if (el.if) {
  12. return genIf(el)
  13. } else if (el.tag === 'template' && !el.attrsMap.slot) {
  14. return genChildren(el)
  15. } else if (el.tag === 'render') {
  16. return genRender(el)
  17. } else if (el.tag === 'slot') {
  18. return genSlot(el)
  19. } else {
  20. // if the element is potentially a component,
  21. // wrap its children as a thunk.
  22. const children = genChildren(el, !isReservedTag(el.tag))
  23. return `__h__('${el.tag}', ${genData(el)}, ${children})`
  24. }
  25. }
  26. function genIf (el) {
  27. const exp = el.if
  28. el.if = false // avoid recursion
  29. return `(${exp}) ? ${genElement(el)} : ${genElse(el)}`
  30. }
  31. function genElse (el) {
  32. return el.elseBlock
  33. ? genElement(el.elseBlock)
  34. : 'null'
  35. }
  36. function genFor (el) {
  37. const exp = el.for
  38. const alias = el.alias
  39. el.for = false // avoid recursion
  40. return `(${exp})&&(${exp}).map(function(${alias},$index) {return ${genElement(el)}})`
  41. }
  42. function genData (el) {
  43. if (el.plain) {
  44. return el.svg ? '{svg:true}' : '{}'
  45. }
  46. let data = '{'
  47. // directives first.
  48. // directives may mutate the el's other properties before they are generated.
  49. if (el.directives) {
  50. let dirs = genDirectives(el)
  51. if (dirs) data += dirs + ','
  52. }
  53. // svg
  54. if (el.svg) {
  55. data += 'svg:true,'
  56. }
  57. // key
  58. if (el.key) {
  59. data += `key:${el.key},`
  60. }
  61. // ref
  62. if (el.ref) {
  63. data += `ref:"${el.ref}",`
  64. }
  65. // slot names
  66. if (el.attrsMap.slot) {
  67. data += `slot:"${el.attrsMap.slot}",`
  68. }
  69. // class
  70. if (el.staticClass) {
  71. data += `staticClass:"${el.staticClass}",`
  72. }
  73. if (el.classBinding) {
  74. data += `class:${el.classBinding},`
  75. }
  76. // style
  77. if (el.styleBinding) {
  78. data += `style:${el.styleBinding},`
  79. }
  80. // props
  81. if (el.props) {
  82. data += `props:{${genProps(el.props)}},`
  83. }
  84. // attributes
  85. if (el.attrs) {
  86. data += `attrs:{${genProps(el.attrs)}}`
  87. }
  88. // hooks
  89. if (el.hooks) {
  90. data += `hook:{${genHooks(el.hooks)}},`
  91. }
  92. // event handlers
  93. if (el.events) {
  94. data += genHandlers(el.events)
  95. }
  96. return data.replace(/,$/, '') + '}'
  97. }
  98. function genChildren (el, asThunk) {
  99. if (!el.children.length) {
  100. return 'undefined'
  101. }
  102. const code = '[' + el.children.map(genNode).join(',') + ']'
  103. return asThunk
  104. ? `_renderWithContext(function(){return ${code}})`
  105. : code
  106. }
  107. function genNode (node) {
  108. if (node.tag) {
  109. return genElement(node)
  110. } else {
  111. return genText(node)
  112. }
  113. }
  114. function genText (text) {
  115. return text.expression
  116. ? `(${text.expression})`
  117. : JSON.stringify(text.text)
  118. }
  119. function genRender (el) {
  120. return `${el.method}(${el.args || 'null'},${genChildren(el)})`
  121. }
  122. function genSlot (el) {
  123. const name = el.name
  124. ? `"${el.name}"`
  125. : (el.dynamicName || '"default"')
  126. return `($slots[${name}] || ${genChildren(el)})`
  127. }
  128. function genProps (props) {
  129. let res = ''
  130. for (let i = 0; i < props.length; i++) {
  131. let prop = props[i]
  132. res += `"${prop.name}":${prop.value},`
  133. }
  134. return res.slice(0, -1)
  135. }
  136. function genHooks (hooks) {
  137. let res = ''
  138. for (let key in hooks) {
  139. res += `"${key}":${hooks[key]},`
  140. }
  141. return res.slice(0, -1)
  142. }