Created
January 13, 2021 10:14
-
-
Save Alan-Liang/a847559433919ecb53dff217ed9708bb to your computer and use it in GitHub Desktop.
Vue 2 teleport
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage: | |
* <app-bar> | |
* <teleport-target name="app-bar" /> | |
* </app-bar> | |
* And then: | |
* <teleport to="app-bar"> | |
* <h1>Hello World!</h1> | |
* </teleport> | |
*/ | |
const targets = {} | |
export const TeleportTarget = { | |
name: 'TeleportTarget', | |
data: () => ({ children: [] }), | |
props: { | |
name: { type: String, required: true }, | |
}, | |
created () { | |
if (this.name in targets) throw new Error(`TeleportTarget: duplicate name ${this.name}`) | |
targets[this.name] = this | |
}, | |
beforeDestroy () { | |
delete targets[this.name] | |
if (this.children.length > 0) throw new Error(`TeleportTarget: ${this.name} beforeDestroy but still has children mounted`) | |
}, | |
render (h) { | |
return h('div', this.children.map(vm => vm.$slots.default || []).flat()) | |
}, | |
} | |
export const Teleport = { | |
name: 'Teleport', | |
props: { | |
to: { type: String, required: true }, | |
}, | |
mounted () { | |
if (!(this.to in targets)) throw new Error(`Teleport: non-existent target ${this.to}`) | |
targets[this.to].children.push(this) | |
}, | |
beforeDestroy () { | |
if (!(this.to in targets)) throw new Error(`Teleport: non-existent target ${this.to} on unmount`) | |
const children = targets[this.to].children | |
children.splice(children.indexOf(this), 1) | |
}, | |
render: h => h('span'), | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment