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()) }