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

Constant component data #6004

Closed
kay999 opened this issue Jun 30, 2017 · 14 comments
Closed

Constant component data #6004

kay999 opened this issue Jun 30, 2017 · 14 comments

Comments

@kay999
Copy link

kay999 commented Jun 30, 2017

What problem does this feature solve?

The ability to define constant data which is accessible in templates/code the same way as data defined in 'data'.

In the moment constant data needs to made available via "data". While it's possible to freeze objects, it looks ugly and uses a certain implementation which may change in the future. So for

  • documentation/readability/better communication of intent
  • allow performance optimizations
  • (maybe) detect unintended changes

Vue should implement a way to explicitly define constant data.

This could be implemented quick and dirty by simply by mixing 'constants' into 'data' but without making the fields reactive.This could be also implemented via plugin, but I think it's important enough to be part of the core.

What does the proposed API look like?

In a .vue file for example:

export default {
    constants:{
        field1: value1, 
        ...
    }
}
@Austio
Copy link

Austio commented Jun 30, 2017

To me, I think that the constantness of a variable would be best conveyed by defining the data as UPPER_CASE instead of expanding the api.

What performance optimizations would this allow that are not realized using reactive get/set.

@LinusBorg
Copy link
Member

Any property that you define on the instance is available in the template. So you can achieve the desired result with a simple created() hook.

created () {
this.yourconstant = "whatever"
}

@kay999
Copy link
Author

kay999 commented Jun 30, 2017

While those would work, IMO it's still not as clear as having an explicit way of declaring them.

And UPPER_CASE could only be used if the coding style allows it.

@LinusBorg
Copy link
Member

The proposed syntax is not shorter than what I showed, and generally, you don't need non-reactive data in the template very often.

So I do think a bit of "cleanness" justifies a new API. We try to keep the API as slim as possible, so new API's need a benefit beyond cosmetics, imho.

@kay999
Copy link
Author

kay999 commented Jun 30, 2017

Hm, in #5932 your reasoning was, I quote "We think it is better to explicitly define your data strcuture, because then the code of your component is more self-explanatory.". But now for a feature which is clearly based on this reasoning, you "need a benefit beyond cosmetics".

I think that this feature would be a useful addition to the API and to use it right now, I've created it as a simple plugin named 'vue-constants'.

@kay999
Copy link
Author

kay999 commented Jun 30, 2017

Also using 'create' has the disadvantage that if you already use it, your constant-declarations are "buried" under other code. If we go by the concept of "explicitly define data structures" that that's just the wrong way to do it.

Also: If you write for example:

created() {
   this.someOptions = { ... }
}

the object in "someOptions" is created for every instance of the component. While memory is cheap today, it still means wasting resources. Of course you can pull it out by declaring it a module local constant, but that requires even more code. And because I still think Vue should make live easier and not requiring to unnecessary boilerplate code, I don't find this optimal.

@posva
Copy link
Member

posva commented Jun 30, 2017

Thanks for creating a plugin for that 🙂 . Because we don't want to bloat the api (and add more code and size to Vue) for features that can already be achieved (unless the benefits are worth the cost), we will pass on this. Also, as you demonstrated, it can be achieved in user land if anyone wants that syntax (which is quite subjective).

Personally I'd even keep constants out of the component, into a different file:

// constants.js
export const FOO = 'foo'
import { FOO } from './constant'

export default {
      created () {
               // Use FOO as you need
     }
}

because they're constants, there's no need to add them to components. That way you keep them in one place as well and just use javascript.

@posva posva closed this as completed Jun 30, 2017
@LinusBorg
Copy link
Member

LinusBorg commented Jun 30, 2017

Hm, in #5932 your reasoning was, I quote "We think it is better to explicitly define your data strcuture, because then the code of your component is more self-explanatory.". But now for a feature which is clearly based on this reasoning, you "need a benefit beyond cosmetics".

You're still seem to be misunderstanding my argument in #5932. I argued that all data that is being used in the template should be initialized in the compoent, never in the template.

In the current issue we are not arguing about component vs. template, we are arguing about introducing a new API to the component.

Those are two very different arguments and I won't mix them up.

I think that this feature would be a useful addition to the API and to use it right now, I've created it as a simple plugin named 'vue-constants'.

I don't doubt that it is useful to you as well other people surely, and I fully respect that. However, we as maintainers have to judge wether it's useful enough to a sufficiently large percentage of our users to justify its introduction into the codebase.

I doubt this, judging from my personal experience and the kind of questions I answer day in, day out on our forum, SO, Discord and other places. But other team members might agree with you over me, which is why this issue is still open to discussion, I'm just giving my opinon.

