1.【OptionAPI】与【compositionAPI】
- vue2的API设计是Option(选项式)风格的
- vue3的API设计是Composition(组合式)风格的。
Option API的弊端:
option类型的API,数据,方法,计算属性等,是分散在:data,methods,computed中的,若想新增或修改一个需求,就需要分别修改:data.methods,computed,不便于维护和复用
通俗点理解就是:vue2的Option是将功能拆散在不同的配置项里面
Composition API的优势:
可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组合在一起。
2.拉开序幕的setup
why:vue3里面有很多组合式的API,这些组合式的API几乎都要写在setup里面,因此学习vue3的第一步就是学习setup。
setup概述:setup是vue3中一个新的配置项,值是一个函数
<script lang="ts">
export default {
name:'Person',
setup(){
// 注意:setup函数中的this是undefined
// vue3 里面setup的执行时机比beforeCreate还要早
// 数据
let name = '张三'//注意:此时不是响应式的
let age = '18'
let tel ='1111'
//方法
function changeAge(){
name = 'zhangsan'
}
function changeName(){
age += 1
}
function showTel(){
alert(tel)
}
// return {
// name:name,
// age:age
// }
//将数据,方法交出去,模板中才可以使用
//返回值简写为:
return{
name,
age,
changeAge,
changeName,
showTel
}
//setup的返回值也可以是一个渲染函数
// return function(){
// return '哈哈'
// }
// 可以改成
// return ()=>{
// return '哈哈'
// }
//简写为:
//return()=>'哈哈'
}
}
</script>
3.setup和optionApi的关系
vue3的setup和正常写data,methods有什么关系?data里面能否读取setup里面的数据
data,method和setup是可以同时存在,setup是最早的那个生命周期,比data执行的要早,所以收当data去配置数据的时候,setup早已解析完毕了,所以在data中是可以读取到setup中的数据的,但是setup是读取不到data中的数据的
4.setup语法糖
<template>
<div class="person">
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
}
</script>
<script lang="ts" setup>
let name = 'zhangsan'
let age = 18
</script>
<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button{
margin: 0 5px;
}
</style>
扩展:上述代码,还需要编写一个不写setup
的script
标签,去指定组件名字,比较麻烦,我们可以借助vite
中的插件简化
第一步
npm i vite-plugin-vue-setup-extend -D
第二步:安装成功之后,在vite.config.ts文件里面引入
第三步:
<script setup lang="ts" name="Person">
补充:安装开发者工具:浏览器搜索极简工具Vue.js Devtools_6.5.1_Chrome插件下载_极简插件 (zzzmh.cn)
5.【ref 创建:基本类型和对象类型的响应式数据】
-
作用:定义响应式变量。
-
语法:
let xxx = ref(初始值)
。 -
返回值:一个
RefImpl
的实例对象,简称ref对象
或ref
,ref
对象的value
属性是响应式的。 -
注意点:
-
JS
中操作数据需要:xxx.value
,但模板中不需要.value
,直接使用即可。 -
对于
let name = ref('张三')
来说,name
不是响应式的,name.value
是响应式的。 -
其实
ref
接收的数据可以是:基本类型、对象类型。 -
若
ref
接收的是对象类型,内部其实也是调用了reactive
函数。 -
<template> <div class="person"> <h2>姓名:{{ name }}</h2> <h2>年龄:{{ age }}</h2> <button @click="changeAge">修改年龄</button> <button @click="changeName">修改名字</button> <button @click="showTel">显示电话</button> </div> </template> <script lang="ts" setup name="Person"> import {ref} from 'vue' let name = ref('张三') let age = ref(18) let tel ='1111' console.log(1,name) console.log(2,tel) function changeAge(){ name.value = 'zhangsan' } function changeName(){ age.value += 1 } function showTel(){ alert(tel) } let car = ref({brand:'奔驰',price:100}) let games = ref([ {id:'sater-1',name:'王者荣耀'}, {id:'sater-2',name:'原始'}, {id:'sater-3',name:'三座'} ]) console.log(car) function changePrice(){ car.value.price += 10 } function chageFirst(){ games.value[0].name="吃鸡" } </script> <style> .person{ background-color: skyblue; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } button{ margin: 0 5px; } </style>
6.【reactive 创建:对象类型的响应式数据】
-
作用:定义一个响应式对象(基本类型不要用它,要用
ref
,否则报错) -
语法:
let 响应式对象= reactive(源对象)
。 -
返回值:一个
Proxy
的实例对象,简称:响应式对象。 -
注意点:
reactive
定义的响应式数据是“深层次”的。<template> <div class="person"> <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2> <h2>游戏列表:</h2> <ul> <li v-for="g in games" :key="g.id">{{ g.name }}</li> </ul> <h2>测试:{{obj.a.b.c.d}}</h2> <button @click="changeCarPrice">修改汽车价格</button> <button @click="changeFirstGame">修改第一游戏</button> <button @click="test">测试</button> </div> </template> <script lang="ts" setup name="Person"> import { reactive } from 'vue' // 数据 let car = reactive({ brand: '奔驰', price: 100 }) let games = reactive([ { id: 'ahsgdyfa01', name: '英雄联盟' }, { id: 'ahsgdyfa02', name: '王者荣耀' }, { id: 'ahsgdyfa03', name: '原神' } ]) let obj = reactive({ a:{ b:{ c:{ d:666 } } } }) function changeCarPrice() { car.price += 10 } function changeFirstGame() { games[0].name = '流星蝴蝶剑' } function test(){ obj.a.b.c.d = 999 } </script>
7.对比ref和reactive:
宏观角度看:
-
ref
用来定义:基本类型数据、对象类型数据; -
reactive
用来定义:对象类型数据。
-
-
区别:
-
-
ref
创建的变量必须使用.value
(可以使用volar
插件自动添加.value
)。 -
reactive
重新分配一个新对象,会失去响应式(可以使用Object.assign
去整体替换)。
-
-
使用原则:
-
-
若需要一个基本类型的响应式数据,必须使用
ref
。 -
若需要一个响应式对象,层级不深,
ref
、reactive
都可以。 -
若需要一个响应式对象,且层级较深,推荐使用
reactive
。
-
-
8.computed计算属性
作用:根据已有数据计算出新数据(和Vue2
中的computed
作用一致)。
区别:vue3里面使用computed计算属性只需要从vue中引入即可
<template>
<div class="person">
姓:<input type="text" v-model="firstName">
名:<input type="text" v-model="lastName">
全名:<span>{{ fullName }}</span>
<br>
<button @click="changeFullName()">将全名改为lisi</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {computed, ref, watch} from 'vue'
let firstName = ref('zhang')
let lastName = ref('san')
//如果想让首字母大写出现在页面上
// 如此定义的fullName是只读的
// let fullName =computed(()=>{
// return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+lastName.value
// })
// 这么定义的fullName是一个计算属性,可读可写
let fullName =computed({
// 什么时候读fullName什么时候就调get
get(){
return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+lastName.value
},
// 什么时候改fullName,什么时候就调set
set(val){
let [str1,str2] = val.split('-')
firstName.value = str1
lastName.value = str2
console.log('set')
}
})
// 这个方法只是引起set的调用
function changeFullName(){
fullName.value ='li-si'
}
</script>
<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button{
margin: 0 5px;
}
</style>
9.watch监视
vue3中的watch只能监视以下四种数据
1.ref定义的数据
2.reactive定义的数据
3.函数返回一个值(getter函数)
4.一个包含上述内容的数组
情况一:监视ref定义的数据
<template>
<div class="person">
<h1>情况一:监视ref定义的基本类型数据</h1>
<h2>当前求和为{{ sum }}</h2>
<button @click="addSum()">点我sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
let sum =ref(0)
function addSum(){
sum.value += 1
}
// watch(谁?,回调函数){
// }
watch(sum,(newVal,oldVal)=>{
console.log('sum变化了',newVal,oldVal)
})
</script>
<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button{
margin: 0 5px;
}
</style>
运行效果如图: