### setup 概述
`setup`是`Vue3`中一个新的配置项,值是一个函数,组件中所用到的:数据、方法、计算属性、监视......等等,均配置在`setup`中。
特点如下:
- `setup`函数返回的对象中的内容,可直接在模板中使用。
- `setup`中访问`this`是`undefined`。
- `setup`函数会在`beforeCreate`之前调用,它是“领先”所有钩子执行的。
```vue
姓名:{{name}}
年龄:{{age}}
```
### setup 的返回值
- 若返回一个**对象**:则对象中的:属性、方法等,在模板中均可以直接使用**(重点关注)。**
- 若返回一个**函数**:则可以自定义渲染内容,代码如下:
```jsx
setup(){
return ()=> '你好啊!'
}
```
### setup 与 Options API 的关系
- `Vue2` 的配置(`data`、`methos`......)中**可以访问到** `setup`中的属性、方法。
- 但在`setup`中**不能访问到**`Vue2`的配置(`data`、`methos`......)。
- 如果与`Vue2`冲突,则`setup`优先。
### setup 语法糖
`setup`函数有一个语法糖,这个语法糖,可以让我们把`setup`独立出去,代码如下:
```vue
姓名:{{name}}
年龄:{{age}}
```
扩展:上述代码,还需要编写一个不写`setup`的`script`标签,去指定组件名字,比较麻烦,我们可以借助`vite`中的插件简化
1. 第一步:`npm i vite-plugin-vue-setup-extend -D`
2. 第二步:`vite.config.ts`
```jsx
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [ VueSetupExtend() ]
})
```
3. 第三步:`
```
## 【reactive 创建:对象类型的响应式数据】
- **作用:**定义一个**响应式对象**(基本类型不要用它,要用`ref`,否则报错)
- **语法:**`let 响应式对象= reactive(源对象)`。
- **返回值:**一个`Proxy`的实例对象,简称:响应式对象。
- **注意点:**`reactive`定义的响应式数据是“深层次”的。
```vue
汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万
游戏列表:
测试:{{obj.a.b.c.d}}
```
## 【ref 创建:对象类型的响应式数据】
- 其实`ref`接收的数据可以是:**基本类型**、**对象类型**。
- 若`ref`接收的是对象类型,内部其实也是调用了`reactive`函数。
```vue
汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万
游戏列表:
测试:{{obj.a.b.c.d}}
```
## 【ref 对比 reactive】
宏观角度看:
> 1. `ref`用来定义:**基本类型数据**、**对象类型数据**;
>
> 2. `reactive`用来定义:**对象类型数据**。
- 区别:
> 1. `ref`创建的变量必须使用`.value`(可以使用`volar`插件自动添加`.value`)。
>
>
>
> 2. `reactive`重新分配一个新对象,会**失去**响应式(可以使用`Object.assign`去整体替换)。
- 使用原则:
> 1. 若需要一个基本类型的响应式数据,必须使用`ref`。
> 2. 若需要一个响应式对象,层级不深,`ref`、`reactive`都可以。
> 3. 若需要一个响应式对象,且层级较深,推荐使用`reactive`。
## 【toRefs 与 toRef】
- 作用:将一个响应式对象中的每一个属性,转换为`ref`对象。
- 备注:`toRefs`与`toRef`功能一致,但`toRefs`可以批量转换。
- 语法如下:
```vue
姓名:{{person.name}}
年龄:{{person.age}}
性别:{{person.gender}}
```
## 【computed】
作用:根据已有数据计算出新数据(和`Vue2`中的`computed`作用一致)。
```vue
姓:
名:
全名:{{fullName}}
```
## 【watch】
- 作用:监视数据的变化(和`Vue2`中的`watch`作用一致)
- 特点:`Vue3`中的`watch`只能监视以下**四种数据**:
> 1. `ref`定义的数据。
> 2. `reactive`定义的数据。
> 3. 函数返回一个值(`getter`函数)。
> 4. 一个包含上述内容的数组。
我们在`Vue3`中使用`watch`的时候,通常会遇到以下几种情况:
### * 情况一
监视`ref`定义的【基本类型】数据:直接写数据名即可,监视的是其`value`值的改变。
```vue
情况一:监视【ref】定义的【基本类型】数据
当前求和为:{{sum}}
```
### * 情况二
监视`ref`定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视。
> 注意:
>
> * 若修改的是`ref`定义的对象中的属性,`newValue` 和 `oldValue` 都是新值,因为它们是同一个对象。
>
> * 若修改整个`ref`定义的对象,`newValue` 是新值, `oldValue` 是旧值,因为不是同一个对象了。
```vue
情况二:监视【ref】定义的【对象类型】数据
姓名:{{ person.name }}
年龄:{{ person.age }}
```
### * 情况三
监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。
```vue
情况三:监视【reactive】定义的【对象类型】数据
姓名:{{ person.name }}
年龄:{{ person.age }}
测试:{{obj.a.b.c}}
```
### * 情况四
监视`ref`或`reactive`定义的【对象类型】数据中的**某个属性**,注意点如下:
1. 若该属性值**不是**【对象类型】,需要写成函数形式。
2. 若该属性值是**依然**是【对象类型】,可直接编,也可写成函数,建议写成函数。
结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。
```vue
情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性
姓名:{{ person.name }}
年龄:{{ person.age }}
汽车:{{ person.car.c1 }}、{{ person.car.c2 }}
```
### * 情况五
监视上述的多个数据
```vue
情况五:监视上述的多个数据
姓名:{{ person.name }}
年龄:{{ person.age }}
汽车:{{ person.car.c1 }}、{{ person.car.c2 }}
```