Also using 'create' has the disadvantage that if you already use it, your constant-declarations are "buried" under other code. If we go by the concept of "explicitly define data structures" that that's just the wrong way to do it.

I can agree to a certain degree, but once again am doubting that the use case for such "constants" is prevalent enough to warrant a new API.

My argument is not that this is not useful. It's that it's not sufficiently more useful, compared to the solutions possible with the current API, to justify adding another API that has to be documented, explained, tested, argued for ("Blog post: When should I use data and when constants? 5 simple rules!"), can could possibly require a breaking change in future versions. Every new API is introcuces a bit of technical debt, so adding one should have a good use case.

So In this case, while yes, introducing such "constants" in created is not 100% clean, I simply doubt that they are required often enough to justify a new API, so I argue that we should accept the trade-off of using creted() for the few instances that this is required. People who rather want an API for this can use your plugin if you publish it - that's what plugins are for :)

@posva: You are right about declaring them outside of the component to prevent re-inialization (we would do the same for reactive data that we can share across compoents). But he is specifically talking about using data in templates that doesn't have to be reactive. Those would have to exist on the instance as properties in some form.

@posva
Copy link
Member

posva commented Jun 30, 2017

@posva: You are right about declaring them outside of the component to prevent re-inialization (we would do the same for reactive data that we can share across compoents). But he is specifically talking about using data in templates that doesn't have to be reactive. Those would have to exist on the instance as properties in some form.

IMO they don't need to exist there, but if you really want, you can use the created thing you did, or use a computed property as well:

computed: {
    FOO: () => 'FOO'
}

But I think you also agree that this is not enough to add more code and a new API to Vue 🙂

@kay999
Copy link
Author

kay999 commented Jun 30, 2017

This discussion makes it clear why it would fit better in the APIs because it would promote a standard way of doing things instead of having people use data, computed properties, code in created() etc.

Constant data is an important part of every code-base and so I still think that Vue should support it instead of promoting various less readable idioms to do it.

@posva
Copy link
Member

posva commented Jun 30, 2017

That's your personal opinion 🙂 Other people will think that's complicating things for no real benefit because they can write just javascript
But the reality is we must be really careful about incrementing the size of Vue with new features and adding a constants property, which is a subjective choice, is possible with an user-land plugin. So we prefer to leave it that way. Thanks for the suggestion, thought!

@yyx990803
Copy link
Member

yyx990803 commented Jul 1, 2017

The reasoning for not adding the feature has been well explained - it's trivial to write a plugin for this purpose. But I thought I'd add a comment regarding the general philosophy for "new features" in Vue.

At this stage, we already have a decently sized API surface (I'd say "bigger than I wanted" in my opinion), and the size of the lib has grown 20% since the 2.0 release. We should now really try to keep the API surface and the size small. So in general we take a somewhat "conservative" stance for new features:

  • If a proposed API's value is subjective, cosmetic or stylistic, we will pass;

  • If a proposed API's functionality can be cleanly implemented in userland without hacks, we will pass unless it's strongly needed by a significant majority of the user base (i.e. we've seen it been raised/discussed multiple times).

  • If a proposed API's added value cannot justify the added code size / complexity / maintenance cost, we will pass. For example, if it requires a significant chunk of code or internal changes to deal with a very niche use case, we will need to think twice. This rule doesn't affect fixes that are about "correctness", though.

/cc @vuejs/collaborators

@kay999
Copy link
Author

kay999 commented Jul 1, 2017

In principle I totally agree with you. But it's quite subjective what is considered "cosmetic" or "stylistic". In this case I consider it quite fundamental especially considering that Vue seems to intend to promote certain coding styles as LinusBorg wrote in another issue.

Constant declarations are part of every modern programming language and using them instead of mutable data as often as possible is considered fundamental in modern programming. Creating them as non-constant data (via data()), computed properties or some non-obvious initialisation code is not a sensible solution to the problem.

And while using plugins is often possible, it's also possible for lots of things which are part of the Vue API. If we're talking about features only few people need, or features where no single "right" implementation exits (like i18n, vuex, routing etc), yes, a plugin is the better option. But everybody need constant fields somewhere in his code and it's also quite straight forward and needs only a few lines to implement so it won't require a "significant chunk of code". And using a plugin always requires additional work and you also need to know that a plugin exists.

@blake-newman
Copy link
Member

You can do many things to solve this without the need of Vue internals..

Object.freeze, created hook and creating a plugin. This is not a feature that needs to be integrated into the core itself. It however could be documented, please feel free to create an issue there or a PR.

@vuejs vuejs locked and limited conversation to collaborators Jul 1, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants