Understanding Vue 3 Composition API: Ref, Reactive, toRefs, Computed, Watch, Provide/Inject, and Lifecycle Hooks
This article explains Vue 3's Composition API, covering how to create reactive data with ref and reactive, use toRefs, define computed properties, apply readonly, watch and watchEffect, handle lifecycle hooks, pass props, and share state via provide and inject, all with practical code examples.
What is the Composition API? The Composition API is a new feature in Vue 3 that allows developers to extract reusable logic into separate functions, improving code maintainability and reusability compared to the Options API.
Using ref and reactive in setup – First import the functions from Vue, then define reactive state. ref creates a single reactive value accessed via .value , while reactive creates a reactive object whose properties are accessed directly.
<code>import { ref, reactive } from 'vue';
export default {
setup() {
// ref example
const title = ref("这是一个标题");
// reactive example
const userinfo = reactive({
username: "张三",
age: 20
});
const getUserName = () => { alert(userinfo.username); };
const getTitle = () => { alert(title.value); };
const setUserName = () => { userinfo.username = "修改后的张三"; };
const setTitle = () => { title.value = "这是修改后的标题"; };
return { title, userinfo, getUserName, getTitle, setUserName, setTitle };
},
data() { return { msg: "这是Home组件的msg" }; },
methods: { run() { alert('这是Home组件的run方法'); } }
};</code>Both title and userinfo can be bound directly in the template using v-model :
<code><input type="text" v-model="title">
<input type="text" v-model="userinfo.username"></code>Destructuring reactive objects with toRefs – toRefs preserves reactivity when spreading an object, unlike the spread operator.
<code>import { ref, reactive, toRefs } from 'vue';
export default {
setup() {
const article = reactive({ title: "标题", content: "内容" });
return { ...toRefs(article) };
}
};</code>Computed properties in setup work like regular computed values but cannot access this .
<code>setup() {
const userinfo = reactive({ firstName: "", lastName: "" });
const fullName = computed(() => userinfo.firstName + " " + userinfo.lastName);
return { ...toRefs(userinfo), fullName };
}</code>Readonly proxy – readonly converts a reactive object into an immutable version.
<code>import { reactive, readonly } from 'vue';
let userinfo = reactive({ firstName: "666", lastName: "" });
userinfo = readonly(userinfo);</code>watchEffect automatically runs its callback whenever any reactive dependency changes and also runs once on initialization.
<code>setup() {
const data = reactive({ num: 1 });
watchEffect(() => { console.log(`num2=${data.num}`); });
setInterval(() => { data.num++; }, 1000);
return { ...toRefs(data) };
}</code>watch vs. watchEffect – watch does not execute on initial render and provides both old and new values, while watchEffect runs immediately and only gives the new value.
<code>setup() {
const keyword = ref("111");
watch(keyword, (newData, oldData) => {
console.log("newData是:", newData);
console.log("oldData是:", oldData);
});
return { keyword };
}</code>Lifecycle hooks in setup are called as regular functions such as onMounted and onUpdated .
<code>setup() {
const keyword = ref("111");
watch(keyword, (newData, oldData) => { /* ... */ });
onMounted(() => { console.log('onMounted'); });
onUpdated(() => { console.log('onUpdated'); });
return { keyword };
}</code>Props in setup – Parent components pass data via props, which are received as the first argument of setup .
<code><Search :msg="'msg'" />
export default {
props: ['msg'],
setup(props) { console.log(props); }
};</code>Provide and inject (Options API) – Used to pass data from a deep ancestor to descendants without prop drilling.
<code>// Provider (root component)
export default {
provide() { return { title: "app组件里面的标题" }; }
};
// Consumer
export default {
inject: ['title'],
template: `<div class="container">这是Location组件 {{title}}</div>`
};</code>Provide and inject with the Composition API – The root component calls provide with a reactive value, and child components retrieve it via inject , keeping the data synchronized.
<code>// Root component
import { ref, provide } from 'vue';
export default {
setup() {
const title = ref('app根组件里面的title');
const setTitle = () => { title.value = '改变后的title'; };
provide('title', title);
return { title, setTitle };
}
};
// Child component
import { inject } from 'vue';
export default {
setup() {
const title = inject('title');
return { title };
}
};</code>Note: Using the Composition API version of provide/inject ensures that changes in the provided value are reflected in all consuming components.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.