From 36cf5665ab8d885ab797fb44211c15e5fb05e32b Mon Sep 17 00:00:00 2001 From: pikax Date: Fri, 12 Mar 2021 10:01:18 +0000 Subject: [PATCH 1/3] no props component --- active-rfcs/0000-no-props-component.md | 88 ++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 active-rfcs/0000-no-props-component.md diff --git a/active-rfcs/0000-no-props-component.md b/active-rfcs/0000-no-props-component.md new file mode 100644 index 00000000..18f1fb0f --- /dev/null +++ b/active-rfcs/0000-no-props-component.md @@ -0,0 +1,88 @@ +- Start Date: 2021-03-12 +- Target Major Version: 3.x +- Reference Issues: None +- Implementation PR: None + +# Summary + +Make `attrs` to behave as `props` to allow a similar interface as `React` + +# Basic example + +```ts +import { defineComponent } from 'vue' + +interface CompProps { + name: string + age: number +} + +// VCA +defineComponent( + noProps: true, + setup(props) { + props.name // string + props.age // number + } +) + +// VOA +defineComponent({ + noProps: true, + mounted(){ + this.name // string + this.age // number + } +}) + + +// No typescript +// in this case `vm` will have a `Record` to allow usage of any prop +defineComponent({ + noProps: true, + mounted(){ + this.name // no typing + } +}) +``` + +# Motivation + +The main motivation is lowering the bar on the people coming from `React` sometimes, the props runtime checks are not needed, because the developer will rely on the typescript typeschecking. + +# Detailed design + +In `vue` `props` and `attrs` are different, to be able to achieve this design, `attrs` will behave like props. +When `noProps:true` the component: + +- Will have implicitly `inheritAttrs:false`. +- `$attrs` will be bound to the `vm` (just like props are) +- `class` and `style` will not be bound to the `vm` since they will be treated as native and allowed to fallthrough. +- `props` cannot be declared with using `noProps:true` + +# Drawbacks + +- Having an extra `prop` on the options might be a bit confusing +- Having the implicit `inheritAttrs:false` might cause some confusing to more experienced users +- Having `$attrs` bound to the `vm` might cause some unwanted behaviour. +- Increased complexity on the `defineComponent` by having one more way to do it. + +# Alternatives + +```ts +defineComponent({ + props: null, +}) +// or +defineComponent({ + props: false, +}) +``` + +# Adoption strategy + +This is completely optional. + +# Unresolved questions + +There might be some unforeseen behaviour by bounding `$attrs` to the `vm` From 4b92931084412c45219a747acdfeb4cbc5037484 Mon Sep 17 00:00:00 2001 From: pikax Date: Fri, 12 Mar 2021 14:27:47 +0000 Subject: [PATCH 2/3] add spec where name collides --- active-rfcs/0000-no-props-component.md | 1 + 1 file changed, 1 insertion(+) diff --git a/active-rfcs/0000-no-props-component.md b/active-rfcs/0000-no-props-component.md index 18f1fb0f..b0d5d3e2 100644 --- a/active-rfcs/0000-no-props-component.md +++ b/active-rfcs/0000-no-props-component.md @@ -59,6 +59,7 @@ When `noProps:true` the component: - `$attrs` will be bound to the `vm` (just like props are) - `class` and `style` will not be bound to the `vm` since they will be treated as native and allowed to fallthrough. - `props` cannot be declared with using `noProps:true` +- If a attribute has the same name as a local property (`computed`, `data`, `methods`, etc), it should warn and do not update or override the local property, that attribute should be added on the `$attrs` or `$props` object # Drawbacks From 5a036bc22245de72f78c1a0e57cd15ab23428255 Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 13 Mar 2021 16:14:51 +0000 Subject: [PATCH 3/3] improve wording and making more clean --- active-rfcs/0000-no-props-component.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/active-rfcs/0000-no-props-component.md b/active-rfcs/0000-no-props-component.md index b0d5d3e2..2b82d95f 100644 --- a/active-rfcs/0000-no-props-component.md +++ b/active-rfcs/0000-no-props-component.md @@ -5,7 +5,7 @@ # Summary -Make `attrs` to behave as `props` to allow a similar interface as `React` +Allow defining props by Typescript interface # Basic example @@ -48,12 +48,18 @@ defineComponent({ # Motivation -The main motivation is lowering the bar on the people coming from `React` sometimes, the props runtime checks are not needed, because the developer will rely on the typescript typeschecking. +People coming form other frameworks (ReactJS) are used to pass `Props` interface as a first generic and expecting to "be working" when using `props`. That's not possible because `vue` has runtime checks and the props will be inferred by the `props` object. +Other case could be: No need to have runtime validation. # Detailed design -In `vue` `props` and `attrs` are different, to be able to achieve this design, `attrs` will behave like props. -When `noProps:true` the component: +In `vue` everything declared in the `props` object will be bound to the component instance, allowing the direct access in the template (without `$props.` prefix), everything else will be added to `$attrs` object. + +When passing the first generic to `defineComponent` (eg: `defineComponent<{ title: string }>`), is expected that will be `props` and have the same behaviour, but in reality that is not possible since what drives the assigning to `$props`/`$attrs` is if that `prop` name is defined in `props` object. + +To achieve what's proposed in this RFC, attributes will need to be treated as props, for that to happen we need an extra option (eg: `noProps: true`) or passing `props:null`. + +If `noProps: true`: - Will have implicitly `inheritAttrs:false`. - `$attrs` will be bound to the `vm` (just like props are) @@ -66,7 +72,7 @@ When `noProps:true` the component: - Having an extra `prop` on the options might be a bit confusing - Having the implicit `inheritAttrs:false` might cause some confusing to more experienced users - Having `$attrs` bound to the `vm` might cause some unwanted behaviour. -- Increased complexity on the `defineComponent` by having one more way to do it. +- Increased complexity on the `defineComponent` by having one more way to do handle the props from generic type. # Alternatives