You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> If you came here from HN/Reddit, we strongly suggest that you read this RFC in its entirety before making a comment.
7
+
8
+
# High Level Q&A
9
+
10
+
## Is this like Python 3 / Do I have to rewrite all my code?
11
+
12
+
No. The new API is 100% compatible with current syntax and purely additive. All new additions are contained within the new `setup()` function. 3.0 standard build will support 2.x options plus the new APIs, but you can optionally use the lean build which drops a number of options while providing a smaller and faster runtime. [Details](#adoption-strategy)
13
+
14
+
2.x options compatibility will be kept through the entire 3.x lifecycle.
15
+
16
+
## Is this set in stone?
17
+
18
+
No. This is an RFC (Request for Comments) - as long as this pull request is still open, this is just a proposal for soliciting feedback. We encourage you to voice your opinion, but **please actually read the RFC itself before commenting, as the impression you got from a random Reddit/HN thread is likely misleading.**
19
+
20
+
## Vue is all about simplicity and this RFC is not.
21
+
22
+
RFCs are written for implementors and advanced users who are aware of the internal design constraints of the framework. It focuses on the technical details, and has to be extremely through and cover all possible edge cases, which is why it may seem complex at first glance.
23
+
24
+
We will provide tutorials targeting normal users which will be much easier to follow along with.
25
+
26
+
## This will lead to spaghetti code and is much harder to read.
Also see [more examples comparing the new API to 2.x options](comparison-with-2.x-api).
31
+
32
+
## The Class API is much better!
33
+
34
+
We [respectfully](https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md#type-issues-with-class-api)[disagree](https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121).
35
+
36
+
This RFC also provide strictly superior logic composition and better type inference than the Class API. As it stands, the only "advantage" the Class API has is familiarity - and we don't believe it's enough to outweigh the benefits this RFC provides over it.
37
+
38
+
## This looks like React, why don't I just use React?
39
+
40
+
First, you are not forced to use this API at all.
41
+
42
+
Second, if you use React, you'll most likely be using React Hooks. This API is certainly inspired by React hooks, but it works fundamentally differently. In fact, [we believe this API addresses a number of important usability issues in React Hooks](#comaprison-with-react-hooks). If you cannot put up with this API, you will most likely hate React Hooks even more.
43
+
6
44
# Summary
7
45
8
46
Expose logic-related component options via function-based APIs instead.
9
47
10
48
# Basic example
11
49
12
50
```vue
51
+
<template>
52
+
<div>
53
+
<span>count is {{ count }}</span>
54
+
<span>plusOne is {{ plusOne }}</span>
55
+
<button @click="increment">count++</button>
56
+
</div>
57
+
</template>
58
+
13
59
<script>
14
60
import { value, computed, watch, onMounted } from 'vue'
15
61
@@ -38,14 +84,6 @@ export default {
38
84
}
39
85
}
40
86
</script>
41
-
42
-
<template>
43
-
<div>
44
-
<span>count is {{ count }}</span>
45
-
<span>plusOne is {{ plusOne }}</span>
46
-
<button @click="increment">count++</button>
47
-
</div>
48
-
</template>
49
87
```
50
88
51
89
# Motivation
@@ -757,21 +795,21 @@ Some feedbacks suggest that undisciplined users may end up with "spaghetti code"
757
795
758
796
# Adoption strategy
759
797
760
-
The proposed APIs are all new additions and can theoretically be introduced in a completely backwards compatible way. However, the new APIs can replace many of the existing options and makes them unnecessary in the long run. Being able to drop some of these old options will result in considerably smaller bundle size and better performance.
798
+
The proposed APIs are all new additions and can be introduced in a completely backwards compatible way. However, the new APIs can replace many of the existing options and makes them unnecessary in the long run. Being able to drop some of these old options will result in considerably smaller bundle size and better performance.
761
799
762
800
Therefore we are planning to provide two builds for 3.0:
763
801
764
-
-**Compatibility build**: supports both the new function-based APIs AND all the 2.x options.
802
+
-**Standard build**: compatible with 2.x API (except for breaking changes introduced in other RFCs), with the ability to optionally use the new APIs introduced in this RFC.
765
803
766
-
-**Standard build**: supports the new function-based APIs and only a subset of 2.x options.
804
+
-**Lean build**: only supports the new APIs and a subset of 2.x options. If you are starting a fresh project using only the new API, this would give you a smaller and faster runtime.
767
805
768
-
In the compatibility build, `setup()` can be used alongside 2.x options. Note that `setup()` will be called before `data`, `computed` and `method` options are resolved - i.e. you can access values returned from `setup()` on `this` in these options, but not the other way around.
806
+
In the standard build, `setup()` can be used alongside 2.x options. Note that `setup()` will be called before `data`, `computed` and `method` options are resolved - i.e. you can access values returned from `setup()` on `this` in these options, but not the other way around.
769
807
770
-
Current 2.x users can start with the compatibility build and progressively migrate away from deprecated options, until eventually switching to the standard build.
808
+
Current 2.x users can start with the standard build and progressively introduce the new API into their current codebase, without having to do a full migration all at once.
771
809
772
-
### Preserved Options
810
+
### Common Options
773
811
774
-
> Preserved options work the same as 2.x and are available in both the compatibility and standard builds of 3.0. Options marked with * may receive further adjustments before 3.0 official release.
812
+
> Common options work the same as 2.x and are available in both the full and lean builds of 3.0. Options marked with * may receive further adjustments before 3.0 official release.
775
813
776
814
-`name`
777
815
-`props`
@@ -783,9 +821,9 @@ Current 2.x users can start with the compatibility build and progressively migra
783
821
-`delimiters` *
784
822
-`comments` *
785
823
786
-
### Options deprecated by this RFC
824
+
### Options removed in the Lean Build
787
825
788
-
> These options will only be available in the compatibility build of 3.0.
826
+
> These options will not be available in the lean build of 3.0.
789
827
790
828
-`data` (replaced by `setup()` + `value` + `state`)
791
829
-`computed` (replaced by `computed` returned from `setup()`)
@@ -798,7 +836,7 @@ Current 2.x users can start with the compatibility build and progressively migra
798
836
799
837
### Options deprecated by other RFCs
800
838
801
-
> These options will only be available in the compatibility build of 3.0.
839
+
> There are a number of additional options that are deprecated by other RFCs. These options will likely be supported via a compatibility plugin. They are not strictly related to this RFC, but we are listing them here for completeness.
802
840
803
841
-`el`
804
842
@@ -822,6 +860,271 @@ Current 2.x users can start with the compatibility build and progressively migra
822
860
823
861
# Appendix
824
862
863
+
## Comparison with 2.x API
864
+
865
+
### Simple Counter
866
+
867
+
2.x
868
+
869
+
```vue
870
+
<template>
871
+
<div>
872
+
Count is {{ count }}, count * 2 is {{ double }}
873
+
<button @click="increment">+</button>
874
+
</div>
875
+
</template>
876
+
877
+
<script>
878
+
export default {
879
+
data() {
880
+
return {
881
+
count: 0
882
+
}
883
+
},
884
+
methods: {
885
+
increment() {
886
+
this.count++
887
+
}
888
+
},
889
+
computed: {
890
+
double() {
891
+
return this.count * 2
892
+
}
893
+
}
894
+
}
895
+
</script>
896
+
```
897
+
898
+
New API
899
+
900
+
```vue
901
+
<template>
902
+
<div>
903
+
Count is {{ count }}, count * 2 is {{ double }}
904
+
<button @click="increment">+</button>
905
+
</div>
906
+
</template>
907
+
908
+
<script>
909
+
import { value, computed } from 'vue'
910
+
911
+
export default {
912
+
setup() {
913
+
const count = value(0)
914
+
const double = computed(() => count.value * 2)
915
+
const increment = () => { count.value++ }
916
+
return {
917
+
count,
918
+
double,
919
+
increment
920
+
}
921
+
}
922
+
}
923
+
</script>
924
+
```
925
+
926
+
### Fetching Data Based on Prop
927
+
928
+
2.x
929
+
930
+
```vue
931
+
<template>
932
+
<div>
933
+
<template v-if="isLoading">Loading...</template>
934
+
<template v-else>
935
+
<h3>{{ post.title }}</h3>
936
+
<p>{{ post.body }}</p>
937
+
</template>
938
+
</div>
939
+
</template>
940
+
941
+
<script>
942
+
import { fetchPost } from './api'
943
+
944
+
export default {
945
+
props: {
946
+
id: Number
947
+
},
948
+
data() {
949
+
return {
950
+
isLoading: true,
951
+
post: null
952
+
}
953
+
},
954
+
mounted() {
955
+
this.fetchPost()
956
+
},
957
+
watch: {
958
+
id: 'fetchPost'
959
+
},
960
+
methods: {
961
+
async fetchPost() {
962
+
this.isLoading = true
963
+
this.post = await fetchPost(this.id)
964
+
this.isLoading = false
965
+
}
966
+
}
967
+
}
968
+
</script>
969
+
```
970
+
971
+
New API
972
+
973
+
```vue
974
+
<template>
975
+
<div>
976
+
<template v-if="isLoading">Loading...</template>
977
+
<template v-else>
978
+
<h3>{{ post.title }}</h3>
979
+
<p>{{ post.body }}</p>
980
+
</template>
981
+
</div>
982
+
</template>
983
+
984
+
<script>
985
+
import { fetchPost, value, watch } from './api'
986
+
987
+
export default {
988
+
setup(props) {
989
+
const isLoading = value(true)
990
+
const post = value(null)
991
+
992
+
watch(() => props.id, async (id) => {
993
+
isLoading.value = true
994
+
post.value = await fetchPost(id)
995
+
isLoading.value = false
996
+
})
997
+
998
+
return {
999
+
isLoading,
1000
+
post
1001
+
}
1002
+
}
1003
+
}
1004
+
</script>
1005
+
```
1006
+
1007
+
### Multiple Logic Topics
1008
+
1009
+
Based on the previous data-fetching example, suppose we want to also track mouse position in the same component:
You'll start to notice that we have two logic topics (data fetching and mouse position tracking) but they are split up and mixed between component options.
1066
+
1067
+
With new API:
1068
+
1069
+
```vue
1070
+
<template>
1071
+
<div>
1072
+
<template v-if="isLoading">Loading...</template>
1073
+
<template v-else>
1074
+
<h3>{{ post.title }}</h3>
1075
+
<p>{{ post.body }}</p>
1076
+
</template>
1077
+
</div>
1078
+
</template>
1079
+
1080
+
<script>
1081
+
import { fetchPost, value, watch, onMounted, onUnmounted } from './api'
1082
+
1083
+
function useFetch(props) {
1084
+
const isLoading = value(true)
1085
+
const post = value(null)
1086
+
1087
+
watch(() => props.id, async (id) => {
1088
+
isLoading.value = true
1089
+
post.value = await fetchPost(id)
1090
+
isLoading.value = false
1091
+
})
1092
+
1093
+
return {
1094
+
isLoading,
1095
+
post
1096
+
}
1097
+
}
1098
+
1099
+
function useMouse() {
1100
+
const x = value(0)
1101
+
const y = value(0)
1102
+
const update = e => {
1103
+
x.value = e.pageX
1104
+
y.value = e.pageY
1105
+
}
1106
+
onMounted(() => {
1107
+
window.addEventListener('mousemove', update)
1108
+
})
1109
+
onUnmounted(() => {
1110
+
window.removeEventListener('mousemove', update)
1111
+
})
1112
+
return { x, y }
1113
+
}
1114
+
1115
+
export default {
1116
+
setup(props) {
1117
+
return {
1118
+
...useFetch(props),
1119
+
...useMouse()
1120
+
}
1121
+
}
1122
+
}
1123
+
</script>
1124
+
```
1125
+
1126
+
Notice how the new API cleanly organizes code by logical topic instead of options.
1127
+
825
1128
## Comparison with React Hooks
826
1129
827
1130
The function based API provides the same level of logic composition capabilities as React Hooks, but with some important differences. Unlike React hooks, the `setup()` function is called only once. This means code using Vue's function APIs are:
0 commit comments