In the last article, I made a preview of Vue 3.0 and experienced Vue Function API. By trying VUe-function-API, I experienced the upcoming functional API of Vue 3.0 in advance. At the end of the article, I put forward some thoughts. The Vue Function API has been changed to Vue Composition API after community feedback has been fully taken into account. The @vue/ composition-API library provides an early taste of this API in Vue 2.x, which I used for learning purposes. In conjunction with the previous article, I describe some of the changes the Vue team made to the API after incorporating community comments.
This article discusses the latest Composition API in the following topics:
- reactive API
- ref API
- Watch the API changes
- The computed API changes
- Lifecycle hook changes
- TypeScript and JSX support
The Composition API is the latest “revision” to fix many of the problems with the Function API. What are the changes to the vue-function-API?
state
renamedreactive
In vue-function-API, reactive objects are created by state, which is not a wrapper object and does not require a. Value value. But here’s the thing: The Vue team decided that it would be more elegant to rename the state API to Reactive, which is equivalent to the vue.Observable () of Vue 2.x. A responsive proxy object used to get an object:
const obj = reactive({ count: 0 });
Copy the code
Value is renamed ref and isRef and toRefs are provided
In vue-function-API, the value function creates a wrapper object that contains a reactive property value. This API was changed to REF after the OFFICIAL Vue team fully adopted community comments. Ref creates a wrapper object with a single value attribute. If an object is specified as the value of REF, the object will be deeply traversed by reactive methods. It should be noted that the Composition API was proposed and used to make it easier to reuse components. In the process of passing state through functions, JavaScript functions pass parameters by value, while basic types do not have references. In order to ensure the responsiveness of properties, Ref will be used to create wrapper objects for passing.
const count = ref(0);
console.log(count.value); / / 0
count.value++;
console.log(count.value); / / 1
Copy the code
Provides isRef to check whether an object is a REF object:
const unwrapped = isRef(foo) ? foo.value : foo;
Copy the code
If you look at this, you might be wondering, when should you use REF and when should you use Reactive? The usage scenario is closely related to the coding style we are used to, and we can better understand the difference between using REF and Reactive by using the following example:
// Style 1: declare state via primitive type variables
let x = 0;
let y = 0;
function updatePosition(e) {
x = e.pageX;
y = e.pageY;
}
// --- compared to ---
// Style 2: Declare state through a single object
const pos = {
x: 0.y: 0};function updatePosition(e) {
pos.x = e.pageX;
pos.y = e.pageY;
}
Copy the code
If the developer is comfortable with style one, it is common to make a primitive type variable reactive by converting it to a reactive wrapper object via ref, whereas in style two, it is only necessary to create a Reactive object.
However, consider the following scenario:
function useMousePosition() {
const pos = reactive({
x: 0.y: 0});// ...
return pos;
}
// consuming component
export default {
setup() {
// Object deconstruction will cause the response to be lost
const { x, y } = useMousePosition();
return {
x,
y,
};
// Extending the operator will result in reactive loss
return {
...useMousePosition()
}
// This is the only way to ensure that the response is not lost
Pos. y of pos.x preserves the x, y response
return {
pos: useMousePosition()
}
}
};
Copy the code
From the above example, remember that there is no way to guarantee that the reactive state returned by composite functions will not be lost through the restriction of coding style. The official Vue team recommends that all composite functions should return ref objects to avoid this problem, and toRef is the best way to do this:
function useMousePosition() {
const pos = reactive({
x: 0.y: 0
});
// ...
return toRefs(pos);
}
// x and y are now responsive
const { x, y } = useMousePosition();
Copy the code
ToRefs transforms reactive objects into normal objects, where each attribute on the resulting object is a ref reference object that points to the corresponding attribute in the original object. This is useful when composite functions return reactive state, ensuring that the response of the original reactive object is not lost when the object is deconstructed or extended by the operator.
watch
It operates on a single function
In the latest @vue/ comaction-API amendment, the method of passing watch can converge to a single function. Vue 3.x will execute the watch callback function when its dependent responsive state changes:
const count = ref(0);
watch((a)= > console.log(count.value)); / / print 0
setTimeout((a)= > {
count.value++; / / print 1
}, 100);
Copy the code
computed
Can be introduced toget
andset
Is used to define computable properties that can be changed
The basic example is shown below, and like Vue 2.x, you can define computable properties that can be changed.
const count = ref(1);
const plusOne = computed({
get: (a)= > count.value + 1.set: val= > { count.value = val - 1}}); plusOne.value =1;
console.log(count.value); / / 0
Copy the code
Lifecycle hook
Compared to vue-function-API, @vue/composition-api removes onBeforeCreate and onCreated. Because Setup is always called when the component instance is created, after onBeforeCreate and before onCreated, onBeforeCreate and onCreated can be used instead.
Use TypeScript and JSX
Setup now supports returning a render function that returns a JSX, which can be used directly with the reactive state declared in the setup scope:
export default {
setup() {
const count = ref(0);
return (a)= > (<div>{count.value}</div>); }};Copy the code
Note: If you use TypeScript and want to use the following interface, declare it in the JSX namespace:
// file: shim-tsx.d.ts
import Vue, { VNode } from 'vue';
import { ComponentRenderProxy } from '@vue/composition-api';
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode { }
// tslint:disable no-empty-interface
interface ElementClass extends ComponentRenderProxy { }
interface ElementAttributesProperty {
$props: any; // specify the property name to use
}
interface IntrinsicElements {
[elem: string] :any; }}}Copy the code
In addition, to work better with TypeScript for type inference, the Vue Composition API recommends using createComponent to define a component for Vue to derive:
import { createComponent } from 'vue';
export default createComponent({
props: {
foo: String,
},
setup(props) {
console.log(props.foo); }});Copy the code
summary
This article is a continuation of my previous Vue 3.0 preview and experience of Vue Function API. It mainly describes the changes of Vue Composition API compared with the previous draft Vue Function API. As you can see, Vue officials have modified the Vue Function API draft in response to community suggestions. In the next article, the author will explain the principle of responsive object of Vue Composition API, and deepen the understanding of Vue Composition API in the process of reading and learning.