-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
Unify/simplify Vue.component
and Vue.extend
#156
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
Comments
In fact I suggest don't even return the extended constructor, just return the options: In plugin: exports['component-A'] = { /* ... */ }
exports['component-B'] = { /* ... */ } In app: var plugin = require('plugin')
Vue.component('A', plugin['component-A'])
Vue.component('B', plugin['component-B']) This allows the user code to rename the component. Theoretically, |
Yes, but my main concern is: how to instantiate the extended VM from the code? I could replace this: // app.js
var PluginComponent = Vue.component('plugin-component')
var app = new PluginComponent({ data: {}, methods: {}, /* … */ }) By this: // app.js
var PluginComponent = Vue.extend(plugin['plugin-component'])
var app = new PluginComponent({ data: {}, methods: {}, /* … */ }) Which is better because it does not register a component name, but it’s still verbose for the user. Maybe the plugin API or Vue itself (see the |
I get you now. That makes sense. I think in addition to var ExtendedComponent = Vue.extend('some-registered-component', { /* ... */ }) So Vue.component('extended-component', 'base-component', { /* ... */ }) Just some rough thoughts, need more polishing. Also @th0r 's previous suggestion of removing chaining and returning the registered component is also worth considering. I think these will have to be part of 0.10 though, since this is going to be pretty big API change. |
Or maybe I should try to unify |
Yes it could make sense, since a
Conversely, the term ViewModel could be replaced with the term Component everywhere (except in the Getting Started section), and // Same as the current .extend()
var ExtendedComponent = Vue.component({})
// Get a component, same as the current .component('name')
var ExtendedComponent = Vue.component('extended-component')
// Still the same, except it returns the extended component
var ExtendedComponent = Vue.component('some-registered-component', {})
// Inheritance
var ExtendedComponent = Vue.component('extended-component', 'base-component', {})
// And now that becomes weird…
ExtendedComponent.component('another-extended-component', 'another-base-component', { /* ... */ }) And the // Same as `new Vue({})`
Vue.create({})
// Same as `new (Vue.component('some-registered-component'))({})`
Vue.component('some-registered-component').create({})
// Same as above
Vue.create('some-registered-component', {}) |
Here's another vote for unifying I like @bpierre's suggestion which favors |
I agree with with unifying everything into Vue.component. In most of my projects I am hardly ever using the Vue.extend({}) syntax and just create my components with Vue.component({}). Maybe you can change extends into an inheritance method? e.g. Vue.component('foo', {}).extend('bar'); // bar is another instantiated component |
Edited issue title to keep it relevant. |
Some thoughts after playing with some options:
// sub-component is using Vue as the base class
// and encapsulated inside MyComponent
MyComponent.component('sub-component', { /* ... */ })
// ExtendedComponent is using MyComponent as the base class
// and isn't necessarily part of MyComponent
var ExtendedComponent = MyComponent.extend({ /* ... */ }) In this case unifying the two would actually cause confusion (as noted in @bpierre 's "now that becomes weird..." example). Back to the original problem, I think a core issue here is Vue.js is trying to support two different paradigms - the first is Backbone-style, class & inheritance based API, and the second is Web Component style, declarative, markup-based API. Think about how you can use a I think it would still help to provide some sugar for some common tasks, but I'd prefer to do so without affecting the underlying semantics. |
Let me see if I understand. When a sub-component is created inside an existing component like this: MyComponent.component('sub-component', { /* ... */ }) It does not inherit the instantiation options of However, in this example: var ExtendedComponent = MyComponent.extend({ /* ... */ }) Instances of |
@Obsoleter yes. Originally it expects a constructor function - directly passing in an option object is just syntax sugar, but now I think that's a source of confusion. |
@yyx990803 I agee on keeping both, there is definitely use cases for either one when you start getting more advanced applications. I think a good explanation of the differences mentioned above in the docs would be enough for people to understand it. |
Thanks Evan, the The plugin API is for adding Components / Directives / etc. to a Vue constructor: an extended Vue can be shared with a simple init function. What about the |
I think an issue with Personally, I recommend the second syntax in your original options: var PluginComponent = Vue.component('plugin-component')
var app = new PluginComponent({ /* … */ }) Also, to cherry pick a component from a plugin that exports option objects: var PluginComponent = Vue.extend(plugin.pluginComponent)
var app = new PluginComponent({ /* … */ }) They are a bit verbose, but I think it makes the concepts clearer. |
A small nitpick about In popular JS libraries (jQuery, Underscore, also others) |
@pesho I think |
Added explanation in docs: vuejs/v2.vuejs.org@1689be6#diff-5f2a33fd3299fa69ca0afb86bb542682R39 |
Let’s say I have a plugin providing a component which is meant to be instantiated with
new
(not from a template):Now, I want to use it for my main VM. Some solutions:
Direct instantiation on the constructor returned by
Vue.component(name)
. Seems verbose and unintuitive:Put the constructor in a variable first. Still verbose, but clearer:
Provide a specific solution in my plugin. Clearer app.js, but proprietary API, and adds a lot of cruft in plugin.js.
Proposed solution
Please ignore if I missed some already existing mechanism.
A solution could be to introduce a new global method:
Vue.create([String | VM], options)
. It’s really the same than the #149 proposal, but for instantiation purposes.The reason to not add this parameter on the
Vue
constructor itself is because it would feel weird to provide a constructor as a parameter of another constructor.It would allow to do this:
It would also add a new syntax for classic instantiations:
Which could have the positive effect of pleasing people who don’t want
new
in their code no matter what, thanks to the “new considered harmful” articles… I know, it’s a stupid reason :-)Extend-only plugin API
Somewhat related question: what if a plugin wants to provide an extended VM only, without registering a component? Should this be taken into consideration by the plugin API, or should it be implemented by every plugin the way they want?
Example:
What do you think?
The text was updated successfully, but these errors were encountered: