目录
link
setup
setup是Vue3.0中一个新的配置项,值的类型为一个函数。setup是所有Composition API(组合API)的“表演舞台 ”。
setup的执行时机
setup函数在beforeCreate之前执行一次,this是undefined;也就是说在setup中不能使用this
!
export default {
setup () {
console.log('this', this) // undefined
}
}
[1]定义数据和方法
在vue2.x中数据需要定义在data中,方法需要定义在methods中。
在vue3.x中数据和方法直接定义在setup中即可。
那么哪些数据可以在模版中直接使用呢?
setup函数返回值若是为一个
对象
,则该对象内的所有属性均可在模版中直接使用<template> <div class="test">{ { name }}</div> </template> <script> export default { setup () { const name = 'chaochao' return { name } } } </script>
setup函数返回值若是一个渲染函数,则该页面的内容为渲染函数的值而非模版中的内容了。
<template> <div class="test">11111</div> </template> <script> export default { setup () { return ()=>{ return h('div', 'chaochao') } } } </script>
tips: 模版中的内容被覆盖了!
注意:setup不能是一个async函数
,因为async函数的返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)
兼容性
vue3.0中可以使用vue2.x的data、methods配置项吗?
在vue3.0中可以兼容之前的配置项,但是尽量不要与Vue2.x配置混用。若是混用:
- Vue2.x配置项(data、methos、computed…)中可以访问到setup中的属性、方法;但在setup中不能访问到Vue2.x配置项中的属性和方法。
- 如果有重名属性/方法, setup优先。
响应式数据
setup (){
let 变量名 = 值
return {
变量名
}
}
直接通过上述语法声明变量,变量虽然可以在模版中使用,但是数据并不是响应式的,当数据更改时,vue并不会重新渲染数据;
若是想要数据是响应式的需要借助 ref函数
或 reactive函数
进行双向数据绑定。
ref(组合API)
作用
ref函数的作用是 定义一个响应式
的数据;推荐在定义简单数据类型时使用;
语法
let 变量名 = ref(initValue)
- 创建一个包含响应式数据的reference引用对象
- JS中操作数据:
变量名.value
- 模板中读取数据: 不需要.value,直接:
{ {变量名}}
即可(内部做了封装,实际读取得是变量名.value)
示例
<template>
<div class="hello">
<h1>姓名:{
{name}}</h1>
</div>
</template>
<script>
import {
ref } from 'vue'
export default {
setup () {
let name = ref('chaochao')
console.log('@@@', name) // reference对象,value属性值为真实的值
return {
name
}
}
}
</script>
本质
- ref函数接收的数据可以是基本类型也可以是引用类型
- 基本类型的数据:响应式依然是靠
Object.defineProperty()
的get
与set
完成的。->实现原理传送门 - 对象类型的数据:内部会自动通过
reactive
函数转为代理对象
reactive(组合API)
作用
reactive函数的作用是 定义一个引用类型的响应式数据(基本类型使用ref函数)
语法
const 代理对象= reactive(源对象)
- 接收一个对象/数组,返回一个Proxy实例对象
- reactive定义的响应式数据是“深层次的”
- 使用reactive方法实现双向绑定原理->传送门
重新赋值失去响应式
在Vue3中如果对一个reactive对象重新赋值,会导致失去响应式。
<template>
<div class="test">
{
{
info.name }}
<br>
{
{
info.age }}
<br>
<button @click="editinfo">修改</button>
</div>
</template>
<script>
import {
reactive } from 'vue'
export default {
setup () {
let info = reactive({
name:'chaochao',
age:18
})
function editinfo () {
info = reactive({
name:'niuniu',
age:20
})
console.log('info', info)
}
return {
info,
editinfo
}
}
}
</script>
上述示例中点击按钮页面没有任何变化(虽然打印的info数据发生了变化)
这是因为reactive是使用了Proxy来实现响应式,而Proxy只能监听对象的属性访问和修改,而不能监听对象本身的赋值操作
!
若是想要修改对象的值应该怎么做呢? 可以修改对象单个的属性
// 此时点击按钮时页面内容随之改变
function editinfo () {
info.name = 'niuniu'
info.age = 20
console.log('info', info)
}
但是很多情况下我们修改对象都是后端直接返回来的数据,字段很多,这样修改比较麻烦,可以使用ref来定义对象。
export default {
setup () {
let info = ref({
name:'chaochao',
age:18
})
function editinfo () {
info.value = {
name: 'niuniu',
age: 20
}
}
return {
info,
editinfo
}
}
}
因为修改ref对象修改的是value属性值,可以直接修改(数据还是响应式的)!
对比ref与reactive
- 从定义数据角度对比:
- ref用来定义:基本类型数据。
- reactive用来定义:对象/数组类型数据。
- 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过
reactive
转为代理对象。
- 从原理角度对比:
- ref通过
Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。 - reactive通过使用
Proxy
来实现响应式(数据劫持)。
- ref通过
- 从使用角度对比:
- ref定义的数据:操作数据需要
.value
,读取数据时模板中直接读取不需要.value
。 - reactive定义的数据:操作数据与读取数据:均不需要
.value
。
- ref定义的数据:操作数据需要
toRef
[2] 组件化开发
[3] 生命周期函数
tips: 个人感觉在3.x中2.x中的生命周期函数毫无用处->获取不到setup中的数据根本进行不了任何操作