# 组合式 API
# setup
- Vue3 的一个新的配置项,其值为一个函数,此函数会在组件 init 时调用,其返回值会挂载在组件对象上。
- 原本的数据属性和方法就在
setup
中定义,并通过return
返回出来 - 其返回值可以是一个对象,也可以是一个渲染函数
- 不建议混用 setup 和 Vue2 的 option API
注意
setup 不能是 async 函数,否则将返回一个 Promise
TIP
由于 setup 调用发生在 data 初始化之前,因此在 setup 函数中初始初始化时,不能访问 option 中的属性和方法
返回一个对象的形式
<template>
<h1>个人信息</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<button @click="sayHello">Hello</button>
</template>
<script>
export default {
name: "App",
setup() {
let name = "刘德华";
let age = 18;
function sayHello() {
alert("Hello");
}
return {
name,
age,
sayHello
};
}
};
</script>
返回一个渲染函数的形式
<script>
import { h } from "vue";
export default {
name: "App",
setup() {
let name = "刘德华";
let age = 18;
function sayHello() {
alert("Hello");
}
return () => {
return h("div", [
h("h1", {}, "个人信息"),
h("h3", {}, "姓名:" + name),
h("h3", {}, "年龄:" + age),
h("button", { onClick: sayHello }, "Hello")
]);
};
}
};
</script>
# ref
此ref
非彼$refs
ref()
用于包装一个简单数据类型,返回一个响应式的引用对象RefImpl
- script
xxx.value
- template
xxx
<template>
<h1>Vue3</h1>
<h2>{{ title }}</h2>
<p>姓名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
<div v-for="(item, index) in hobbits" :key="index">{{ item }}</div>
<button @click="changeAge">按钮</button>
</template>
<script lang="ts">
import { ref, reactive } from "vue";
export default {
name: "App",
setup() {
let title = ref("前端工程师");
let user = reactive({
name: "Gauss Zhou",
age: 18,
a: {
b: 1
}
});
const hobbits = reactive(["吃饭", "睡觉", "打豆豆"]);
console.log(title); // RefImpl
console.log(title.value); // 前端工程师
console.log(user); // Proxy {name: 'Gauss Zhou', age: 18}
console.log(hobbits); // Proxy {0: '吃饭', 1: '睡觉', 2: '打豆豆'}
function changeAge() {
user.age++;
console.log(user.age);
console.log(user.a.b);
}
return {
title,
user,
hobbits,
changeAge
};
}
};
</script>
const foo = ref(1);
const bar = ref(foo)
console.log(foo === bar) // true
# reactive
reactive()
用于包装一个对象或数组,返回一个响应式的代理对象Proxy
- script
xxx.a
- template
xxx.a
<script lang="ts" setup>
import { ref, reactive } from "vue";
interface User {
name: string;
age: number;
a?: any;
}
let title = ref<string>("前端工程师");
let user = reactive<User>({
name: "Gauss Zhou",
age: 18
});
const hobbys = reactive<object>(["吃饭", "睡觉", "打豆豆"]);
console.log(title); // RefImpl
console.log(title.value);
console.log(user); // Proxy {name: 'Gauss Zhou', age: 18}
console.log(hobbys); // Proxy {0: '吃饭', 1: '睡觉', 2: '打豆豆'}
function changeAge() {
user.age++;
console.log(user.age);
}
</script>
<template>
<h1>Vue3</h1>
<h2>{{ title }}</h2>
<p>姓名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
<div v-for="(item, index) in hobbys" :key="index">{{ item }}</div>
<button @click="changeAge">按钮</button>
</template>
# ref vs reactive
从定义来说
- ref 用于定义基本数据类型
- reactive 用于定义引用数据类型
从实现来说
- ref 使用
Object.defineProperty()
- reactive 使用 Proxy 和 Reflect
从使用角度来说
- ref 的值需要通过
.value
来访问
简单理解
function ref(val) {
let value = val;
let refImpl = Object.defineProperty("value", {
get() {
return value;
},
set(val) {
value = val;
}
});
return refImpl;
}