What does the Composition API bring to Vue
- Better code organization
- Better logic reuse
- Better type derivation
Better code organization
-
In optionsAPI components, when a component becomes too large, the list of different business logic also grows. When working with individual business logic, we must constantly “jump” to the option blocks of the related code. Fragmentation makes it difficult to understand and maintain complex components.
-
The Composition API enables us to gather together related code for the same logic.
Better logic reuse
In Setup, you can separate the logical code into a separate composite function. The function naming convention is useXxxx format, and then reference the useXxx function in setup
Example: Get the mouse logic to pull away
What if we wanted to remove the mouse-capture logic so that each component could use a responsive mouse-location coordinate? We can write the logic in a separate file, extract the above code into a separate composite function, export it, and reference it in setup
//useMousePosition.js
import { ref, onMounted, onUnmounted } from 'vue'
function useMousePosition() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() = > {
console.log('useMousePosition mounted')
window.addEventListener('mousemove', update)
})
onUnmounted(() = > {
console.log('useMousePosition unMounted')
window.removeEventListener('mousemove', update)
})
return {
x,
y
}
}
Copy the code
Use: import the relevant logic, deconstruct the coordinates
<template>
<p>mouse position {{x}} {{y}}</p>
</template>
<script>
import useMousePosition from './useMousePosition'
export default {
name: 'MousePosition'.setup() {
const { x, y } = useMousePosition()
return {
x,
y
}
}
}
</script>
Copy the code
Better type derivation
In optionsAPI,data
, methods
, computed
Etc are mounted to the current instance, unified usethis
This makes it unhelpful to derive types syntactically. According to js usage habits, we should use similarthis.methods.fn1()
Is logical.
Vue3 setup does not use this. Instead, it wraps each logic into a function, making the logic clearer and returning values clear.
ref()
/ reactive()
, toRef()
/ toRefs()
ref
/ reactive
use
Ref () :
-
The ref function takes an internal value (the original value) and returns a reactive and mutable REF object.
-
This object is an object with a value property that can be used to access or change the value of a reactive variable.
-
The ref value can be used for templates and reactive
Reactive () :
-
To create reactive state for JavaScript objects, you can use the Reactive method
-
The API returns a reactive object state.
-
Reactive conversions are “deep” — they apply to all nested properties
The view updates automatically when the reactive state changes
For example:
<template>
<p>ref demo {{ageRef}} {{state.name}}</p>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
name: 'Ref'.setup() {
const ageRef = ref(20) // The value type is responsive
const nameRef = ref(' ')
const state = reactive({
name: nameRef
})
setTimeout(() = > {
console.log('ageRef', ageRef.value)
ageRef.value = 25 //. Value Changes the value
nameRef.value = 'xxx'
}, 1500);
return {
ageRef,
state
}
}
}
</script>
Copy the code
Ref can also get DOM elements
<template>
<p ref="elemRef">I'm a line of text</p>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
name: 'RefTemplate'.setup() {
const elemRef = ref(null)
onMounted(() = > {
console.log('ref template', elemRef.value.innerHTML, elemRef.value)
})
return {
elemRef
}
}
}
</script>
Copy the code
toRef
/ toRefs
use
ToRef: Creates a REF for a prop wrapped reactive object and maintains a reference relationship between the two
<template>
<p>toRef demo - {{ageRef}} - {{state.name}} {{state.age}}</p>
</template>
<script>
import { ref, toRef, reactive } from 'vue'
export default {
name: 'ToRef'.setup() {
const state = reactive({
age: 20.name: 'xxx'
})
const age1 = computed(() = > {
return state.age + 1
})
// // toRef If used for ordinary objects (non-reactive objects), the output does not have a reactive formula
// const state = {
// age: 20,
// name: 'xxx'
// }
const ageRef = toRef(state, 'age')
setTimeout(() = > {
state.age = 25
}, 1500)
setTimeout(() = > {
ageRef.value = 30 //. Value Changes the value
}, 3000)
return {
state,
ageRef
}
}
}
</script>
Copy the code
ToRefs: Transforms a reactive object (wrapped in Reactive) into a normal object. Each prop of the object is a corresponding REF, and the two are referenced
<template>
<p>toRefs demo {{age}} {{name}}</p>
</template>
<script>
import { ref, toRef, toRefs, reactive } from 'vue'
export default {
name: 'ToRefs'.setup() {
const state = reactive({
age: 20.name: 'xx'
})
const stateAsRefs = toRefs(state) // Turn a reactive object into a normal object
// const {age: ageRef, name: nameRef} = stateAsRefs
// return {
// ageRef,
// nameRef
// }
setTimeout(() = > {
state.age = 25
}, 1500)
return stateAsRefs
}
}
</script>
Copy the code
So if you use the toRefs structure, the responsiveness is preserved, and if you write it like this, you lose the responsiveness
setup() {
const state = reactive({
age: 20.name: 'xx'
})
return {
...state
}
}
Copy the code
Best way to use the above API
-
Reactive for objects and REF for value type responses
-
Setup returns toRefs(state), or toRef(state,’ XXX ‘). Try not to return reactive objects, otherwise you will need to use variables in the template as state.xxx
-
XxxRef = xxxRef = xxxRef = xxxRef
-
ToRefs is used when a synthesized function returns a reactive object, for example:
Deep understanding of
Why we needref
The official answer:
To put it simply:
-
Return value type, the response will be lost. By changing this reactive value to a reference, it can be modified anywhere without losing its responsiveness and can be safely modified
-
For example, setup, computed (computed returns an object similar to ref, including.value), and composite functions can all return value types. If Vue does not define ref, users will create their own ref, which will be chaotic
.value
<template>
<p>why ref demo {{state.age}} - {{age1}}</p>
</template>
<script>
import { ref, toRef, toRefs, reactive, computed } from 'vue'
function useFeatureX() {
const state = reactive({
x: 1.y: 2
})
return toRefs(state)
}
export default {
name: 'WhyRef'.setup() {
const { x, y } = useFeatureX()
const state = reactive({
age: 20.name: 'xxx'
})
// Computed returns an object similar to ref, also with.value
const age1 = computed(() = > {
return state.age + 1
})
setTimeout(() = > {
state.age = 25
}, 1500)
return {
state,
age1,
x,
y
}
}
}
</script>
Copy the code
ref
Why is the created object needed.value
- As stated above, ref is an object (so as not to lose the response), so use
.value
Used to store its original value - Can be achieved by
.value
Properties of theget
和set
Implementing responsiveness
Note: For templates and reactive, you do not need to write.value. For other cases, you need to obtain and modify
Why we needtoRef
和 toRefs
ToRefs is useful when returning a reactive object from a composite function so that the consuming component can decompose/diffuse the returned object without losing its responsiveness. (This also makes it easier to deconstruct the assignment)
function useFeatureX() {
const state = reactive({
foo: 1.bar: 2
})
// Operate on the logic of state
// Convert to ref on return
return toRefs(state)
}
export default {
setup() {
// Can be destructed without losing responsiveness
const { foo, bar } = useFeatureX()
return {
foo,
bar
}
}
}
Copy the code
So, the goal is to decompose/diffuse the object data without losing the response. You don’t create responsiveness, you continue responsiveness
setup
In theprops
So props in Setup is equivalent to a reactive object created using reactive functions.
Notice, optionalprops
Will not betoRefs
Processing, so if aprops
It doesn’t have to be transmitted, it has to be usedtoRef
, the official website is explained as follows:For example:
<PropsTest :p1="' I am p1" :p2="' I am the p2 '"></PropsTest>
Copy the code
//PropsTest.vue
<template>
<p>props demo <br>
p1:{{p1}} <br>
p2:{{p2}} <br>
p3:{{p3}}</p>
</template>
<script>
import {ref, reactive, toRef, toRefs, onMounted} from 'vue'
export default {
name: 'PropsTest'.setup(props) {
const {p1, p2,p3} = toRefs(props)
// const p3 = toRef(props, 'p3')
onMounted(() = > {
console.log('p1', p1)
console.log('p2', p2)
console.log('p3', p3)
return {
p1,
p2,
p3
}
})
},
props: {p1:String.p2:String.p3:String}}</script>
Copy the code
If used this way:
const {p1, p2} = toRefs(props)
const p3 = toRef(props, 'p3')
Copy the code
You can return a reactive object