1.拉开序幕的setup

  1. 理解:Vue3.0中一个新的配置项,值为一个函数。
  2. setup是所有Composition API(组合API)“ 表演的舞台 ”
  3. 组件中所用到的:数据、方法、生命周期等等,均要配置在setup中。
  4. setup函数的两种返回值:
    1. 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
    2. 若返回一个渲染函数:则可以自定义渲染内容。(了解)
  5. 注意点:
    1. 尽量不要与Vue2.x配置混用
      • Vue2.x配置(data、methos、computed...)中可以访问到setup中的属性、方法。
      • 但在setup不能访问到Vue2.x配置(data、methos、computed...)。
      • 如果有重名, setup优先。
    2. setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

代码展示:

<template>
<!-- Vue3新特性,模板结构中引用多个组件不再需要根标签(可有可无) -->
<h1>张三的信息</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>性别:{{sex}}</h2>
<button @click="sayHello">Vue2方法</button><br><br>
<button @click="sayHi">Vue3方法</button>
</template>

<script>
// 引入 h
// import { h } from '@vue/runtime-core'
export default {
name: 'App',
// Vue3全新的配置项,以往vue2的配置项(data,methods等全部配置在setup里面)
//切记,这里展示不考虑响应式
setup() {
let name = '张三'
let age = 18
function sayHi(){
console.log('Vue3的写法','Hello! Vue3');
}

// 最后通过return 返回整个对象后,里面的属性模板可以直接使用
return {
name,
age,
sayHi
}

// 也可以直接返回渲染函数,不过很少用
// return () => h('h1' , 'wyu')
},

// Vue3是向下兼容的,也可以使用Vue2的写法
data() {
return {
sex:'男'
}
},
methods: {
sayHello(){
console.log('Vue2的写法','Hello! Vue2');
}
},
}
</script>

结果展示:

  • 1.使用渲染函数返回值(return () => h('模板' , '值'))
    image
  • 2.使用对象返回值
    image
    image

2.ref函数(与vue2中的ref属性是不一样的)

  • 作用: 定义一个响应式的数据
  • 语法: const xxx = ref(initValue)
    • 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)
    • JS中操作数据: xxx.value
    • 模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>
  • 备注:
    • 接收的数据可以是:基本类型、也可以是对象类型。
    • 基本类型的数据:响应式依然是靠Object.defineProperty()getset完成的。
    • 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数。

代码展示:

<template>
<!-- Vue3新特性,模板结构中引用多个组件不再需要根标签(可有可无) -->
<h1>张三的信息</h1>
<!-- (ref函数)模板中读取数据: 不需要.value,直接调属性名 -->
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>工作种类:{{job.type}}</h2>
<h2>薪水:{{job.salary}}</h2>
<button @click="changeInfo">更改信息</button><br><br>
</template>

<script>
// 引入ref函数
import {ref} from 'vue'
export default {
name: 'App',
// Vue3全新的配置项,以往vue2的配置项(data,methods等全部配置在setup里面)
setup() {
// 这里的变量赋值不能写死(响应式是依靠ref函数来实现的)
// let name = '张三'
// let age = 18

// 正确写法(基本数据类型)
let name = ref('张三')
let age = ref(18)

// 对象数据类型
let job = ref({
type:'前端工程师',
salary: 1000
})


function changeInfo(){
//切记,这里是使用的是ref读取的对象,所以要加.value
console.log(name , age , job.value);
// 因为ref函数返回的是一个引用实现对象,所以现有修改引用实现对象里面的值就需要使用.value
name.value = '李四'
age.value = '20'

//实现对象的ref函数修改,返回的是proxy对象,不再是refimp对象
job.value.type = '泥水匠'
job.value.salary = 2000
}
// 最后通过return 返回整个对象后,里面的属性模板可以直接使用
return {
name,
age,
job,
changeInfo
}
},
}
</script>

结果展示:

image
image

3. reactive函数(相较于ref读取对象更为方便简单)

  • 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
  • 语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
  • reactive定义的响应式数据是“深层次的”(即无论你的对象里面嵌套多少个对象,都可以读取到)。
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

代码展示:

<template>
<h1>一个人的信息</h1>
<!-- 这里读取reactive函数封装的对象属性时更加语义化 -->
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h3>工作种类:{{person.job.type}}</h3>
<h3>工作薪水:{{person.job.salary}}</h3>
<h3>爱好:{{person.hobby}}</h3>
<h3>测试的数据c:{{person.job.a.b.c}}</h3>
<button @click="changeInfo">修改人的信息</button>
</template>
<script>
// 引入reactive函数
import {reactive} from 'vue'
export default {
name: 'App',
setup(){
//数据(相较于ref函数一个一个的读取属性,reactive函数将变量封装成一个对象,更加简洁)
let person = reactive({
name:'张三',
age:18,
job:{
type:'前端工程师',
salary:'30K',
// reactive函数是深层次的读取,无论你对象套的有多深
a:{
b:{
c:666
}
}
},
// reactive函数还可以读取和修改数组
hobby:['抽烟','喝酒','烫头']
})
//方法
function changeInfo(){
console.log(person);
// 使用reactive函数修改响应式属性时不再需要.value
person.name = '李四'
person.age = 48
person.job.type = '泥水匠'
person.job.salary = '2000'
person.job.a.b.c = 999
person.hobby[0] = '学习'

// 使用ref函数修改属性时
// person.value.属性(过于复杂)
}

//返回一个对象(常用)
return {
person,
changeInfo
}
}
}
</script>

结果展示:

image
image

reactive对比ref(实际开发中,reactive用得较多)

  • 从定义数据角度对比:
    • ref用来定义:基本类型数据
    • reactive用来定义:对象(或数组)类型数据
    • 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象
  • 从原理角度对比:
    • ref通过Object.defineProperty()getset来实现响应式(数据劫持)。
    • reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
  • 从使用角度对比:
    • ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value
    • reactive定义的数据:操作数据与读取数据:均不需要.value