The better way to code。
Basic example
<template>
<div>
<div>
<span>double:</span><span>{{double}}</span>
</div>
<button @click="inc">Clicked {{ count }} times.</button>
<div>
<div><input type="number" v-model="form.a"></div>
<div><input type="number" v-model="form.b"></div>
<div>
<span>a + b:</span>
<span>{{result1}}</span>
</div>
<div>
<span>a + count:</span>
<span>{{result2}}</span>
</div>
<div>
<span>b + count:</span>
<span>{{result3}}</span>
</div>
<div>
<span>a + b + double:</span>
<span>{{result4}}</span>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, computed } from 'vue'
export default {
setup () {
const form = reactive({
a: 1,
b: 2
})
const count = ref(0)
const inc = () => {
count.value++
}
const double = computed(() => {
return count.value * 2
})
const result1 = computed(() => {
return form.a + form.b
})
const result2 = computed(() => {
return form.a + count.value
})
const result3 = computed(() => {
return form.b + count.value
})
const result4 = computed(() => {
return form.a + form.b + double.value
})
return {
form,
count,
double,
result1,
result2,
result3,
result4,
inc
}
}
}
</script>
The usage of .value is easy to make Bug.
So I think the better way is like this.
<template>
<div>
<div>
<span>double:</span><span>{{double}}</span>
</div>
<button @click="inc">Clicked {{ count }} times.</button>
<div>
<div><input type="number" v-model="form.a"></div>
<div><input type="number" v-model="form.b"></div>
<div>
<span>a + b:</span>
<span>{{result1}}</span>
</div>
<div>
<span>a + count:</span>
<span>{{result2}}</span>
</div>
<div>
<span>b + count:</span>
<span>{{result3}}</span>
</div>
<div>
<span>a + b + double:</span>
<span>{{result4}}</span>
</div>
</div>
</div>
</template>
<script>
import { toRefs, reactive, computed } from 'vue'
export default {
setup () {
const state = reactive({
form: {
a: 1,
b: 2
},
count: 0
})
const inc = () => {
state.count++
}
state.double = computed(() => {
return state.count * 2
})
state.result1 = computed(() => {
return state.form.a + state.form.b
})
state.result2 = computed(() => {
return state.form.a + state.count
})
state.result3 = computed(() => {
return state.form.b + state.count
})
state.result4 = computed(() => {
return state.form.a + state.form.b + state.double
})
return {
...toRefs(state),
inc
}
}
}
</script>
No more .value,just like state instead of this in vue2.
I proposed exactly the same previously. But then after using the API for a while it became clear to me that ref is amazing.
There is nothing to stop you from coding in that style tho. Feel free to do whatever you prefer?
One big thing that does not work with reactive is TypeScript support. Even simple things like this don't compile with TypeScript without declaring a separate interface
const state = reactive({
a: 1,
b: 2,
c: computed(() => {
return state.a * state.b
})
})
And even though everyone seem to embrace better TypeScript support - all the examples don't use it or just use ref instead. Even official ones.
So if you need TypeScript you either get used to write value & ref everywhere or get used to write interfaces for TypeScript & reactive (or hope that some day TS will compile recursive types). ref seems like a better option in the end.
To be precise - it compiles, but state has type any (so no point in using TypeScript) - 'state' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
The .value is necessary and described at https://vue-composition-api-rfc.netlify.com/#ref-vs-reactive
This was largely discussed during the RFC process at https://github.com/vuejs/rfcs/pull/78 and the previous one at #42 (that's why it has a note on the RFC website)