A Vue plugin which make Vue component invocated by API.
use npm
$ npm install vue-create-api
use cdn
<script src="https://unpkg.com/vue-create-api/dist/vue-create-api.min.js"></script>
import CreateAPI from 'vue-create-api'
Vue.use(CreateAPI)
// or with options.
Vue.use(CreateAPI, {
componentPrefix: 'cube-'
apiPrefix: '$create-'
})
// then the Vue constructor will have the createAPI function.
import Dialog from './components/dialog.vue'
// make Dialog component invocated by API.
Vue.createAPI(Dialog, true)
// use in general JS files.
// however, the $props can not be reactive.
Dialog.$create({
$props: {
title: 'Hello',
content: 'I am from pure JS'
}
}).show()
// use in a vue component.
this.$createDialog({
$props: {
title: 'Hello',
content: 'I am from a vue component'
},
}).show()// typescript
import CreateAPI from 'vue-create-api'
Vue.use(CreateAPI)
Vue.createAPI(Dialog, events, single)
this.$createDialog({
$props: {
title: 'Hello',
content: 'I am from a vue component'
}
}).show()// d.ts
import Vue, { VueConstructor } from 'vue'
import { createFunction } from 'vue-create-api';
export declare class UIComponent extends Vue {
show ():void
hide ():void
}
declare module 'vue/types/vue' {
interface Vue {
/** create Dialog instance */
$createDialog: createFunction<UIComponent>
}
}using typescript,
terser-webpack-plugin(vue-cli3.x) oruglifyjs(vue-cli2.x) adds{ keep_fnames: true }
| key | description | default |
|---|---|---|
componentPrefix |
the prefix name of your component | - |
apiPrefix |
the api prefix | $create |
-
Parameters:
{Function | Object} ComponentVue component which must containsname{Boolean} [single]whether singleton
-
Usage:
-
This method will add a method which is named
$create{camelize(Component.name)}to Vue's prototype, so you can instantiate the Vue component byconst instance = this.$createAaBb(config, [renderFn, single])in other components. The instantiated component's template content will be attached tobodyelement. -
const instance = this.$createAaBb(config, renderFn, single)Parameters:
Attribute Description Type Accepted Values Default config Config options Object {} - renderFn Optional, used to generate the VNode child node in the slot scene in general Function - function (createElement) {...} single Optional, whether the instantiated component is a singleton or not. If two parameters are provided and the renderFn's type is not function, then thesinglevalue is the sencond parameter's value.Boolean true/false single in createAPI() Config options
config:You can set
$propsand$eventsinconfig,$propssupported reactive properties, these props will be watched.Attribute Description Type Accepted Values Default $props Component props Object - {
title: 'title',
content: 'my content',
open: false
}$events Component event handlers Object - {
click: 'clickHandler',
select: this.selectHandler
}$propsexample,{ [key]: [propKey] }:{ title: 'title', content: 'my content', open: false }
title,contentandopenare keys of the component prop or data, and the prop' value will be taken by the following steps:- If
propKeyis not a string value, then usepropKeyas the prop value. - If
propKeyis a string value and the caller instance dont have thepropKeyproperty, then usepropKeyas the prop value. - If
propKeyis a string value and the caller instance have thepropKeyproperty, then use the caller'spropKeyproperty value as the prop value. And the prop value will be reactive.
$eventsexample,{ [eventName]: [eventValue] }:{ click: 'clickHandler', select: this.selectHandler }
clickandselectare event names, and the event handlers will be taken by the following steps:- If
eventValueis not a string value, then useeventValueas the event handler. - If
eventValueis a string value, then use the caller'seventValueproperty value as the event handler.
You can set all avaliable properties in Vue, but you need to add prefix
$, eg:this.$createAaBb({ $attrs: { id: 'id' }, $class: { 'my-class': true } })
The Returned value
instance:instanceis a instantiated Vue component.And the
removemethod will be attached to this instance.You can invoke the
removemethod to destroy the component and detach the component's content frombodyelement.If the caller is destroyed and the
instancewill be automatically destroyed. - If
-
-
Example:
First we create Hello.vue component:
<template> <div @click="clickHandler"> {{content}} <slot name="other"></slot> </div> </template> <script type="text/ecmascript-6"> export default { name: 'hello', props: { content: { type: String, default: 'Hello' } }, methods: { clickHandler(e) { this.$emit('click', e) } } } </script>
Then we make Hello.vue as an API style component by calling the
createAPImethod.import Vue from 'vue' import Hello from './Hello.vue' import CreateAPI from 'vue-create-api' Vue.use(CreateAPI) // create this.$createHello API Vue.createAPI(Hello, true) // init Vue new Vue({ el: '#app', render: function (h) { return h('button', { on: { click: this.showHello } }, ['Show Hello']) }, methods: { showHello() { const instance = this.$createHello({ $props: { content: 'My Hello Content', }, $events: { click() { console.log('Hello component clicked.') instance.remove() } } }, /* renderFn */ (createElement) => { return [ createElement('p', { slot: 'other' }, 'other content') ] }) } } })
In this example, we create a component
Hellowhich needs to be invoked in api form and we invoke it in another component.The focus is whatshowHello()does: invoking methodthis.$createHello(config, renderFn)to instantiateHello.
In vue component, you can call by this.$createHello(config, renderFn) because the this is just a Vue instance. But in general JS files, you need to use Hello.$create. As shown below:
import Vue from 'vue'
import Hello from './Hello.vue'
import CreateAPI from 'vue-create-api'
Vue.use(CreateAPI)
// create this.$createHello and Hello.create API
Vue.createAPI(Hello, true)
Hello.$create(config, renderFn)Notice, when we use in general JS files, we can't make props be reactive.
We can use the batchDestroy method provided by vue-create-api to destroy all instances uniformly. For example, we can destroy them uniformly when the route is switched:
import Vue from 'vue'
import VueRouter from 'vue-router'
import CreateAPI from 'vue-create-api'
Vue.use(VueRouter)
const router = new VueRouter({ routes: [] })
router.afterEach(() => {
CreateAPI.batchDestroy()
})batchDestroy can receive a filter function to determine which instances need to be destroyed:
CreateAPI.batchDestroy(instances => instances.filter(ins => ins))