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

Vue 3.0 full state with classes and annotations. #459

Closed
AliLozano opened this issue Sep 25, 2020 · 4 comments
Closed

Vue 3.0 full state with classes and annotations. #459

AliLozano opened this issue Sep 25, 2020 · 4 comments

Comments

@AliLozano
Copy link

AliLozano commented Sep 25, 2020

A month ago I was working in a concept to use Vue 3.0 / Composition API with Statefull classes, the result of this work is here:

https://codesandbox.io/s/test-vue-class-n0iuf?file=/src/components/HelloWorld.vue

  1. It works with annotations, I implement 4 annotations @watch @prop @Inject @context
  2. It have a vanilla JS Class without inheritance of Vue.
  3. It uses setup method with full state.
  4. It have getters/setters as computed properties
  5. It also exposes static properties, static getters and static methods.
  6. I think that it could be full safe typed (although my example is still missing many type declarations 🙄).
  7. It is small 🤭
import { Component, Inject, Prop, Context, Watch } from "./vue-class";

@Component()
export default class MyComponent {
  static VERSION = "1.2";

  @Inject()
  name: string = "";

  @Prop(String)
  msg: string;

  @Context()
  emit: any;

  newItem = "";

  items = ["Hello", "World"];

  setup() {
    // this is a reactive component :)
    console.log(this.msg);
  }

  @Watch("counter")
  watchCounter() {
    console.log("watch counter.. ");
    this.emit("hiFather");
  }

  get counter() {
    return this.items && this.items.length;
  }

  add() {
    this.items.push(this.newItem);
  }

  static uppercase(s: string) {
    return s && s.toUpperCase();
  }
  static get VERSION_NUMBER() {
    return parseFloat(this.VERSION) * 10;
  }
}
@ktsn
Copy link
Member

ktsn commented Sep 27, 2020

Thanks for posting your idea but it looks too broad and vague to make changes for Vue Class Component. As stated in contribution guideline, you should mention use cases or problems you want to solve for each feature request to verify if the feature is really worth adding and benefits the most of people.

As for the next major version, there are threads to discuss particular use cases and you can comment in the threads. You also can create a new issue if your use case is not covered in the existing thread for a feature request. Please make sure to make your issue precise and specific with a concrete use case to solve. Thank you.

@ktsn ktsn closed this as completed Sep 27, 2020
@AliLozano
Copy link
Author

AliLozano commented Sep 27, 2020

@ktsn Sorry If I posted this as an all. I published this no to make a pull request or change the current code, if not then to show another perspective of Vue with classes and showing that it is possible.

When I saw Vue 3.0 and Composition API by first time, I love it, because It separate the magic reactiviness with controllers(components), and now we can use reactiveness independently from components. And for example I can make a reactive service(test it as simple service class not as vue component) and only import it in a setup function exposing what is important in the view.

I was very unhappy when Vue decided to don't give support to classes, but after I see that it was the best choose because give us a lot of flexibility to make many architectures on the top of vue.

I came to see if the vue classes is already supported but I found that is not already and I think is loosing some of simplicity of what Vue classes was. For example I think that it is unnecessary use a Vue class in an attempt to replicate Vue 2.0 and by consequence looking for ways to type $props and $emit (#447), these things could be injected and typed. O this for data variables using reactive (#416) increasing boilerplate code when It could be reactive transparently.

Vue 3.0 and Composition API is very simple, we have to try to keep it.

I can't publish this in many issues because is all in one and there are not a problem yet, I only wanted give us another perspective (functional and showing you that is possible) of how we can get this more simple than was before.

@ktsn
Copy link
Member

ktsn commented Sep 28, 2020

Thank you for explaining your intention. I understand you shared it to show another perspective of class component.

But please understand we have to cover the various use cases of it. For example, TypeScript support is a must because it is the original motivation of this library. I know we can create class component without extending Vue base class but it loses type support.

I'm asking concrete use case or problems because we cannot discuss properly without them. We could make our API as simple (or short) as possible but we may lose another benefit (e.g. TypeScript support) at the same moment. To cover as much use case as possible, we have to clarify what the fundamental demand is.

@AliLozano
Copy link
Author

@ktsn but I didn't remove Typescript support in this concept.. the user can declare for example

  • @Inject myservice: ServiceFoo
  • @Context emit: EmitFunction and then use this.emit like setup function
  • @Prop(String) param: string for string props

It is more like a Dependency injection Pattern.

Maybe I omitted some TypeScript declarations in my example, but it was because it is only a concept.

And for this result I thought/tested another ways for do this simple, for example:

Put constructor like setup, constructor(props: Prop, context: Context) I loved if it could because it could be naturally to any object programmer developer, but this is imposible because the object can't be reactive in the constructor, at least we use reactive of composition api in every data declared, but It could be like setup function, and could be more confused.

Another thing that I already think, is handle it like interface class A implements Component<Props> and then force to implement a function called setup(props: Props, context: Context) like functions, and we can extract everything that we need and put it in a fields manually, for each prop or each injection, or we can use this.$props = props. Anyway we have to declarate the interface of Props and after the assignment.

Another way is to assign automatically this.$props = props with inherit or transparently to the developer before setup call, but then we have to do "this.$prop.propA" accessing the propA in the second level and another objection is that we have 3 types of data in the component "Data, Props and Injects" why we have to handle it of different ways?, props declaring automatically, injections explicit in a setup and data in fields.. I think is some messed.

In any case, if we focus in leave this as a vanilla class with a setup function, the user could decide to not use annotations and make things like this:

export class Component {
   msg: string = '';

   setup(props: Props, context: Context) {
       this.msg = props.msg
       // anything like setup functions of Vue 3
   }
}

And Vue Classes will be aligned to Vue 3.

If you need to talk about this, please write me in discord, my user is the same that here @alilozanoc.

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