Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin interface spec #88

Closed
yyx990803 opened this issue Feb 9, 2014 · 4 comments
Closed

plugin interface spec #88

yyx990803 opened this issue Feb 9, 2014 · 4 comments
Milestone

Comments

@yyx990803
Copy link
Member

Verbose version

var vueTouch = require('vue-touch')
Vue.use(vueTouch)

Shorthand equivalent

Vue.use('vue-touch')

Inside plugin...

exports.install = function (Vue) {
    // Vue.require exposes internal modules
}

The use function...

Vue.use = function (plugin) {
    // if string require it
    plugin.install(Vue)
}
@yyx990803 yyx990803 added this to the v0.8.5 milestone Feb 9, 2014
@yyx990803
Copy link
Member Author

a891df2

@bpierre
Copy link

bpierre commented Feb 19, 2014

I have a few questions about the plugin interface!

  1. What is the usage of the require param here (which is now Vue.require according to main.js)?
    For example, is it correct to assume that Vue.require('utils') will be available, and to use it in a plugin?
  2. Why do we have the choice between returning a function or an object containing { install: function(){} }? Is it to keep the same design than directives, computed properties, etc.?
  3. I would like to allow the user to configure a plugin before adding it. Some ideas:

Idea 1: a configuration function

// my-plugin.js
module.exports = function(config) {
  return function(Vue) {
  };
};
// my-app.js
var myPlugin = require('my-plugin');
Vue.use(myPlugin({ foo: 'bar' }));

The issue with that solution is that it disables the usage of the shorthand:

// my-app.js
Vue.use('my-plugin'); // Won’t work, only the configure function is called

Idea 2: add a config hook

// my-plugin.js
module.exports = {
  config: function(config) {
    this.foo = config.foo;
    return this.install;
  },
  install: function(Vue) {
  }
};
// my-app.js
var myPlugin = require('my-plugin');

// This would allow this (`config` returns `this.install`):
Vue.use(myPlugin.config({ foo: 'bar' }));

// Or this, with the configuration passed as a second param:
Vue.use('my-plugin', { foo: 'bar' });

// And of course, this (`install` is directly called, no config):
Vue.use(myPlugin);
Vue.use('my-plugin');

// Or a global configuration:
myPlugin.config({ foo: 'bar' });
Vue.use(myPlugin);
AnotherVue.use(myPlugin);

As you can see in the last example, there is still an issue with this solution: each time .config() is called, the settings defined on the plugin object will persist and be shared between the plugin’s instances.

A solution could be to wrap this in some magic (which is more verbose…):

// my-plugin.js

// Vue.plugin() ensures that each time .config() is called, a new object is created.
var Vue = require('vue');
module.exports = Vue.plugin({
  config: function() {
  },
  install: function() {
  }
});

…but another problem is that require could be missing (e.g. with Vue on window.Vue), and it will require some detection code, which is not acceptable for a plugin interface.

I don’t really like the second idea, because it adds “Plugin” concept, and I think the less concepts we have, the better it is. Also, maybe I’m missing a super elegant solution that already exists for what I’m trying to achieve: sorry if it’s the case.

What do you think?

@yyx990803
Copy link
Member Author

Thanks for the suggestions Pierre! The original issue is a bit out of date - require is no longer passed in as an argument. I have edited it.

  • Vue.require works as you'd expect - it exposes internal modules like utils, compiler, etc.
  • Allowing both function and { install: function () {}} is just for convenience - similar to the directive and computed property APIs.
  • For configuration - I think we can do this:
Vue.use(plugin, { foo: 'bar' })
// or
Vue.use('my-plugin', { foo: 'bar' })

We just need to change Vue.use's implementation to:

Vue.use = function (plugin, options) {
    // if plugin is string require it
    plugin.install(Vue, options)
}

Inside plugins:

exports.install = function (Vue, options) {
    // do stuff based on options
}

Plugins that don't need options can simply ignore the options argument. I want plugins to be implemented without having to require Vue at all, so that we can easily mock Vue and test the plugin.

@bpierre
Copy link

bpierre commented Feb 20, 2014

Thanks for your answers!

bpierre added a commit to bpierre/vue that referenced this issue Feb 20, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants