963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
4.6 KiB
4.6 KiB
Plugin Structure: Install Method Requirements
Rule
A Vue plugin must be either an object with an install() method, or a function that serves as the install function. The install function receives the app instance and optional user-provided options.
Why This Matters
-
API contract: Vue's
app.use()expects a specific interface. Incorrect structure causes silent failures or errors. -
Options passing: The install method receives options that users pass to
app.use(), enabling plugin configuration. -
App access: The install method receives the app instance, providing access to
app.component(),app.directive(),app.provide(), etc.
Plugin Structures
Object with install method (recommended)
// plugins/myPlugin.ts
import type { App } from 'vue';
interface PluginOptions {
prefix?: string;
debug?: boolean;
}
const myPlugin = {
install(app: App, options: PluginOptions = {}) {
const { prefix = 'my', debug = false } = options;
if (debug) {
console.log('Installing myPlugin with prefix:', prefix);
}
app.provide('myPlugin', { prefix });
},
};
export default myPlugin;
// Usage
app.use(myPlugin, { prefix: 'custom', debug: true });
Function as install (alternative)
// plugins/simplePlugin.ts
import type { App } from 'vue';
function simplePlugin(app: App, options?: { message: string }) {
app.config.globalProperties.$greet = () => {
return options?.message ?? 'Hello!';
};
}
export default simplePlugin;
// Usage
app.use(simplePlugin, { message: 'Welcome!' });
Factory function pattern (most flexible)
// plugins/configuredPlugin.ts
import type { App, Plugin } from 'vue';
interface I18nOptions {
locale: string;
messages: Record<string, Record<string, string>>;
fallbackLocale?: string;
}
export function createI18n(options: I18nOptions): Plugin {
return {
install(app: App) {
// Options are captured in closure - no need to pass through app.use()
const { locale, messages, fallbackLocale = 'en' } = options;
const translate = (key: string): string => {
return messages[locale]?.[key] ?? messages[fallbackLocale]?.[key] ?? key;
};
app.provide('i18n', { translate, locale });
},
};
}
// Usage - options passed to factory, not app.use()
const i18n = createI18n({
locale: 'fr',
messages: {
en: { hello: 'Hello' },
fr: { hello: 'Bonjour' },
},
});
app.use(i18n); // No second argument needed
Common Plugin Capabilities
const fullFeaturedPlugin = {
install(app: App, options: PluginOptions) {
// 1. Register global components
app.component('MyButton', MyButtonComponent);
app.component('MyInput', MyInputComponent);
// 2. Register global directives
app.directive('focus', focusDirective);
// 3. Provide injectable values (recommended)
app.provide('pluginConfig', options);
// 4. Add global properties (use sparingly)
app.config.globalProperties.$myHelper = helperFunction;
// 5. Add global mixins (avoid if possible)
app.mixin({
created() {
// Runs for every component
},
});
// 6. Custom error handling
app.config.errorHandler = (err, vm, info) => {
// Handle errors
};
},
};
TypeScript: Plugin Type
Use the Plugin type for proper typing:
import type { App, Plugin } from 'vue';
// With options type parameter
interface MyOptions {
apiKey: string;
}
const myPlugin: Plugin<[MyOptions]> = {
install(app: App, options: MyOptions) {
// options is typed as MyOptions
},
};
// Without options
const simplePlugin: Plugin = {
install(app: App) {
// No options expected
},
};
Common Mistakes
Missing install method
// BAD - This is just an object, not a plugin
const notAPlugin = {
doSomething() {
/* ... */
},
};
app.use(notAPlugin); // Error or silent failure
// GOOD
const actualPlugin = {
install(app) {
app.provide('service', {
doSomething() {
/* ... */
},
});
},
};
Forgetting to use the app parameter
// BAD - Does nothing
const uselessPlugin = {
install(app, options) {
const service = createService(options);
// Forgot to register anything with app!
},
};
// GOOD
const usefulPlugin = {
install(app, options) {
const service = createService(options);
app.provide('service', service); // Actually makes it available
},
};