vuejs / rfcs

RFCs for substantial changes / feature additions to Vue core
4.87k stars 546 forks source link

Function-based component API (extended discussion) #55

Closed abalashov closed 5 years ago

abalashov commented 5 years ago

Opening an issue here with a copy of my original comment to #42, per @yyx990803's request:


I am the author of "Love letter to Vue": http://www.evaristesys.com/blog/love-letter-to-vue/

As a big booster of Vue who can appreciate its distinctive characteristics and the way it has stood apart from competing frameworks, I must say that I am perturbed and disappointed by the function API proposal. I have to agree with the above posters who say that no serious problem is being solved here which would warrant such a radical shift, and that in essence, this proposal amounts to chasing shiny new things. Yes, there are indeed some code decomposition and modularity problems that this change addresses. But not all theoretical problems are worth addressing.

One of the biggest virtues of Vue, which I mention in the article, is that here, halfway through 2019, it's still quite literally the same Vue I first picked up in late 2016. This is a refreshing contrast to the general pace of change and deprecation in the JS/web world. Frank Chimero's high-level, perspicacious take on this problem bears mention here: https://frankchimero.com/writing/everything-easy-is-hard-again/

From a political and a philosophical point of view, I think it's vital to understand that introducing radical API changes of any kind to any project is breaking, and a generous offer of backward compatibility with old APIs does not solve this problem. With due acknowledgment to the fact that the 2.x API is not slated for deprecation and the labourious emphasis this has received, you're still sunsetting it in an overall ecosystem sense. The 2.x API will no longer be a first-class citizen. A completely new way of doing things insinuates a preferred new way of doing things, and sample code, tutorials, books, etc. will inevitably adopt it over time, leading to a manageability and direction crisis for those with investments in huge Vue code bases. New APIs are unavoidably ideological statements, and the devaluation of old APIs -- indeed, the very ontology of "old" vs. "new" -- have an ideological valence.

While change is inevitable, people want to follow "best practices" in an effort to stave off bit rot, and feel a psychological pressure to buy into the current wave of thinking. So, offering to support the old options API is not of much help; this RFC raises the prospect that the commitment to maintaining backward compatibility with the 2.x option API is not steadfast, and will slowly de-orbit over time, like the Mir space station. In effect, you are decreeing that there's now a new way of doing things, and this is the way they should be done.

I also agree with the criticism mentioned in the Downsides section above: the concern that this way of doing things is arcane and more likely to lead to byzantine or labyrinthine "spaghetti code". One of the biggest selling points of Vue is its simplicity and approachability. It's static enough that a major organisational commitment to Vue has shelf life and durability, rather than evaporating in one's hands, as so many other JavaScript-related commitments do owing to capricious, whimsical API changes and architectural gewgaws.

Thus, technical bickering about code organisation and modularity notwithstanding, from a business and ecosystem health point of view, I think this is the light in which this RFC should be considered, and the cost against which the (from my perspective, marginal) improvements offered should be carefully and judiciously weighed. I do not see a sufficiently captivating problem here worthy of such a radical solution, even if commitment to the 2.x approach is scrupulously observed for some time. It's not worth throwing away the things that make Vue good.

I'm natively Russian, and there is an old political anecdote about this:

Lazar Kaganovich brings Stalin a scaled-down model of a new, reconstituted Moscow, the grandiose global Capital of Socialism that Stalin envisioned (not unlike the visions of Hitler & Speer for the Thousand Year Reich architecture). Most iconic historical features of pre-revolutionary Moscow are demolished, and replaced with grand plazas and enormous, titanic buildings that capture the idealism of the class-conscious revolutionary proletariat, the enormity of the Generalissimus's futuristic vision, and the zeal to shed bourgeois architecture and aesthetics and break with the past.

Stalin asks: "Lazar, where is Saint Basil's Cathedral?"

"It was removed; it will be demolished."

Stalin heaves a sigh and rolls his eyes. "Lazar, put it back."

yyx990803 commented 5 years ago

I respect your opinion so please don't take any of the following as being personal.

no serious problem is being solved here which would warrant such a radical shift, and that in essence, this proposal amounts to chasing shiny new things

I couldn't disagree with this more. Logic composition is probably one of the most serious problems in terms of scaling projects. Quoting myself from another thread:

Vue started small, but today it's being used in a very wide range of projects, with varying level of complexity and business domains. Users dealing with different types of projects will run into different needs, some can be easily dealt with using the object-based API, while some cannot. The primary example is

  1. Large components (hundreds of lines long) with encapsulates multiple logical tasks
  2. The need for sharing the logic of such tasks between multiple components.

For (1), each logical task is forced to be split between option types. For example, a single data-fetching task may need a prop, a data property, a computed property, a mounted hook and a watcher to work together. This means when you pick up this component and try to understand its data-fetching logic, you are constantly jumping up and down in the options list trying to locate the pieces that are related to it. At the same time, when you skim over a property, although you know what type it is, it's quite a bit harder to tell which logical task it is supposed to be dealing with. This gets worse as more logical topics are added to the component. In comparison, with the new API, all related logic for data fetching can be grouped together, and more importantly, cleanly extracted into a separate function, or even a separate file.

An analogy for this problem is file organization in projects. Many of us have come to agree that organizing files by file type (e.g. splitting everything into html, js and css folders) don't really scale. The code related to a feature will be forced to be split between three folders, just for a false impression of "separation of concerns". The key here is that "concerns" is not defined by file type. Instead, most of us opt to organize files by feature or responsibility. This is exactly why people love Vue single-file components. SFC is a way to organize code by feature. Ironically, when SFCs were first introduced, many resisted it because they feel that it violated separation of concerns, only later to acknowledge that SFCs are in fact the more reasonable way to separate concerns.

Point (2) has largely been explained in the Motivations section of the RFC, showing that it achieves what mixins/HOCs/scoped slots can achieve without any of their drawbacks.

With React Hooks, we discovered some of its characteristics could help those users solve these problems described above. This is the fundamental reason for us to come up with this proposal. It is indeed a "new thing", but we are adopting the new thing because it presents a solution to objectively existing problems, not just because they are "new". In the long run, the availability of this new API will pay huge dividends in the hours saved for the developers dealing with the mentioned problems.

Type safety is also an important consideration - again, this is something many users wanted badly but may not appear valuable to those who do not use TS. That's understandable - but I think it's a bit selfish to claim that it's not solving any problems because the problems being solved does not affect you.

introducing radical API changes of any kind to any project is breaking, and a generous offer of backward compatibility with old APIs does not solve this problem

"Breaking" is defined by users forced to change their code. Since users will not have to change their existing code, it is not breaking. I don't think there's anything else to argue about in this aspect.

If even backwards compatibility is not enough, then you are essentially saying a project should never introduce any radical new ideas, ever. I think that's project policy level argument, which if I get to vote, I will firmly vote against. We will try our best to keep the best interest of our users in mind, but the project must and will evolve.

this way of doing things is arcane and more likely to lead to byzantine or labyrinthine "spaghetti code". One of the biggest selling points of Vue is its simplicity and approachability. It's static enough that a major organisational commitment to Vue has shelf life and durability, rather than evaporating in one's hands, as so many other JavaScript-related commitments do owing to capricious, whimsical API changes and architectural gewgaws.

On the contrary, the very motivation of this proposal was to improve the maintainability of long-term Vue projects.

If we look at any JavaScript project, all code starts from an entry file, which is essentially an implicit "main" function being called when your app starts. If having a single function entry will lead to spaghetti code, then all JavaScript projects should be spaghetti code - which is obviously not the case. Why? Because as developers we've learned to organize our code by splitting it up, either into modules or into smaller functions.

A core characteristics of the function-based API design is that understanding code in setup() is not any different from understanding idiomatic JavaScript code and any technique you can use to organize ordinary JavaScript code can be used to organize your setup() function. Any knowledge / style guide / code review process that applies to normal JavaScript code written by your team can be applied to code in Vue setup() functions.

I agree that with the new API you have a theoretically lower bottom threshold for code quality, but as mentioned that can be mitigated by whatever you are already doing to prevent spaghetti code in non-Vue parts of your codebase. On the other hand, code written with the new API also has a substantially higher upper limit in terms of code quality. Any code written with the new API can be refactored into much higher quality code than their options-based equivalent, whereas with the options-based API you will have to resort to mixins and deal with its drawbacks.

I also want to point out that this RFC is not about trading simplicity for maintainability. We should be aware that we are comparing the impressions between an API you've probably been using for years vs. an API you've just seen for the first time. Fundamentally, this is a shift of how you think of a component:

What many users are lamenting when they talk about "losing simplicity" is in fact losing the ability to inspect a component by option types. But with the new API, it should be quite straightforward to implement a component analyzer that provides a view that allows you to inspect the component by property types. That is to say we would be able to look at our component from both perspectives, whereas with options-based API you are limited to one (since the intention about logical topics is lost when split between options).

It's not worth throwing away the things that make Vue good

I'm getting tired of repeating "nothing is being thrown away." But let's try to define what "things that make Vue good" really is. Many users against this RFC seem to define that as the object-syntax, and as if taking the object-syntax away takes away everything that makes Vue Vue. But let's take a look at what is left intact:

Vue's object syntax has existed since day one. Many of the above were added later along the way, and each contributed to Vue's growth. If you believe the object-syntax is all that matters to you, I would kindly ask you to take a step back and rethink what really makes Vue what it is. After all, this RFC is not that radical a change as it may seem.

smolinari commented 5 years ago

I have to agree with the above posters who say that no serious problem is being solved here which would warrant such a radical shift, and that in essence, this proposal amounts to chasing shiny new things.

The new API solves these problems:

  1. It fixes the issues Vue currently has with logic composition.
  2. It solves the issues of type inference, leading the way for Vue to be built on TypeScript and offering first class TypeScript support.
  3. And not directly mentioned in the RFC, but core to the whole RFC, is the way features of one or more components can now be encapsulated properly and still have strong cohesion. It's allows for better following of the SOLID design principles.

I wrote an article many moons ago about the "separation of responsibilities" Vue affords the community and I knew at that time, it was why Vue was so cherished by those who "understood" it. It's why I love Vue too. Yes, Vue was also my favorite and still is, because every time I leave Vue and work even a little on some React project, even a simple to-do list, it feels......icky.

So, I get it. I do understand the feeling of having been let down, by leaving Vue's "norm" of object option API.

But, I also understand the benefits of the new API. I wouldn't consider myself an advanced programmer, and I'm learning more and more. I'm on the Quasar Framework team and I'm only mentioning that, because here and there, I get to work on bugs and dig into sometimes complex components. For instance, just the other day, I dug into QEditor to fix a link button/ link editor issue. It was hard for me to get into that component's code, because so much of the feature's code I needed to look at was split up into the different options. Some of the code was in a mixin, the rest spread out across a 400 line component, using a render function. It was hard for me to get the gist of the whole feature of the link button and the link editor.

In the end, I fixed the bug, but my solution wasn't elegant and of course, Razvan, the founder and lead dev of Quasar, came up with a much more elegant (and cross-browser complete) solution.

Thing is, I know for sure, had QEditor been built with a more "feature based" code design, where the link button and editor were more encapsulated, I'd have been able to understand the inner workings of the component much faster and might even have come up with a more elegant solution.

I also wrote an article asking users to actually dig into the source code of Quasar. But, I also understood the "nah, it's wonderful magic, I don't want to learn the tricks" kind of mentality. And it's Vue's option object magic that more advanced developers want to break. And, unfortunately, it's also that kind of magic that makes Vue so wonderful.

I realize that story and my impressions/ opinions aren't going to persuade many users, who haven't gotten into that kind of depth of component code yet. And that is more than likely 80% of Vue's user base. However, the things most of you are counting on, the component frameworks you are using, could very much take advantage of better code encapsulation. So, maybe we can all see this as a good addition (and most importantly, always an addition) to the current API for more advanced users????

One thing that also just hit me while writing this reply was this. We are all happy with Vue's template DSL, which is staying despite the new API btw 😄. When I reread this part of the RFC......

Options removed in the Lean Build These options will not be available in the lean build of 3.0.

data (replaced by setup() + value + state) computed (replaced by computed returned from setup()) methods (replaced by plain functions returned from setup()) watch (replaced by watch) provide/inject (replaced by provide and inject) mixins (replaced by function composition) extends (replaced by function composition) All lifecycle hooks (replaced by onXXX functions)

......all v3.0 is doing is the same for HTML. It's a (rather simple) DSL for getting Vue's reactivity into standard JavaScript. I'm not sure how many of you can agree with that, but if you look at the 7 function + the lifecycle hook onXXX additions, it's really not that much to learn or use. It's most definitely easier than React's hook system (and also doesn't have it disadvantages). And in the end, Vue's SFCs, even with this new API, is absolutely nothing like React. Why people say that, I have no idea.

What is similar to React is offering more flexiblity and yes that means more responsibility on us, the users of Vue. But, it's still Vue and it's still better than the rest and now it's even more awesome.

Scott

beeplin commented 5 years ago

@smolinari totally agree... digging into Quasar's complex components and finding something among all kinds of mixins is a nightmare. :))

EDIT: in case of misunderstanding: I am talking about the flaws of mixin mechanism. Nothing to do with quasar ;)

smolinari commented 5 years ago

@beeplin - And just to be clear, you would also agree when I say, Quasar isn't poorly written either. It's Vue's built-in constraints, which make it that nightmare.

Scott

martinsotirov commented 5 years ago

I think the elephant in the room is that the problems this RFC solves (logic composition and better type support) are legitimate but not faced by the community at large.

I have used Vue exclusively for frontend work since 2016 (from small one-off things to large enterprise projects), and I have yet to face any of the problems this RFC solves. I admit that mixin usage can be a problem for large codebases (see Vuetify) so I just avoid using mixins. There are just better ways to structure large modular codebases.

thatandyrose commented 5 years ago

Hi guys and gals, not sure if this is the right place to comment on the RFC (if not let me know!) but here goes:

What's great about the current options based API is clarity and opinion. It's clear what is framework hook/code and what is your code.

What's bad about the new proposal is, it lacks opinion and everything is kinda just mixed in there. It's not as clear nor as friendly.

Having said that, I 100% agree this is solving a real issue, which is separating different concerns of your component. And I also agree mixins don't kinda work.

However, could we find another middle ground? vuex has a nice example of "modules" within a store to separate concerns of different sections of your app.

In this way, could we not think of the options API as having many concerns? So, you could perhaps have many data options, many computed options, but all nested within their own concern.

I realise this is just an off the cuff idea, but could be path towards solving the concerns issue while still maintaining the API friendliness and simplicity of vue!

Thoughts? or... shall I just "get my coat" (reference to an old British sitcom 😬 )

smolinari commented 5 years ago

In this way, could we not think of the options API as having many concerns? So, you could perhaps have many data options, many computed options, but all nested within their own concern.

That IS the whole idea of the function-based API. It takes the options you mentioned and makes them functions, which need to be called within a setup method, but can be encapsulated in different "feature" functions or rather - for better TS support - feature objects.

@yyx990803 - If you could just say, Vue will offer both APIs forever. Then all this will stop. The fear comes from the greatness of the options API possibly being lost at some point (doesn't matter when). It is what makes Vue so attractive to beginner, intermediate and maybe even early advanced programmers (if that is such a thing, but you get the point). You did make a great API and again, the fear is, you want to make it into something different, something where those who love Vue aren't seeing or even contemplating finding that same love with the new API. Those others aren't seeing the advantages of the new API and in fact, are seeing it as something "ugly". I too still feel that sentiment. It doesn't really look elegant to me either. But, I can overlook those "warts", as I do see the practical advantages.

If you could find a better more "elegant" way to have a function-based API, next to the options API, you'll probably be hitting the home run it should be. 😄 Your "programming art" just needs to be more "pretty" and less "abstract". 😉

Scott

yyx990803 commented 5 years ago

@martinsotirov I'd be curious to hear about "better ways to structure large modular codebases" when using the options-based API, especially how they allow you to avoid all these mentioned problems in a large enterprise codebase.

martinsotirov commented 5 years ago

@martinsotirov I'd be curious to hear about "better ways to structure large modular codebases" when using the options-based API, especially how they allow you to avoid all these mentioned problems in a large enterprise codebase.

Export shared functionality in a separate vanilla JS service class that you just import in every component that needs it. Much easier to track things later than trying to figure out where X or Y was inherited from.

Structuring code in a way that avoids mixin usage also forces you to rethink your architecture and discover potential problems, similar to how writing unit-testable code forces you to think about your code. And in many other cases it is better even to reimplement a nuanced version of some functionality instead of blindly following the DRY principle, if it helps keep clarity of the codebase better.

martpie commented 5 years ago

I don't have as much experience with Vue.js as I have with React.js so take what I am going to say with a pinch of salt. Though I absolutely like this proposal, I think one point has been really wrongly formulated.

One advantage of Vue.js is also one of the advantage of the Go language: you have "one way" of doing things, instead of 20 different ones. Whereas React falls short is this aspect: classes/function components, hooks/higher-order-components/decorators for example, are just solving the same problems in 2 or 3 different ways.

Yes, they are all supported and nothing is deprecated, but when opening a file, you will never know with what concepts the developer wrote this component (redux or providers? HoC or decorators? etc..), and the cognitive effort to switch from one to the other is not trivial.

Of course this could be enforced by team decisions, but still, the point remains.

Here is I think one of the key of the ranting going on: giving more tools/flexibility to the community also gives more tools to fracture how everyone will write Vue components.

I don't think there's a solution to this problem, but I just wanted to share that.

yyx990803 commented 5 years ago

@martinsotirov I think what you are doing is essentially side-stepping the options-based API and introducing a custom pattern, whereas the function-based API provides first-class affordance to such logic extraction. Reactivity inside service classes are also somewhat implicit (I assume you are returning class instances in data()?). In addition, note that your service class can only encapsulate pure state logic and won't be able to encapsulate logic that has to do with side effects (i.e. watchers or component lifecycle hooks), so there's a limitation on what type of logic you can extract.

martinsotirov commented 5 years ago

In addition, note that your service class won't be able to encapsulate logic that has to do with side effects (i.e. watchers or component lifecycle hooks), so there's a limitation on what type of logic you can extract.

If you get to the point of having to reuse things tightly bound to the component (side effects etc.), then you are doing something wrong and have to rethink your architecture or break up the component. That's the benefit of avoiding mixins, at least for me – it forces me to write simpler and better structured components.

Akryum commented 5 years ago

@martpie Vue is already providing a lot of different ways for doing the sames things, and it's been fine! For example:

Akryum commented 5 years ago

Export shared functionality in a separate vanilla JS service class that you just import in every component that needs it.

@martinsotirov Sounds a lot like what the Function API provides (but it does in a more Vue kind of way).

have to rethink your architecture or break up the component

The Function API allows you to easily do exactly that without having to create a lot of new components.

yyx990803 commented 5 years ago

@martinsotirov

If you get to the point of having to reuse things tightly bound to the component (side effects etc.), then you are doing something wrong and have to rethink your architecture or break up the component. That's the benefit of avoiding mixins, at least for me – it forces me to write simpler and better structured components.

The fact that you can cleanly extract and reuse side effects is the exact power of the function-based API. It's not just about reuse - but also code organization. There are certain things that just won't make sense as a separate component, nor would they fit in a service class, but can still be perfectly extracted into a function (e.g. data fetching on mount + refetch when props change).

jacekkarczmarczyk commented 5 years ago

@yyx990803 I agree about life cycle but why watchers? Can't I put watchers for example in the constructor or in some method (startWatching() { watch(() => this.foo, () => this.doSomething() })?

Also as this RFC became quite a PR (public relations, not pull request) failure maybe you can try using a backdoors to introduce it. What I mean is to provide an API for reactive data which is not related to the component API, so something that is already partially done (see observable in 2.6), I guess watchers and computeds are almost ready as well. And if this is something that people need they will start using it but nobody will oppose because it doesn't even try to deprecate anything, it's not related to component API etc. And when it will start to be widely used it will be much more natural to merge it into the component API. That could mean that the function API could be introduced later than in 3.0, maybe 3.X, maybe 4.0, but you'd have a time to see how the small features (observable, watchers) etc are used in the real world and have a chance to analyse it, maybe rethink API etc

Sounds a lot like what the Function API provides (but it does in a more Vue kind of way).

@Akryum that's the point - this interferes with the existing API. If it wasn't related to the component API there wouldn't be a threat that something will be backwards incompatible or deprecated.

yyx990803 commented 5 years ago

@jacekkarczmarczyk the RFC has already been updated to reflect exactly that: https://github.com/vuejs/rfcs/pull/42/commits/6fe6f7be06dd5982be3c57e248fcd66cd55748e0

jacekkarczmarczyk commented 5 years ago

@yyx990803 Not exactly, the current RFC still uses components as a main example of how to use it:

Expose logic-related component options via function-based APIs instead.

A new component option, setup() is introduced

One of the key aspects of the component API is how to encapsulate and reuse logic across multiple components.

What I meant is to decouple it completely from components and call it reactive data api

martinsotirov commented 5 years ago

@martinsotirov Sounds a lot like what the Function API provides (but it does in a more Vue kind of way).

You're thinking from the point of view of a framework developer, not product owner or CTO. From the business perspective, you want to have less things tightly coupled to the framework, not more. You want to be able to reuse at least parts of it when you port your product to framework Y next year.

yyx990803 commented 5 years ago

@jacekkarczmarczyk it was originally two separate RFCs (advanced reactivity + dynamic lifecycle injection). Unfortunately the ability of hooking into component lifecycle is a crucial part of the composition capabilities.

Akryum commented 5 years ago

@martinsotirov Maybe you shouldn't use a framework then? 😕 I'm confused because I would rather use the framework to its full potential to go faster, be more efficient and have better, more maintenable code than going halfway which can lead to unnecessary more complicated code, unnecessary custom solutions, spaghetti code, bikeshedding...

backbone87 commented 5 years ago

i never really got this "framework independence" stuff really. the benefits of (good) frameworks only comes to fruition when you embrace its paradigms and best practices fully. sure, not every framework is good for every use-case (edit: or every dev team), but that doesnt mean a framework should stop evolving. especially in the Web app world where you are so heavily constrained by the platform (browser) it makes no sense to argue for framework agnostic coding. i personally never saw a project swap frameworks without rewriting like 80% of its codebase anyway.

martinsotirov commented 5 years ago

@martinsotirov Maybe you shouldn't use a framework then? 😕 I'm confused because I would rather use the framework to its full potential to go faster, be more efficient and have better, more maintenable code than going halfway which can lead to unnecessary more complicated code, unnecessary custom solutions, spaghetti code, bikeshedding...

The solution to tight coupling is not to not use a framework. That's just naive.

i never really got this "framework independence" stuff really. the benefits of (good) frameworks only comes to fruition when you embrace its paradigms and best practices fully. sure, not every framework is good for every use-case (edit: or every dev team), but that doesnt mean a framework should stop evolving. especially in the Web app world where you are so heavily constrained by the platform (browser) it makes no sense to argue for framework agnostic coding. i personally never saw a project swap frameworks without rewriting like 80% of its codebase anyway.

Starting to get off topic here, but anyway - this is not about framework independence but about SOLID code. Even if you're not switching frameworks but just upgrading versions, it would be much easier if your core business logic is not tightly coupled to specific framework features.

I agree with you about the 80% code rewrite, what we're arguing here about is the 20%.

Am I old or are best practices and design patterns just generally not known among web developers nowadays?

mika76 commented 5 years ago

@backbone87 This is really one of those things which different people see differently. And I don't think the two sides would ever come together. One one hand is the camp that says "use the framework to its fullest potential" but the other one is "protect your business logic in separate modules so as not to rewrite later". Both views are totally valid and they both have pretty strong pros and cons too.

See the further up from from developing you go, the more you see how much all this rewriting costs companies. While they have to pay for someone to rewrite code that worked perfectly well in a previous framework those developers are NOT working on new features, or fixing important bugs for customers. They are basically making something work which was already working. Real big waste of money.

Now I'm not saying that there are not reasons to change things and to evolve, but the people that have to fork out money, or even worse, BEG their bosses/investors for money to do this are the ones that feel the pain.

@martinsotirov I think we're just getting old man 😆

Now please, this is just an explanation to @backbone87 's comment - I really do not want to open up another huge debate/talk about what's better. If there's one thing I think everyone should be aware of by now in these threads is how diverse a population is using Vue and how passionate people are about it. This is not a bad thing, but it makes evolution and change hard - always has and always will.

yyx990803 commented 5 years ago

Please stay on track and focus on the original RFC (on why it is or is not necessary).

tochoromero commented 5 years ago

I'm personally looking forward to trying this function API, I do see it's advantages and the problems it is solving. But the Object API would still be my preferred way of writing a good amount of simpler components.

I can also see components with the normal object API properties: life cycle hooks, data, computed properties and methods, coexisting with a setup function to bring in functionality that would normally be on a mixin. Is this mix and match approach going to be supported?

Akryum commented 5 years ago

Is this mix and match approach going to be supported

Yes.

jacekkarczmarczyk commented 5 years ago

it was originally two separate RFCs (advanced reactivity + dynamic lifecycle injection)

@yyx990803 and that's exactly what i'm talking about. Maybe the new RFC trying to add too much unknown to the well established API is what made people scared. Maybe if you implemented those 2 RFCs first people would have time to get familiar with new techniques and then, in the next version of Vue, maybe major, maybe minor (and after getting a lot feedback from real world use cases) you could add the function-based component API which would use already known patterns.

Despite appearances programmers (at least some) are humans and human manipulation techniques (such as introducing changes step by step instead of 1 big at a time, even if that leads to the same outcome) also could be successful :)

