helpers.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* @flow */
  2. import { isPrimitive } from '../util/index'
  3. import VNode from './vnode'
  4. export function normalizeChildren (
  5. children: any,
  6. ns: string | void
  7. ): Array<VNode> | void {
  8. // invoke children thunks.
  9. // components always receive their children as thunks so that they
  10. // can perform the actual render inside their own dependency collection cycle.
  11. if (typeof children === 'function') {
  12. children = children()
  13. }
  14. if (isPrimitive(children)) {
  15. return [createTextVNode(children)]
  16. }
  17. if (Array.isArray(children)) {
  18. const res = []
  19. for (let i = 0, l = children.length; i < l; i++) {
  20. const c = children[i]
  21. const last = res[res.length - 1]
  22. // nested
  23. if (Array.isArray(c)) {
  24. res.push.apply(res, normalizeChildren(c))
  25. } else if (isPrimitive(c)) {
  26. if (last && last.text) {
  27. last.text += String(c)
  28. } else {
  29. // convert primitive to vnode
  30. res.push(createTextVNode(c))
  31. }
  32. } else if (c instanceof VNode) {
  33. if (c.text && last && last.text) {
  34. last.text += c.text
  35. } else {
  36. // inherit parent namespace
  37. if (ns) {
  38. applyNS(c, ns)
  39. }
  40. res.push(c)
  41. }
  42. }
  43. }
  44. return res
  45. }
  46. }
  47. function createTextVNode (val) {
  48. return new VNode(undefined, undefined, undefined, String(val))
  49. }
  50. function applyNS (vnode, ns) {
  51. if (vnode.tag && !vnode.ns) {
  52. vnode.ns = ns
  53. if (vnode.children) {
  54. for (let i = 0, l = vnode.children.length; i < l; i++) {
  55. applyNS(vnode.children[i], ns)
  56. }
  57. }
  58. }
  59. }
  60. export function updateListeners (
  61. on: Object,
  62. oldOn: Object,
  63. add: Function,
  64. remove: Function
  65. ) {
  66. let name, cur, old, fn, event, capture
  67. for (name in on) {
  68. cur = on[name]
  69. old = oldOn[name]
  70. if (!old) {
  71. capture = name.charAt(0) === '!'
  72. event = capture ? name.slice(1) : name
  73. if (Array.isArray(cur)) {
  74. add(event, (cur.invoker = arrInvoker(cur)), capture)
  75. } else {
  76. fn = cur
  77. cur = on[name] = {}
  78. cur.fn = fn
  79. add(event, (cur.invoker = fnInvoker(cur)), capture)
  80. }
  81. } else if (Array.isArray(old)) {
  82. old.length = cur.length
  83. for (let i = 0; i < old.length; i++) old[i] = cur[i]
  84. on[name] = old
  85. } else {
  86. old.fn = cur
  87. on[name] = old
  88. }
  89. }
  90. for (name in oldOn) {
  91. if (!on[name]) {
  92. event = name.charAt(0) === '!' ? name.slice(1) : name
  93. remove(event, oldOn[name].invoker)
  94. }
  95. }
  96. }
  97. function arrInvoker (arr: Array<Function>): Function {
  98. return function (ev) {
  99. const single = arguments.length === 1
  100. for (let i = 0; i < arr.length; i++) {
  101. single ? arr[i](ev) : arr[i].apply(null, arguments)
  102. }
  103. }
  104. }
  105. function fnInvoker (o: { fn: Function }): Function {
  106. return function (ev) {
  107. const single = arguments.length === 1
  108. single ? o.fn(ev) : o.fn.apply(null, arguments)
  109. }
  110. }