-
Notifications
You must be signed in to change notification settings - Fork 9
2. Structure of a Vue Plugin
If you don't created a package yet, please read the creating a Vue Plugin page.
Now we have a plugin folder structure, only the important files were shown below:
package.json
src
|____types
| |____index.d.ts # Type definitions for TypeScript
|____utils.js # Some utility functions for your plugin
|____vue-todo-component.vue # A sample Custom Component, you can remove it if you don't want to provide one.
|____vue-todo.js # The main file of your plugin.
.storybook
|____stories.js # Your plugin's Storybook stories.
examples
|____kitchensink # An example folder for your plugin, you can duplicate
| |____App.vue
| |____index.js
Command | Description |
---|---|
yarn build |
Builds your project for production usage |
yarn example:kitchensink |
Runs the examples/kitchensink application on http://localhost:4000
|
yarn storybook |
Runs storybook stories on http://localhost:{a free port}
|
This is the main file of your plugin, this has some preset abilities like installing itself, registering components, directives, Vuex stores, instance variables or some mixins.
You can see all the file by opening it but we'll focus on the following part of the file:
import VueTodoComponent from './vue-todo-component.vue';
export default class VueTodo {
constructor(options = {}) {
const defaults = {
// This is your plugin's options. It will be accessible with this.options
accessorName: '$todo'
};
this.options = { ...defaults, ...options };
}
// Some instance methods that you can access from this.$myPlugin
world() {
return 'world';
}
static register = (Vue, options, store) => {
console.log('Here is the options of the component', options);
console.log('Here is the store of the app', store);
// You can use `this.options` property to access options.
// Delete this line if your plug-in doesn't provide any components
Vue.component('VueTodo', VueTodoComponent);
// Vue.directive('your-custom-directive', customDirective);
// registerVuexStore(store, 'counterStore', {
// namespaced: true,
// state: { counter: 0 },
// getters: {
// counter: state => state.counter
// },
// actions: {
// increment: ({ commit }) => commit('increment')
// },
// mutations: {
// increment: state => state.counter++
// }
// });
};
// Some lifecycle hooks to add on mixin
static mixin = () => ({
mounted() {
console.log('Hey! I am running on every mount, please remove me!');
console.log(this.$store);
}
});
The code is separated into 5 main parts:
- Components
- Options
- Instance methods/getters
- Registrations
- Mixins
Since the plugin is based on a class, you can convert it to your own structure.
// 1. COMPONENTS
// Here is the place for your component imports
import MyButton from './myButton.vue';
import MyInput from './myInput.vue';
export default class VueMyUILibrary {
constructor(options = {}) {
// 2. OPTIONS
const defaults = {
// This accessorName is required, you can remove it but you'll need to remove this from
// the logic. Most of the time, plugins need an accessor like that.
accessorName: '$myUI',
// Here is the place for your another options
};
// Setting options with defaults.
this.options = { ...defaults, ...options };
}
// 3. INSTANCE METHODS
// You may want to have some abilities by reaching from the component using `this.$myUI.{method}`.
// This may be handy on your plugins.
doSomething() {
/* */;
}
// 4. REGISTRATIONS
// This is a static method to register your:
// - Components
// - Directives
// - Vuex Stores
// - Mixins
// - Global variables/methods.
static register = (Vue, options, store) => {
// This method is being called with 3 arguments, the Vue instance, the options and the global Vuex store.
// You can use `registerVuexStore` utility to register a custom store.
// e.g. let's register the things we've imported.
Vue.component('my-button', MyButton);
Vue.component('my-input', MyInput);
};
// 5. THE MIXIN
// These will be registered to the components. `Vue.mixin` could be used on `register` but I recommend
// using this since it's `beforeCreate` has some required tasks about registering plugin.
static mixin = () => ({
data: () => ({
heyIAmAStateOnEveryComponent: true
}),
mounted() {
console.log('Hey! I am running on every mount, please remove me!');
},
/* Other things to do */
});
You can have many custom components in your plugin. E.g.
- Building a Vue UI plugin that provides a UI component set,
- A functional plugin that provides a component that makes some complex things,
You need to import them in your vue-plugin.js
(your-dashed-plugin-name.js
)
It is a simple import statement:
import MyButton from './myButton.vue';
import MyInput from './myInput.vue';
You may need to allow your users customize something on your plugin. E.g.
- The theme options if you're building an UI plugin,
- Simple on/off switches.
You need to add some extra keys to defaults
constant since you can only provide defaults. this.options
will be set by boilerplate.
Note:
accessorName
is required on the file, you shouldn't remove it. If you remove it please change references. But I don't recommend making it static, plugin users may need to change it.
If you're providing a component
, directive
, Vuex store or something needs to be injected into users app, you need to setup your register
static function.
static register = (Vue, options, store) => {
Vue.component('my-button', MyButton)
Vue.component('my-input', MyInput)
Vue.directive('focus', ...)
Vue.mixin({ ... })
};
vue-plugin-boilerplate
has a registerVuexStore
helper that registers a custom store to users' store.
static register = (Vue, options, store) => {
registerVuexStore(store, 'my-awesome-store', {
namespaced: true,
state: { counter: 0 },
getters: {
counter: state => state.counter
},
actions: {...}
mutations: {...}
})
};
You can also import these stores from file:
import vuePluginStore from './vue-plugin-store';
...
static register = (Vue, options, store) => {
registerVuexStore(store, 'my-awesome-store', vuePluginStore)
};
...
The boilerplate has a beforeCreate
method to setup Vue instances. You can extend the mixin by using mixin
static method of the plugin.
static mixin = () => ({
data: () => ({
heyIAmAStateOnEveryComponent: true
}),
methods: {
hello() {
console.log('I am a method on every component!')
}
}
});