Blame view

node_modules/portal-vue/src/components/portal.tsx 2.51 KB
4cd4fd28   郭伟龙   feat: 初始化项目
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
96
97
98
99
100
101
102
103
104
105
106
import Vue from 'vue'
import { VNode } from 'vue'
import { TransportInput, TransportVector } from '../types'
import { wormhole } from './wormhole'

let _id = 1

export default Vue.extend({
  name: 'portal',
  props: {
    disabled: { type: Boolean },
    name: { type: String, default: () => String(_id++) },
    order: { type: Number, default: 0 },
    slim: { type: Boolean },
    slotProps: { type: Object, default: () => ({}) },
    tag: { type: String, default: 'DIV' },
    to: {
      type: String,
      default: () => String(Math.round(Math.random() * 10000000)),
    },
  },
  created() {
    this.$nextTick(() => {
      wormhole.registerSource(this.name, this)
    })
  },
  mounted() {
    if (!this.disabled) {
      this.sendUpdate()
    }
  },

  updated() {
    if (this.disabled) {
      this.clear()
    } else {
      this.sendUpdate()
    }
  },

  beforeDestroy() {
    wormhole.unregisterSource(this.name)
    this.clear()
  },
  watch: {
    to(newValue: string, oldValue: string): void {
      oldValue && oldValue !== newValue && this.clear(oldValue)
      this.sendUpdate()
    },
  },

  methods: {
    clear(target?: string) {
      const closer: TransportVector = {
        from: this.name,
        to: target || this.to,
      }
      wormhole.close(closer)
    },
    normalizeSlots(): Function[] | VNode[] | undefined {
      return this.$scopedSlots.default
        ? [this.$scopedSlots.default]
        : this.$slots.default
    },
    normalizeOwnChildren(children: VNode[] | Function): VNode[] {
      return typeof children === 'function'
        ? children(this.slotProps)
        : children
    },
    sendUpdate() {
      const slotContent = this.normalizeSlots()
      if (slotContent) {
        const transport: TransportInput = {
          from: this.name,
          to: this.to,
          passengers: [...slotContent],
          order: this.order,
        }
        wormhole.open(transport)
      } else {
        this.clear()
      }
    },
  },

  render(h): VNode {
    const children: VNode[] | Function =
      this.$slots.default || this.$scopedSlots.default || []
    const Tag = this.tag
    if (children && this.disabled) {
      return children.length <= 1 && this.slim ? (
        this.normalizeOwnChildren(children)[0]
      ) : (
        <Tag>{this.normalizeOwnChildren(children)}</Tag>
      )
    } else {
      return this.slim
        ? h()
        : h(Tag, {
            class: { 'v-portal': true },
            style: { display: 'none' },
            key: 'v-portal-placeholder',
          })
    }
  },
})