'f'
mh-two-thousand-and-two
2024-04-12 26f2711ef9461961fb953e2b497bd314ef95e345
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function initRelationHandlers (type, handler, target, ctx) {
  if (!handler) {
    return
  }
  const name = `_$${type}Handlers`;
  (ctx[name] || (ctx[name] = [])).push(function () {
    handler.call(ctx, target)
  })
}
 
function initLinkedHandlers (relation, target, ctx) {
  const type = 'linked'
  const name = relation.name
  const relationNodes = ctx._$relationNodes || (ctx._$relationNodes = Object.create(null));
  (relationNodes[name] || (relationNodes[name] = [])).push(target)
  initRelationHandlers(type, relation[type], target, ctx)
}
 
function initUnlinkedHandlers (relation, target, ctx) {
  const type = 'unlinked'
  initRelationHandlers(type, relation[type], target, ctx)
}
 
function findParentRelation (parentVm, target, type) {
  const relations = parentVm &&
    parentVm.$options.mpOptions &&
    parentVm.$options.mpOptions.relations
 
  if (!relations) {
    return []
  }
  const name = Object.keys(relations).find(name => {
    const relation = relations[name]
    return relation.target === target && relation.type === type
  })
  if (!name) {
    return []
  }
  return [relations[name], parentVm]
}
 
function initParentRelation (vm, childRelation, match) {
  const [parentRelation, parentVm] = match(vm, vm.$options.mpOptions.path)
  if (!parentRelation) {
    return
  }
 
  initLinkedHandlers(parentRelation, vm, parentVm)
  initLinkedHandlers(childRelation, parentVm, vm)
 
  initUnlinkedHandlers(parentRelation, vm, parentVm)
  initUnlinkedHandlers(childRelation, parentVm, vm)
}
 
function initRelation (relation, vm) {
  const type = relation.type
  if (type === 'parent') {
    initParentRelation(vm, relation, function matchParent (vm, target) {
      return findParentRelation(vm.$parent, target, 'child')
    })
  } else if (type === 'ancestor') {
    initParentRelation(vm, relation, function matchAncestor (vm, target) {
      let $parent = vm.$parent
      while ($parent) {
        const ret = findParentRelation($parent, target, 'descendant')
        if (ret.length) {
          return ret
        }
        $parent = $parent.$parent
      }
      return []
    })
  }
}
 
export function initRelations (vm) {
  const {
    relations
  } = vm.$options.mpOptions || {}
  if (!relations) {
    return
  }
  Object.keys(relations).forEach(name => {
    initRelation(relations[name], vm)
  })
}
 
export function handleRelations (vm, type) {
  // TODO 需要移除 relationNodes
  const handlers = vm[`_$${type}Handlers`]
  if (!handlers) {
    return
  }
  handlers.forEach(handler => handler())
}