2
0

render.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import createElement from '../vdom/create-element'
  2. import { flatten } from '../vdom/helpers'
  3. import { bind, isArray, isObject, renderString } from 'shared/util'
  4. export const renderState = {
  5. activeInstance: null
  6. }
  7. export function initRender (vm) {
  8. vm._vnode = null
  9. vm._mounted = false
  10. vm._staticTrees = null
  11. vm.$slots = {}
  12. // bind the public createElement fn to this instance
  13. // so that we get proper render context inside it.
  14. vm.$createElement = bind(createElement, vm)
  15. if (vm.$options.el) {
  16. vm.$mount(vm.$options.el)
  17. }
  18. }
  19. export function renderMixin (Vue) {
  20. Vue.prototype._render = function () {
  21. const prev = renderState.activeInstance
  22. renderState.activeInstance = this
  23. const { render, _renderChildren } = this.$options
  24. // resolve slots. becaues slots are rendered in parent scope,
  25. // we set the activeInstance to parent.
  26. if (_renderChildren) {
  27. resolveSlots(this, _renderChildren)
  28. }
  29. // render self
  30. const vnode = render.call(this._renderProxy)
  31. // restore render state
  32. renderState.activeInstance = prev
  33. return vnode
  34. }
  35. // shorthands used in render functions
  36. Vue.prototype.__h__ = createElement
  37. // toString for mustaches
  38. Vue.prototype.__toString__ = renderString
  39. // render v-for
  40. Vue.prototype.__renderList__ = function (val, render) {
  41. let ret, i, l, keys, key
  42. if (isArray(val)) {
  43. ret = new Array(val.length)
  44. for (i = 0, l = val.length; i < l; i++) {
  45. ret[i] = render(val[i], i, i)
  46. }
  47. } else if (typeof val === 'number') {
  48. ret = new Array(val)
  49. for (i = 0; i < val; i++) {
  50. ret[i] = render(i + 1, i, i)
  51. }
  52. } else if (isObject(val)) {
  53. keys = Object.keys(val)
  54. ret = new Array(keys.length)
  55. for (i = 0, l = keys.length; i < l; i++) {
  56. key = keys[i]
  57. ret[i] = render(val[key], i, key)
  58. }
  59. }
  60. return ret
  61. }
  62. // register ref
  63. Vue.prototype.__registerRef__ = function (key, ref, vFor, remove) {
  64. const refs = this.$refs
  65. if (remove) {
  66. if (vFor) {
  67. remove(refs[key], ref)
  68. } else {
  69. refs[key] = undefined
  70. }
  71. } else {
  72. if (vFor) {
  73. if (refs[key]) {
  74. refs[key].push(ref)
  75. } else {
  76. refs[key] = [ref]
  77. }
  78. } else {
  79. refs[key] = ref
  80. }
  81. }
  82. }
  83. }
  84. function resolveSlots (vm, children) {
  85. if (children) {
  86. children = flatten(isArray(children) ? children : children())
  87. const slots = { default: children }
  88. let i = children.length
  89. let name, child
  90. while (i--) {
  91. child = children[i]
  92. if ((name = child.data && child.data.slot)) {
  93. let slot = (slots[name] || (slots[name] = []))
  94. if (child.tag === 'template') {
  95. slot.push.apply(slot, child.children)
  96. } else {
  97. slot.push(child)
  98. }
  99. children.splice(i, 1)
  100. }
  101. }
  102. vm.$slots = slots
  103. }
  104. }