1.拉开序幕的setup
1. 理解:Vue3.0中一个新的配置项,值为一个函数。
2. setup是所有<strong style="color:#DD5145">Composition API(组合API)</strong><i style="color:gray;font-weight:bold">“ 表演的舞台 ”</i>。
4. 组件中所用到的:数据、方法等等,均要配置在setup中。
5. setup函数的两种返回值:
1. 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
2. <span style="color:#aad">若返回一个渲染函数:则可以自定义渲染内容。(了解)</span>
6. 注意点:
1. 尽量不要与Vue2.x配置混用
- Vue2.x配置(data、methos、computed...)中<strong style="color:#DD5145">可以访问到</strong>setup中的属性、方法。
- 但在setup中<strong style="color:#DD5145">不能访问到</strong>Vue2.x配置(data、methos、computed...)。
- 如果有重名, setup优先。
2. setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)
<template>
<h2>个人简历</h2>
<div>{{name}}</div>
<div>{{age}}</div>
<button @click="sayHello">你好</button>
</template>
<script>
export default {
name: 'App',
setup(){
let name = '张三';
let age = 22;
const sayHello=()=>{
console.log(`你好${name}`)
}
return {
name,
age,
sayHello,
}
}
}
</script>
## 2.ref函数
- 作用: 定义一个响应式的数据
- 语法: ```const xxx = ref(initValue)```
- 创建一个包含响应式数据的<strong style="color:#DD5145">引用对象(reference对象,简称ref对象)</strong>。
- JS中操作数据: ```xxx.value```
- 模板中读取数据: 不需要.value,直接:```<div>{{xxx}}</div>```
- 备注:
- 接收的数据可以是:基本类型、也可以是对象类型。
- 基本类型的数据:响应式依然是靠``Object.defineProperty()``的```get```与```set```完成的。
- 对象类型的数据:内部 <i style="color:gray;font-weight:bold">“ 求助 ”</i> 了Vue3.0中的一个新函数—— ```reactive```函数。
<template>
<h2>个人简历</h2>
<div>姓名:{{name}}</div>
<div>年龄:{{age}}</div>
<div>住址:{{obj.address}}</div>
<div>住址:{{obj.tel}}</div>
<button @click="sayHello">点我换人</button>
</template>
<script>
import { ref } from '@vue/reactivity';
export default {
name: 'App',
setup(){
let name=ref('张三');
let age= ref(22);
let obj=ref({
address:'泉州',
tel:'15260482369'
})
const sayHello=()=>{
name.value='李四';
age.value=99;
obj.value.address='丰泽区'
obj.value.tel='110'
}
return {
name,
age,
sayHello,
obj
}
}
}
</script>
3.reactive函数
- 作用: 定义一个<strong style="color:#DD5145">对象类型</strong>的响应式数据(基本类型不要用它,要用```ref```函数)
- 语法:```const 代理对象= reactive(源对象)```接收一个对象(或数组),返回一个<strong style="color:#DD5145">代理对象(Proxy的实例对象,简称proxy对象)</strong>
- reactive定义的响应式数据是“深层次的”。
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。
let obj=reactive({
address:'泉州',
tel:'15260482369'
})
const sayHello=()=>{
name='李四';
age=99;
obj.value.address='丰泽区'
obj.value.tel='110'
}
reactive原理proxy(Reflect)
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
## 6.setup的两个注意点( v-slots->#)
- setup执行的时机
- 在beforeCreate之前执行一次,this是undefined。
- setup的参数
- props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
- context:上下文对象
- attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 ```this.$attrs```。
- slots: 收到的插槽内容, 相当于 ```this.$slots```。
- emit: 分发自定义事件的函数, 相当于 ```this.$emit```。
7.computed计算属性
<template>
姓:<input type="text" v-model="person.firstName" ><br>
名:<input type="text" v-model="person.lastName" ><br>
全名:{{person.fullName}} <br>
全名:<input type="text" v-model="person.fullName">
</template>
<script>
import { reactive } from '@vue/reactivity'
import { computed } from '@vue/runtime-core'
export default {
name: 'App',
setup(){
let person=reactive({
firstName:'张',
lastName:'三',
// fullName:computed(()=>{
// return person.firstName+'-'+person.lastName
// })
fullName:computed({
get(){
return person.firstName+'-'+person.lastName
},
set(value){
const hh=value.split('-')
person.firstName=hh[0]
person.lastName=hh[1]
}
})
})
return {
person,
}
}
}
</script>
8.监视
两个小“坑”:
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
<template>
<div>当前的值是{{hh}}</div>
<button @click="hh++">点我+1</button>
<br>
<div>{{msg}}</div>
<button @click="msg+='!'">哈哈</button>
<br>
<div>{{person.name}}</div>
<button @click="person.name+='~'">嘿嘿嘿</button>
<div>{{person.age}}</div>
<button @click="person.age++">点我变老</button>
<div >{{person.work.salary}}</div>
<button @click="person.work.salary++">点我加薪</button>
</template>
<script>
import { reactive, ref } from '@vue/reactivity'
import { watch } from '@vue/runtime-core'
export default {
name:'app',
setup(){
let hh=ref(0)
let msg=ref('我是')
let person=reactive({
name:'张三',
age:22,
work:{
salary:4,
}
})
// watch(hh,(newValue,oldValue)=>{
// console.log('哈哈哈',newValue,oldValue)
// },{immediate:true})
// watch([hh,msg],(newValue,oldValue)=>{
// console.log('哈哈哈',newValue,oldValue)
// },{immediate:true})
// watch(person,(newValue,oldValue)=>{
// console.log('我变了',newValue,oldValue)
// })
// watch(()=>person.name,(newValue,oldValue)=>{
// console.log('你变了',newValue,oldValue)
// })
watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
console.log('你变了',newValue,oldValue)
})
return {
hh,
msg,
person
}
}
}
</script>
### 9.watchEffect函数
- watch的套路是:既要指明监视的属性,也要指明监视的回调。
- watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
- watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
```js
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
const x1 = sum.value
const x2 = person.age
console.log('watchEffect配置的回调执行了')
})
```