The only drawback is that it could delay the whole process. However since none of those 2 RFCs as I understand is not a breaking change then they could be introduced anytime, maybe even in 2.X, the point is that it would give people time and opportunity to understand new API and make the switch from advanced reactivity + dynamic lifecycle injection to function-based component API more natural

Side note - it's not about how to introduce any change/new feature, but problem with this RFC escalated enormously and i'm trying to find a way how to make the change eventually implemented with people's approval rather than with votes against

mika76 commented 5 years ago

Is this mix and match approach going to be supported

Yes.

I would actually love more details on this. I'm guessing there will be a lot of mixing while converting components so it's worth knowing more details.

Which of the sections would have preference? If I have a computed in the computed object and then a computed in the setup() method, which one can access which? What about duplicating, like maybe lifecycle methods/hooks...

tochoromero commented 5 years ago

@Akryum knowing that and with the changes to the RFC because of the user feedback, I'm 100% behind all of this.

Kudos for listening to the community and being willing to backpedal when it is granted. Feeling that we have a voice increased our love and commitment to Vue.

Keep up the good work!!!

tochoromero commented 5 years ago

@mika76 From what I got from the updated RFC, setup will be resolved first, so it would seem the computed in the object will override the one in setup.

mika76 commented 5 years ago

@tochoromero hmm I think it probably should be the other way around then, since converting these means some might be left in the computed object while you reference then in setup(). I'm pretty sure there won't be overriding though - like current vue it would probably fail if 2 things are named the same...

beeplin commented 5 years ago

@jacekkarczmarczyk would you please kindly take the TS users' interests into consideration when proposing to postpone such a vital feature for typing support? 😭

Just as Evan said above:

Type safety is also an important consideration - again, this is something many users wanted badly but may not appear valuable to those who do not use TS. That's understandable - but I think it's a bit selfish to claim that it's not solving any problems because the problems being solved does not affect you.

smolinari commented 5 years ago

FYI, any wording about deprecating the object API has been removed from the RFC!!!! Yes!

Thanks Vue Team!!! 😄

Scott

Aaron-Pool commented 5 years ago

@yyx990803, while I'm pro-RFC at this point, I think one thing you failed to respond to in the original message here is the idea of options API being symbolically deprecated, even if not literally deprecated, by documentation beginning to abandon the object API.

Do you have any insights in to how the Vue team will decide what syntax to use in official documentation example for Vue 3.x?

Akryum commented 5 years ago

@Aaron-Pool We are actively working on the new documentation for Vue 3.x so things are still in flux.

jacekkarczmarczyk commented 5 years ago

@beeplin actually I am quite happy TS user and I'm using TS without vue-class-component or similar tools, just plain Vue. I think not having a big community against the framework is also important

yyx990803 commented 5 years ago

@Aaron-Pool documentation will largely remain the same, with a new dedicated chapter on function-based API (just like a new feature), likely replacing the current content talking about component composition / mixins.

Aaron-Pool commented 5 years ago

@yyx990803 If I were you, from a politics perspective, I would massively emphasize what you just said to me and make it very prominent in the RFC.

Documentation is indicative of what parts of the API a dev teams cares about and will maintain, and I think if most people saw the setup function as something that would be portrayed as an "advanced use case" feature and treated similarly to the "render functions" section of the current documentation, it would alleviate more of the fears currently present than simply saying, "Ok, we'll definitely continue to support the object API, we promise, seriously". People need a tangible example of how this could be integrated into the Vue API without making other approaches seem secondary or antiquated. Using the "Render Functions & JSX" as an analogous example of an already existing alternate API within Vue that is additive, rather than subtractive, would be a great way to do so, imho.

modularcoder commented 5 years ago

Can't wait until a good TypeScript support! @yyx990803 thanks for the great discussion and your efforts! ✌️

Aferz commented 5 years ago

@yyx990803 I've read the update of the RFC and the plan to implement it first as a plugin.

How are we going to integrate this plugin with existing codebase? Will it be a separate build?

Is there any approximated date when we are going to be able to use this feature? I think Vue will benefit a lot if end-users like us can interact with this proposal as soon as possible just to check if this is the correct approach to solve the problems this RFC is attempting to fix. (I honestly think it is)

Thank you for your communication efforts throughout this (difficult) process. 👍

yyx990803 commented 5 years ago

@Aferz it will be a plugin just like Vue.use(VueFunctionAPI).

The code for it already exists in the Vue 3 branch, so my estimate is within a week. Edit: we are likely going to work with @liximomo and adopt his vue-function-api package, which you can already use right now!

Aferz commented 5 years ago

@yyx990803 Awesome! Thank you

paulm17 commented 5 years ago

@Akryum @yyx990803

Having a mix and match method is the best of both worlds for me. Having the ability to use the object-based API means that for smaller components I can have the same structure across the application. That said, when I build a more complex component or set of components then I can rely on the new Function-base component API. Additionally, for the future having typescript support natively is great as and when I decide to migrate over from JS.

I think from the community perspective this will be a huge win. For the designers, backend coders, and devs who didn't want to use React. Vue still gives them exactly what they want. For the devs that want to push to building complex apps and those who develop frameworks like Nuxt and Quasar and who develop plugins for devs like me to use. The newer API is there for them too.

Thanks for clarifying and I cannot wait for the release of 3 now!

smolinari commented 5 years ago

Oohh.. As a plugin? Like Vue 2.0 can then have a function-based API too? How awesome is that?

Great idea!!!

Scott

kenigbolo commented 5 years ago

After reading the first RFC (before all the edits) my feeling was “this should have been released as a plugin” first to get first hand feedback with regards to functionality and usage. This would have given a better overview of how the community viewed it. Ember JS does this very well and I’m glad Vue is picking this up.

As someone who teaches Vue and have spent a lot of time migrating legacy projects to Vue, I absolutely understand why there’s a strong case for the object API especially when it comes to ease of entry and understanding, however I also love the Function based API and honestly feel it should be a fairly straightforward transition (doesn’t always happen like that anyways) and I feel there can be a reasonable coexistence (I teach using string templates before showing students how to use single file components) between both approaches however there’s already a huge Us vs Them (Object/Function based) in the community right now and I think I’ve heard the phrases “a large number”, “so many”, “a lot of” etc. Maybe it’ll be great to give a reasonable percentage of those using typescript who are eager for this to come into play (I for example) so it is clear where this is coming from

I’d really love us to let this rest and move on. Never ever have I seen the Vue community become so divided and toxic, we’re beginning to look more like the “other” community and it is really not nice. Thanks for all the hardwork the core team have put into making Vue as awesome as it is. As we move forward in the community, I hope this episode is one we can learn from

abalashov commented 5 years ago

@martinsotirov @yyx990803 I agree with Martin that there are already plenty of ways to generalise and abstract common code and logic out of the component, and, indeed, make heavy use of my own modules and services that are just imported everywhere. I agree that this is sometimes a pain as the modules don't have access to the state or innards of the Vue component structure, though, but hardly an insurmountable one. For truly common logic, mix-ins have worked very well for me, and the ability to use multiple ones is a blessing, and I think mix-ins can take one sufficiently far.

Otherwise, my tendency is to put most data-related plumbing into Vuex store actions. I grant that this approach is not without controversy, as it results mostly in mutation of state that is linked to a particular component (I make heavy use of the store pattern where there are many "screen"-oriented mutation contexts), rather than truly global and shared state, which is the intent of the store pattern.

However, it has two virtues:

All of this sounds a lot like what @yyx990803 said above:

"I think what you are doing is essentially side-stepping the options-based API and introducing a custom pattern"

I am not oblivious to that, and can appreciate the way that the function API aims to generalise solutions to this problem in a more native and first-class way. I really can. I also understand that change is inevitable and necessary for progress. I just think there are other drawbacks, even to an "additive" API change, that are way, way more important than that. A body of knowledge and practices evolves around this stuff, and people devise adaptations. That is an organic process and takes time; it takes time for the experience and the folklore around the framework to diffuse, and it can't be hurried along, and can be easily disrupted by crises of faith, the appearance of caprice, or offences against the mercurial sensibilities of potential everyday users and newbies.

This is true even if there are no plans to deprecate the object API, ever -- there's Deprecation and there's deprecation, which is what I was trying to tease out in my original comment, and I think that point continues to get the short shrift in this discussion as if it can be simply waved away with the notion that the function API is additive and the object API isn't going away. No, it's not going away, but you're changing the canon. Zooming out from relatively narrow technical preoccupations, that's a vitally important artery that gives the organism of frameworks and tools life in the real world. It weighs heavily into decisions to use Vue, for projects big and small. For better and for worse, Vue is the way it is, and its unwavering constancy, sharply contrasting against the vicissitudes of the byzantine and overcomplicated JS world, has been front and centre. There's valuable capital being lost here.

likern commented 5 years ago

I've created proposal of new Scoped Mixin API, outlined in this issue https://github.com/vuejs/rfcs/issues/60. Could you please look at and provide feedback and your feeling about it?

Ju66ernaut commented 5 years ago

When can we try it out?

keithn commented 5 years ago

this "Denying some users' opportunity to solve their problems with a better abstraction due to the aesthetics preference of some other users seems like the wrong trade-off to make." feels like a very risky statement. It feels like it's loaded with bias. I would guess aesthetic preference is one of the biggest reasons people pick particular frameworks. Your statement is akin to "Denying people more power just because you like this easy and simple to use 'thing' seems like the wrong tradeoff". This doesn't means it isn't the right thing to do, but this line of reasoning seems problematic. Software History is littered with frameworks who try to scale up to handle larger projects while destroying simplicity that it started with. I see a lot of people going "but this is addititive, you can just keep doing the same thing". But much like UIs, if you keep adding things, it doesn't necessarily preserve the "feel", it can destroy it. If the additions cause the ecosystem to warp to something people are not (especially newer people) attracted to, then this would seem to be the wrong tradeoff. I'm not saying it is, and I'm not sure what the impact will be, but I'm worried that key people SEEM to be very quickly defending the new way as the "right" thing. I would advise caution if you can't delight the "normal" users with the changes. Aesthetics are important.