resolve-slots.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /* @flow */
  2. import type VNode from 'core/vdom/vnode'
  3. /**
  4. * Runtime helper for resolving raw children VNodes into a slot object.
  5. */
  6. export function resolveSlots (
  7. children: ?Array<VNode>,
  8. context: ?Component
  9. ): { [key: string]: Array<VNode> } {
  10. if (!children || !children.length) {
  11. return {}
  12. }
  13. const slots = {}
  14. for (let i = 0, l = children.length; i < l; i++) {
  15. const child = children[i]
  16. const data = child.data
  17. // remove slot attribute if the node is resolved as a Vue slot node
  18. if (data && data.attrs && data.attrs.slot) {
  19. delete data.attrs.slot
  20. }
  21. // named slots should only be respected if the vnode was rendered in the
  22. // same context.
  23. if ((child.context === context || child.fnContext === context) &&
  24. data && data.slot != null
  25. ) {
  26. const name = data.slot
  27. const slot = (slots[name] || (slots[name] = []))
  28. if (child.tag === 'template') {
  29. slot.push.apply(slot, child.children || [])
  30. } else {
  31. slot.push(child)
  32. }
  33. } else {
  34. (slots.default || (slots.default = [])).push(child)
  35. }
  36. }
  37. // ignore slots that contains only whitespace
  38. for (const name in slots) {
  39. if (slots[name].every(isWhitespace)) {
  40. delete slots[name]
  41. }
  42. }
  43. return slots
  44. }
  45. function isWhitespace (node: VNode): boolean {
  46. return (node.isComment && !node.asyncFactory) || node.text === ' '
  47. }
  48. export function resolveScopedSlots (
  49. fns: ScopedSlotsData, // see flow/vnode
  50. hasDynamicKeys?: boolean,
  51. res?: Object
  52. ): { [key: string]: Function, $stable: boolean } {
  53. res = res || { $stable: !hasDynamicKeys }
  54. for (let i = 0; i < fns.length; i++) {
  55. const slot = fns[i]
  56. if (Array.isArray(slot)) {
  57. resolveScopedSlots(slot, hasDynamicKeys, res)
  58. } else if (slot) {
  59. res[slot.key] = slot.fn
  60. }
  61. }
  62. return res
  63. }