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

[Abandoned] Class API proposal #17

Closed
wants to merge 10 commits into from
Closed

[Abandoned] Class API proposal #17

wants to merge 10 commits into from

Conversation

@yyx990803
Copy link
Member

@yyx990803 yyx990803 commented Feb 27, 2019

Rendered

Update: this proposal has been dropped. Read why here.

@ashokgelal
Copy link

@ashokgelal ashokgelal commented Feb 27, 2019

What about local component registration?

Also, I might start using TypeScript after this :)

@yyx990803
Copy link
Member Author

@yyx990803 yyx990803 commented Feb 27, 2019

@ashokgelal any existing option can be mapped to a static property:

class Foo extends Vue {
  static components = {
    Bar,
    Baz
  }
}
@ashokgelal
Copy link

@ashokgelal ashokgelal commented Feb 27, 2019

@yyx990803 That's what I thought. And does that mean with Typescript it would be something like @components({ ... })

It'd be nice to mention local component registration in the RFC as well.

@crutchcorn
Copy link

@crutchcorn crutchcorn commented Feb 27, 2019

In regards to using [[Set]], I could easily see this being a large point of confusion, especially for those coming from other front-end component libraries where this behavior does not cause problems. Might it be a good idea to mention a warning of some kind in the parent Vue class if this is done? I'm not even sure that's the right way to go but I'm moreover noting that I personally would have had a fair amount of confusion had not read this RFC previously

@yyx990803
Copy link
Member Author

@yyx990803 yyx990803 commented Feb 27, 2019

@ashokgelal no, you do that the same way in TypeScript. @prop is the only decorator that we currently plan to include (for the reason discussed in the decorators section)

@crutchcorn the note on [[Set]] vs [[Define]] is just there for those who are interested in the details (mostly library authors). In practice it doesn't really "cause problems" of any kind - users don't need to be aware of this.

@CyberAP
Copy link
Contributor

@CyberAP CyberAP commented Feb 27, 2019

How would inject/provide look like?

@jaesung2061
Copy link

@jaesung2061 jaesung2061 commented Feb 27, 2019

Would we need to us TS if we wanted prop validation?

Edit: Nevermind, dumb question.

@aparajita
Copy link

@aparajita aparajita commented Feb 27, 2019

Would this work in the script section of an SFC? Don't especially want to give up all of the advantages of having a separate <template> section vs. a string.

@yyx990803
Copy link
Member Author

@yyx990803 yyx990803 commented Feb 28, 2019

@aparajita of course!

@aparajita
Copy link

@aparajita aparajita commented Feb 28, 2019

@yyx990803 Well, your first "basic usage" example uses a template string, and none of the examples show usage within an SFC, so I hope you can see why I was wondering. It's obvious to you, but not necessarily to everyone else. The more explicit you are in docs, the better.

In any case, I would suggest that the overwhelming "basic usage" will be in an SFC, not using a template string, and perhaps the first example should be changed accordingly.

@twaite
Copy link

@twaite twaite commented Feb 28, 2019

So it sounds like based on the Alternatives section that you're going to be using decorators, is there any way we could something like this to make it simpler to keep our interfaces in one spot without generics?

interface propType {
  numeric: number,
  text: string,
}

class MyComponent extends Vue {
  @props()
  props: propType = {
    numeric: 0,
    text: 'string',
  }

  created() {
    this.msg
  }
}

I guess this doesn't solve the issue of validators. But I wish that I could create one interface for props and one for my data. that keeps the different concerns isolated.

@sombriks
Copy link

@sombriks sombriks commented Feb 28, 2019

as long as the old object notation remains valid, this is perfect.

@brianjohnsonsr
Copy link

@brianjohnsonsr brianjohnsonsr commented Feb 28, 2019

I'm sold on it, given the last paragraph in the adoption strategy. As long as the vue-class-component API can remain the same while the implementation is improved, I see no issues.

@Justineo
Copy link
Member

@Justineo Justineo commented Feb 28, 2019

