A tool for dynamic mounting Vue components and maintaining the component tree.
中文文档 | English
You can install the library via npm.
npm i vue-mount -S
or via yarn:
yarn add vue-mount
or via CDN
<!-- import Vue. -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<!-- import vue-mount -->
<script src="https://cdn.jsdelivr.net/npm/vue-mount/dist/vue-mount.min.js"></script>
<script>
var mount = window['VueMount'].mount;
var Mount = window['VueMount'].default;
</script>
import { mount } from "vue-mount";
// just import a single file component
import Alert from "./alert.vue";
// mount component and return instance
const alert = mount(Alert);
// The exposed method `mount(cmp, opt)` is the syntactic sugar of `new Mount(cmp, opt).mount()`
import Mount from "vue-mount";
// alert.vue is a common `single file component`
import Alert from "./alert.vue";
const mountAlert = new Mount(Alert, {
// mount target.
// the special value indicates create a new root vue instance
target: 'new',
// props data passed to component
props: {
content: 'Mount alert component to a new Vue root instance'
},
// modify component data
data: {
someInnerData: 'modified'
},
// attach event listeners
on: {
'some-event'(eventData, vm, mnt) {
// vm is a component instance
// mnt is current Mount instance
}
},
watch: {
content: {
immediate: true,
handler(newValue, oldValue, vm, mnt) {
console.log('Content has changed: ' + newValue);
// do unwatch
// make sure the unwatch method exsit while `immediate` is true
if (mnt.unwatchMapper.content) {
mnt.unwatchMapper.content();
}
}
}
}
});
// Get alert component instance
let alertVm = mountAlert.getInstance();
// Mount alert component
// Component would not be mounted more than once
alertVm = mountAlert.mount();
// Dynamicly set props data of the component.
mountAlert.set({
props: { content: 'Props changed' }
});
// Destroy component and it's element
mountAlert.destroy();
// New component would be mounted
alertVm = mountAlert.mount();
- Type: { string | Element | Vue | VNode }
- Default:
new
- Details: You can pass
css selector
,Element
,Vue instance
,VNode
or special value includingnew
androot
new
: default value. Vue component would be mounted with a new Vue root instance.root
: Vue component would be mounted to an existing Vue root instance. if the root instance or root element is not found underMountOption.root
option, the component would be mounted with a new Vue root instance behaving just like optionnew
.- When giving a
Vue instance
, the component would replace/append the Vue instance and added to the components tree(see MountOption.mode), former Vue instance would be destroyed when the component is mounted.
- Examples:
mount(Alert, { target: "root" }; mount(Alert, { target: "#target" }; mount(Alert, { target: document.querySelector('.list') }; mount(Alert, { target: this.$refs.component }; mount(Alert, { target: this.$refs.component.$slots.default[0] };
Special Note: When configured as
new
, the mounted component cannot access the configuration passed in the root instance, resulting in the mounted component UNABLE to access configuration globally registered on the root component such asthis.$router
(because a new root instance was created, but there is alternative); In other cases,vue-mount
will automatically query and join the component tree context.
- Type: { string }
- Default:
replace
- Options:
replace
,append
- Details: Specific the mount mode. Corresponds to the behavior on its component tree.
- Examples:
// Alert component would be append to current component mount(Alert, { target: this, mode: 'append' });
Attention: When the value of option
target
isnew
, orroot
, optionmode
will be ignored and be reset toappend
.
- Type: { string | Element | Vue | VNode }
- Default:
#app
- Details: Specific a root element. (All values given will be parsed to be an HTML element)
- Type: { VueOptions }
- Default:
{}
- Details: Specific the Vue contructor options when creating new vue root instance
- Examples:
mount(Alert, { rootOptions: { data: { root: 'new root instance' }, methods: { ... }, ... } };
- Type: { Object }
- Details: Specific component props data.
- Type: { Object }
- Details: Modify component data after the component instance was created (mounted is not necessary).
- Type: { [event: string]: Function | Object }
- Details: Attach event listener to the component instance.
-
build-in event:
mount:mount
: Triggered when callingmount
method or ready to mount component。mount:destroy
: Triggered when (underlying) callingdestroy
method.
-
Object configure:
once
{ Boolean }: Whether the listener will be removed once it triggers for the first time.handler
{ Function }: The event callback function. Compared to event callback function of Vue (vm.$on/$once), the last two additional arguments are currentVue component
and currentMount instance
.
The
this
argument of the callback function points to the current Mount instance, although you can use the arrow function to avoid this behavior.
-
- Examples:
mount(Alert, { on: { 'mount:mount'(vm, mnt) { console.log('mount:mount'); vm.doSomething(); }, 'mount:destroy'() { console.log('mount:destroy') }, remove: { once: true, handler: (vm, mnt) => { console.log('remove'); } }, 'remove-with-data'(...args) { console.log(args); } } })
- Type: { [key: string]: Function | Object }
- Details: An object where keys are expressions to watch and values are the corresponding callbacks. The value can also be a string of a method name, or an Object that contains additional options.
-
Object configure:
immediate
{ Boolean }: Passing inimmediate: true
in the option will trigger the callback immediately with the current value of the expression.deep
{ Boolean }: To also detect nested value changes inside Objects, you need to pass indeep: true
in the options argument.handler
{ Function }: The callback function when the value changes. Compared to the callback function of Vue (vm.$watch), there are always be 4 parameters like:newValue, oldValue, vm, mnt
. The last two additional arguments are currentVue component
and currentMount instance
.
The
this
argument of the callback function points to the current Mount instance, although you can use the arrow function to avoid this behavior. -
Unwatch: Each key you passed in the
watch
option will be added to the attributeunwatchMapper
of Mount instance, you can call the method likemnt.unwatchMapper.attr()
to unwatch it.
-
- Examples:
mount(Alert, { watch: { otherAttr(newV) { console.log(newV); } attr: { handler(newValue, oldValue, vm, mnt) { console.log(args); // do unwatch // make sure the unwatch method exsit while `immediate` is true if (mnt.unwatchMapper.content) { mnt.unwatchMapper.content(); } }, immediate: true, }, } })
Attention: Only declare the data upfront in the
data
option, the callback function can be called.
- Arguments: { MountOptions }
- Returns: { Vue }
- Details: Return a vue component instance, calling the method multiple times will returns the same instance
Attention: When the value of option
target
isroot
while no root instance/element was found(which means need to create a new Vue instance), ortarget
isnew
, they all lead to the result that instance would be mounted right now.
In order to ensure behavioral consistency, it is recommended to use the
#mount
method first.
- Arguments: { MountOptions }
- Returns: { Vue }
- Details: Mount Vue component, update the component tree and return a Vue component instance.
Calling the method after the component was destroyed will re-mount the component.
Calling the method multiple times will ONLY mount once
- Arguments: { MountDataOptions }
- Returns: { Mount } Current instance of
Mount
. - Details: Dynamicly set
props
,data
andlisteners
of the component.
- Returns: { Vue }
- Details: Destroy the Vue component instance and remove the associated elements. Diff from Vue's $destroy method.
- Returns: { Element | Node }
- Details: Returns the element associated with the component.
- Returns: { VueMount }
- Details: returns the VueMount instance associated with the component instance.
-
When VueMount mounts the component to a new Vue root instance, the component will not be able to obtain the
$router
/$store
and other attributes (reason) configured in the original root component. Of course, there are the following ways to solve this problem.mount(Component, { ... data: { $store: this.$store, // Why not $router? VueRouter uses the object.defineProperty method internally and only sets the getter property, so this value cannot be overridden router: this.$router, ... }, ... });
Then you can use
this.$store
/this.router
inside the component to access. -
When the component has been mounted on the original root instance, but the value cannot be obtained in the component's
created
/mounted
lifecycle hooks, you need to use VueMount built-in event to solve the problem:mount(Component, { ... on: { 'mount:mount'(vm) { vm.$router; vm.$store; } }, ... }