- Core concepts and functions of the Composition API
- Composition API Writing Components
- Migrate from Options API to Composition API
The comprehensive upgrade of Vue 3.x introduces the Composition API, which is a major improvement over the traditional Options API of Vue 2.x. It provides a more flexible and modular way of organizing code.
Core concepts and functions of the Composition API
setup() function:
The core entry point in Vue 3, used to set the state and logic of the component, which is executed after the beforeCreate hook and before the create hook. It replaces the content originally defined in options such as data and methods.
import { ref, computed } from "vue";
export default {
setup() {
// Responsive Data
const count = ref(0);
// Computed properties
const doubleCount = computed(() => count.value * 2);
// 方法
function increment() {
count.value++;
}
// Returns the data and methods needed to be used in the template
return {
count,
doubleCount,
increment,
};
},
};
ref and reactive:
Used to create responsive data, ref
is used to create responsive data of basic types, and reactive
is used for responsive proxies of objects and arrays.
import { ref, reactive } from "vue";
export default {
setup() {
// Creating Responsive Primitives Using ref
const count = ref(0);
// Creating responsive objects using reactive
const user = reactive({
name: "Alice",
age: 30,
});
// Modifying Responsive Data
count.value++;
user.age++;
return { count, user };
},
};
Computed properties and listeners:
computed
is used to create computed properties that are recalculated only when dependencies change.
import { ref, computed } from "vue";
export default {
setup() {
const firstName = ref("John");
const lastName = ref("Doe");
// Calculate full name
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
return { firstName, lastName, fullName };
},
};
watch
is used to observe changes in responsive data and execute callbacks when changes occur.
import { ref, watch } from "vue";
export default {
setup() {
const count = ref(0);
// Observe the change of count
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`);
});
function increment() {
count.value++;
}
return { count, increment };
},
};
Composition Functions
The Composition API encourages the creation of reusable composition functions.
// useCounter.js
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
function increment() {
count.value++;
}
return { count, increment };
}
// Use in components
import { useCounter } from "./useCounter";
export default {
setup() {
const { count, increment } = useCounter(10);
return { count, increment };
},
};
Lifecycle hooks:
Lifecycle hooks in Vue 3 are no longer used directly inside setup(), but through new lifecycle hook functions such as onBeforeMount and onMounted.
1. onBeforeMount: This hook is called before the component is mounted to the DOM. This is similar to the beforeMount
lifecycle hook in Vue 2.x.
import { onBeforeMount } from "vue";
export default {
setup() {
onBeforeMount(() => {
console.log("Component is about to be mounted");
});
},
};
2. onMounted: Called immediately after the component is mounted to the DOM. Equivalent to mounted
in Vue 2.x.
import { onMounted } from "vue";
export default {
setup() {
onMounted(() => {
console.log("Component mounted");
});
},
};
3. onBeforeUpdate: Called before the component data is updated, but before the DOM update begins. Similar to Vue 2.x's beforeUpdate
.
import { onBeforeUpdate } from "vue";
export default {
setup() {
let previousData;
onBeforeUpdate(() => {
console.log("Before data update:", previousData);
});
return { data };
},
};
4. onUpdated: Called after the DOM update caused by component data changes is completed. Equivalent to updated in Vue 2.x.
import { onUpdated } from "vue";
export default {
setup() {
onUpdated(() => {
console.log("Component update completed");
});
},
};
5. onBeforeUnmount: Called before the component is uninstalled. Similar to beforeDestroy in Vue 2.x.
import { onBeforeUnmount } from "vue";
export default {
setup() {
onBeforeUnmount(() => {
console.log("The component is about to be uninstalled");
});
},
};
6. onUnmounted: Called after the component has been uninstalled. Equivalent to destroyed in Vue 2.x.
import { onUnmounted } from "vue";
export default {
setup() {
onUnmounted(() => {
console.log("The component has been uninstalled");
});
},
};
7. onActivated: Called only when the component wrapped with <keep-alive>
is activated.
import { onActivated } from "vue";
export default {
setup() {
onActivated(() => {
console.log("Component is activated");
});
},
};
8. onDeactivated: Called only when the component wrapped with <keep-alive>
is deactivated.
import { onDeactivated } from "vue";
export default {
setup() {
onDeactivated(() => {
console.log("Component is deactivated");
});
},
};
Composition API Writing Components
- Create responsive data: Use ref and reactive to create responsive variables.
- Computed properties: Use computed functions to create computed properties.
- Responsive functions: Use toRefs() and toRef() to convert object properties to responsive.
- Listener: Use watch or watchEffect to monitor data changes.
import { ref, reactive, computed, toRefs, watch } from "vue";
import axios from "axios";
export default {
setup() {
// Create responsive data
const state = reactive({
cityInput: "",
city: "",
weather: null,
});
// Calculate the property and return the input city name directly
const currentCity = computed(() => state.cityInput);
// Convert the properties of the state object to responsive references
const { cityInput } = toRefs(state);
// Responsive function for processing API requests
const fetchWeather = async () => {
if (!cityInput.value.trim()) return;
try {
const response = await axios.get(
`https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=${cityInput.value}`
);
state.city = response.data.location.name;
state.weather = { temp: response.data.current.temp_c };
} catch (error) {
console.error("Failed to get weather information", error);
}
};
// Listener, listen to changes in city input, clear weather information
watch(cityInput, () => {
state.weather = null;
});
// Return variables and methods exposed to templates
return {
cityInput,
currentCity,
fetchWeather,
};
},
};
Create responsive data: Use
reactive
to create a responsive object containingcityInput
,city
, andweather
.ref
can also be used for basic types of responsive data, but in this scenario,reactive
is more suitable for managing multiple states.Computed properties: The
currentCity
computed property directly returns the value ofstate.cityInput
. Although it may be more intuitive to usev-model="cityInput"
directly in this example, it shows how to define computed properties.Responsive functions: Use
toRefs
to convert the properties of thestate
object into independent responsive references for direct binding in the template. This mainly shows the use of responsive data, rather than the conversion function itself, because direct destructuring assignment (such asconst { cityInput } = state;
) is sufficient in the template.Listeners: Use
watch
to listen to changes incityInput
, and clear theweather
state every time the input changes, so that it can be queried next time.
Migrate from Options API to Composition API
Component structure
Separate state, methods, and logic into separate functions. In the Options API, we usually define data, methods, computed, etc. in the component options. In the Composition API, these logics are separated into separate functions. For example:
Options API:
export default {
data() {
return {
message: 'Hello, Vue!'
};
},
methods: {
greet() {
console.log(this.message);
}
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
};
Composition API:
import { ref, computed } from 'vue';
export default {
setup() {
const message = ref('Hello, Vue!');
function greet() {
console.log(message.value);
}
const reversedMessage = computed(() => message.value.split('').reverse().join(''));
return {
message,
greet,
reversedMessage
};
}
};
Dependency Injection
Use provide and inject. In Options API, we use provide and inject to pass data. In the Composition API, this process remains the same:
Options API:
// Parent component
export default {
provide() {
return {
parentValue: 'Parent component value'
};
}
};
// Child component
export default {
inject: ['parentValue'],
mounted() {
console.log(this.parentValue); // Output "parent component value"
}
};
Composition API:
// Parent component
export default {
setup() {
provide('parentValue', 'parent component value');
}
};
// Child component
export default {
setup(_, { inject }) {
const parentValue = inject('parentValue');
onMounted(() => {
console.log(parentValue); // Output "parent component value"
});
}
};
Template refactoring
Convert bound properties and methods from this to direct references.
Top comments (0)