Should component inheritance be covered in the RFC? Like how one component extends another one, possibly with mixins included at the same time.

@634750802
Copy link

@634750802 634750802 commented Feb 28, 2019

Hi, I have some questions:

  1. How could I declare a non-observable field?
  2. How to create a method that has the same name with reserved name?

For question 1, maybe vue can provide a decorator @Observable() or @NonObservable().

For question 2, maybe vue can provide some special constant key to declare a hook. For example:

import Vue, { Options, Lifecycles } from 'vue'

class Component extends Vue {

    [Options.provide] () {
        return { bar: 'foo' }
    }

    [Options.data] () {
        return { foo: 'bar' }
    }

    [Lifecycles.created] () { 
        // ... 
    }

}
@caridy
Copy link

@caridy caridy commented Feb 28, 2019

Note about mixins, we are trying to align multiple frameworks to provide sugar for the current stage 1 proposal for mixins, and so far, people seems to like it. Have you consider using:

class Foo extends mix(Bar).with(X, Y) { 
    ...
}

The implementation of that utility is quite simple, and in maps exactly to the syntax that we are proposal for the language:

class MixinBuilder {
    constructor(superclass) {
        this.superclass = superclass;
    }

    // This is a method of the class, not a "with" statement
    with(...mixins) {
        return mixins.reduce((c, mixin) => mixin(c), this.superclass);
    }
}

export default superclass => new MixinBuilder(superclass);
@alexsasharegan
Copy link

@alexsasharegan alexsasharegan commented Feb 28, 2019

What distinguishes a method from a filter?

@GlebkaF
Copy link

@GlebkaF GlebkaF commented Feb 28, 2019

What about checking prop type in template?
It would be great if Vue could leverage typescript to check prop types :) Any plans?

@michaelolof
Copy link

@michaelolof michaelolof commented Feb 28, 2019

Guessing watchers will also be defined via decorators.

@zuoez02
Copy link

@zuoez02 zuoez02 commented Feb 28, 2019

Which will be called first? constructor() or beforeCreate()? Currently beforeCreate will be called first.

import Vue from 'vue';
import Component from 'vue-class-component';

@Component
class App extends Vue {
  constructor() {
    super();
    console.log('constructor');
  }

  beforeCreate() {
    console.log('beforeCreate');
  }

  created() {
    console.log('created');
  }
}

new App();

// beforeCreate
// constructor
// created

image

@zaun
Copy link

@zaun zaun commented Feb 28, 2019

Could you remove the need the prop decorator if props were only available via this.$props? I don’t see a need for them to be directly on this like a component’s data is. In fact it makes it clear your accessing a prop rather than data.

Also, how do you go about defining what the types are for this.$refs? Im having to cast them currently and would like to avoid that in the future if at all possible. Ideally if you try to access a $refs property that’s not setup with a ref attribute in the template it should error.

@donnysim
Copy link

@donnysim donnysim commented Feb 28, 2019

I also like the idea of only having this.$props and this.$data, no direct access on this. This also makes a clear distinction that this.isLoggedIn is a computed property, and this.success() is a class methods instead of:

data() {
  return {
    success: () => { /* ... */},
  };
},

or

props: {
  success: {
    type: Function,
  },
},

being accessed through this.success() where prop, data and class method can exist with the same name.

There also is a need for non-reactive properties, like storing Popper instance, without having it trigger useless updates.

@rickyruiz
Copy link

@rickyruiz rickyruiz commented Feb 28, 2019

The RFC does not mention anything about Vue.extend explicitly. As a TypeScript user, I've never needed vue-class-component.

  • Using classes will be the recommended option for TypeScript users?
  • Are there going to be any disadvantages if I keep using Vue.extend instead of classes?
@zuoez02
Copy link

@zuoez02 zuoez02 commented Feb 28, 2019

@rickyruiz This is Class API proposal

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

The Composition API is so elegant to me, as we can write so simple, modular, easily typable code with just variables and functions. No need for thousands of concepts or other bloat. And it's not even enforcing functional programming (nor directly related to it).

Benefits (and drawbacks) of the Composition API and its superiority over the Class API has been already discussed at length. No Class API will be added to core for all the reasons we have already openly discussed. It will still be possible in userland though, so if you still want to use classes despite the drawbacks, you will be able to.

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

Also, the World would be better without this imho. More explicit code with simple variable scopes!

@davidbusuttil
Copy link

@davidbusuttil davidbusuttil commented Dec 12, 2019

I understand, however the benefits of Typescript cannot be exhausted...

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

The Composition API works better with Typescript than the Class API...

@davidbusuttil
Copy link

@davidbusuttil davidbusuttil commented Dec 12, 2019

In the paradigm of Vue, yes.

In the paradigm of Typescript, no.

@davidbusuttil
Copy link

@davidbusuttil davidbusuttil commented Dec 12, 2019

Take this example available on the API reference.

import { createComponent } from 'vue'

export default createComponent({
  props: {
    foo: String
  },
  setup(props) {
    props.foo // <- type: string
  }
})

In order to use a Typescript Interface or Type, you need to hack it as explained in this article.

Now I understand the whole issue why Vue is dropping experimental decorators... And I understand Vue cannot make a solution for everyone :)

I'm just saying, from where I stand, it is a pity, since those are my requirements. I would love to move to Vue, however I feel more comfortable with a Class based syntax.

We can agree to disagree.

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

The link you provided isn't using the Composition API 😕

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

In the paradigm of Vue, yes.

Good!

In the paradigm of Typescript, no.

What is the paradigm of Typescript? Is good Typescript only with classes?

@davidbusuttil
Copy link

@davidbusuttil davidbusuttil commented Dec 12, 2019

The link you provided isn't using the Composition API 😕

Sorry my mistake, I updated the comment.

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

Sorry my mistake, I updated the comment.

It still isn't 😸

@davidbusuttil
Copy link

@davidbusuttil davidbusuttil commented Dec 12, 2019

The link you provided isn't using the Composition API 😕

Sorry my mistake, I updated the comment.

From my understanding, props will remain unchanged in Vue 3?

Therefore, the example I provided still stands.

As for the setup method, take this line of code.

const obj = reactive({ count: 0 })

At which point is the Type of obj being inferred?

@shentao
Copy link
Member

@shentao shentao commented Dec 12, 2019

@davidbusuttil https://vue-composition-api-rfc.netlify.com/api.html#setup scroll down to the typing section of props.
Same here: https://vue-composition-api-rfc.netlify.com/api.html#ref for reactive properties.

The Composition API seems to be very well received. Literally everyone I know that tried it – loved it. Maybe take it for a spin with the @vue/composition-api plugin? Or try running Vue 3.0 locally since it’s written in TypeScript and should give you an even better typing experience.

And if you still dislike it, why not just stick with Angular?

@Akryum
Copy link
Member

@Akryum Akryum commented Dec 12, 2019

From my understanding, props will remain unchanged in Vue 3?

The point is about using the Composition API to get better type inference, and you link to an article that is not using it...

At which point is the Type of obj being inferred?

In your example, obj is infered as { count: number }:

image (1)

@kabaluyot
Copy link

@kabaluyot kabaluyot commented Feb 25, 2020

Will vue-class-component still be officially maintained in Vue 3.0?

@smolinari
Copy link
Contributor

@smolinari smolinari commented Feb 25, 2020

@kabaluyot - From what has been said in the past by the Vue team, yes. But, you'll hopefully learn at some point that it is the lesser pragmatic use of Vue. 😀

Scott

@jaytonic
Copy link

@jaytonic jaytonic commented May 6, 2020

Really sad about this, the class approach with decorator was so easy to read, no more weird "declare an object with a property named computed that contains a method to just have something that is implemented in base javascript with getters :(.

I was really hyped by this until I found out it was going to be dropped. It would have been perfect for smaller projects than my angular ones.

@pikax
Copy link
Member

@pikax pikax commented May 6, 2020

There will be support through vue-class-component

@jaytonic
Copy link

@jaytonic jaytonic commented May 6, 2020

There will be support through vue-class-component

Still mean that this will not be present in web courses, not in base documentation, less community :(
I cannot understand this choice. This approach was doing a lot of the composition api is doing be in a more OOP way.

Wish they kept that(and added service injections for stuff like ionic)

@kabaluyot
Copy link

@kabaluyot kabaluyot commented May 6, 2020

Actually the main thing that im hoping tha the vue-class-component still be supported officially is the transition when the time comes when the composition API matures and had advantages in real application compared to class components.

Also, the class component will have a bridge to composition APIs. We have assurance with the vue-class-component author: vuejs/vue-class-component#402

@alexey2baranov
Copy link

@alexey2baranov alexey2baranov commented Jun 6, 2020

Sorry if my question duplicates others, but I really want to ask Evan.

What was the main reason when he was preferring the Functional API over the Class API. Has the Functional API won because of current JS/TS limitations (lack of JS decorators, TS typing limitations, etc... ) or because of functional style is more awesome?

BTW: could't open "read why" link on top

@smolinari
Copy link
Contributor

@smolinari smolinari commented Jun 6, 2020

@John0King
Copy link

@John0King John0King commented Jun 8, 2020

this is nothing wrong in Typescript, and it just not work for previous "re-project-this" base transformer and I previous write a prototype of typescript runtime for wechat-mini-programe and the this is the real this, instead of the hacker one

https://github.com/John0King/typed-we-app/blob/705b2a128de3e846fa31c5fc620005aa62f5a72b/runtime/Runtime.ts#L181-L241

from what I understand,

export default {  // this is a object  which mean this is an instance of class,  only the class is Object
    setup() {
      const state = reactive({
        count: 0,
        double: computed(() => state.count * 2), 
      })

      function increment() {
        state.count++
      }

      return {  //  again  this is another instance of Object, 
        state,
        increment,
      }
    },
  }

let me transform you to typescript class word

class MyConfigurate{
    state : any =  reactive({
        count: 0,
        double: computed(() => this.state.count * 2), 
      }) ;// sorry I do not know want type it is, so I'm using AnyScript 🤣
     increment() : void {
        this.state.count++
      } // if this `this` is the problem, then use 
      increment2:()=>void = ()=>{
        this.state.count++;
     }
}
class MyComponent{
    setup() {
         return new MyConfigurate();
    }
}

export default new MyComponent();

so you can see, there are nothing wrong with this right ?
the only difference is that the prototype of MyConfigurate and MyCompont is not same as Object, but I do not think the class.prototype is the blocker here.

and my prototype being abandoned previously because it can not find a proper time to attach the projected this , you can see I attach the this from the begin of the Page lifetime OnLoad , but it also too late, so I doing lot of the work to delay the property initialization after I attach to the this .
but it doen't has any issue for Vue 3, because Vue3's root Object (eg. MyComponent) has a setup method , and it indeed has two level of object 😀


after use the decorator it should be look like this

@Component()
export default class Hellowork{
    count = 0;
    get double(){
        return this.count * 2
    }
    increment() : void {
        this.state.count++
      } 
    // if use some reused function
   position :{ x:number, y:number } = useMousePosition() 
    // or
    constructor()
   {
      var { x, y } = useMousePosition();
     this.x = x;
      this.y = y;
    }
    x:number;
    y:number;

    //inject

   @inject(()=>useStore())
    store:any!;
}

the Component decorator do 2 things,

  1. it wrap this class with a root object with setup function
  2. it apply necessary change to this class and return in the setup function
@sreenaths
Copy link

@sreenaths sreenaths commented Mar 6, 2021

[composition class] Component setup using ES6 class works out of the box in Vue 3, why not officially support it!
discussions @ #276

@hex11o hex11o mentioned this pull request Apr 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet