vue3中基本类型和对象类型的响应式数据
OptionsAPI与CompstitionAPI的区别
OptionsAPI
Options API
• 特点:基于选项(options)来组织代码,将逻辑按照生命周期、数据、方法等分类。• 结构:代码按照 data 、 methods 、 computed 、 watch 等选项分块。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default{
name:'Person',
data(){
return{
name:'小聂',
age:18,
tel:'1598744444'
}
},
methods:{
updataName(){
this.name='xiao-nie'
},
updataAge(){
this.age+=1
},
showTel(){
alert(this.tel)
}
}
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
点击之后页面进行了修改
CompstitionAPI
Composition API
• 特点:基于函数组合(composition)来组织代码,将逻辑按照功能模块划分。
• 结构:代码通过 setup 函数组织,使用 ref 、 reactive 、 computed 、 watch 等函数来定义响应式数据和逻辑。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default{
name:'Person',
setup(){
let name="小聂" //此时的name不是响应式的
let age=18 //此时的age不是响应式的
let tel='188844444' //此时的tel不是响应式的
function updataName(){
name="xiao-nie"
}
function updataAge(){
age+=1
}
function showTel(){
alert(tel)
}
return {name,age,tel,updataName,updataAge,showTel};
}
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
因为不是响应式的基本类型 所以点击之后页面并没有反应
OptionsAPI和CompositionAPI的优缺点
OptionsAPI优点
:
- 易学易用:对于初学者来说,Options API 的结构非常直观,代码组织方式类似于 Vue 2,学习曲线平缓。
- 易于理解:代码按照生命周期、数据、方法等选项分块,逻辑清晰,易于阅读和维护。
OptionsAPI缺点
:
2. 复用性差
- 混入(Mixins)问题:虽然可以通过混入复用逻辑,但混入可能导致命名冲突,且逻辑分散在多个地方,难以追踪。
- 组件继承问题:通过组件继承复用逻辑时,子组件可能会继承过多不必要的逻辑,导致代码臃肿。
- 复杂组件难以管理
- 逻辑分散:对于复杂组件,逻辑可能会分散在多个选项中(如 data 、 methods 、 computed 等),难以集中管理。
- 维护困难:随着组件逻辑的增加,代码的可读性和可维护性会下降。
CompositionAPI优点
:
- 高度复用性
组合函数(Composables):通过组合函数可以将逻辑模块化,便于复用和组合。逻辑清晰,避免了混入带来的命名冲突。
逻辑集中:将相关逻辑集中在一个函数中,便于管理和维护。 - 适合复杂组件
灵活的代码组织:可以将逻辑按照功能模块划分,适合复杂组件的开发。
可读性强:通过 setup 函数组织代码,逻辑更加清晰,易于理解和维护。
强大的类型支持 - TypeScript 友好:在 TypeScript 中,Composition API 提供了强大的类型推断,减少了手动声明类型的工作量,提高了开发效率。
CompositionAPI缺点
:
- 学习曲线较陡
语法复杂:对于初学者来说,Composition API 的语法和概念(如 ref 、 reactive 等)可能需要一些时间来适应。
文档和资源较少:虽然 Vue 3 的文档已经很完善,但相比 Options API,Composition API 的学习资源和社区支持相对较少。
setup返回值
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default{
name:'Person',
setup(){
let name="小聂" //此时的name不是响应式的
let age=18 //此时的age不是响应式的
let tel='188844444' //此时的tel不是响应式的
function updataName(){
name="xiao-nie"
}
function updataAge(){
age+=1
}
function showTel(){
alert(tel)
}
return ()=>"接着努力啊! 小聂!"
}
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
setup和OptionsAPI的关系
setup里面不可以调用data里面的数据 但是data可以调用setup里面的数据
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
<br>
<h2>data访问setup里的name为:{{a}}</h2>
<button @click="updataA">查看name</button>
</div>
</template>
<script lang="ts">
export default{
name:'Person',
data(){
return {
a:this.name
}
},
methods:{
updataA(){
console.log(this.a)
}
},
setup(){
let name="小聂" //此时的name不是响应式的
let age=18 //此时的age不是响应式的
let tel='188844444' //此时的tel不是响应式的
function updataName(){
name="xiao-nie"
}
function updataAge(){
age+=1
}
function showTel(){
alert(tel)
}
return {name,age,tel,updataName,updataAge,showTel};
}
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
}
</script>
<script lang="ts" setup>
let name="小聂" //此时的name不是响应式的
let age=18 //此时的age不是响应式的
let tel='188844444' //此时的tel不是响应式的
function updataName(){
name="xiao-nie"
}
function updataAge(){
age+=1
}
function showTel(){
alert(tel)
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
小提示 如果像上面这样写我们需要在加入一个script
所以我们我们可以借助vite
中的插件简化
下载插件 npm i vite-plugin-vue-setup-extend -D
更改vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
[ VueSetupExtend() ]
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})
ref 创建:基本类型的响应式数据
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="updataName">修改姓名</button>
<button @click="updataAge">修改年龄</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='188844444'
function updataName(){
name.value="xiao-nie"
}
function updataAge(){
age.value+=1
}
function showTel(){
alert(tel)
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
我们想让谁变成响应式的 我们就把他用ref包裹起来 这样他就变成了响应式的了
点击之后页面变了
reactive创建:对象类型的响应式数据
<template>
<div class="person">
<h2>有一部{{phone.name}}手机,价格为{{ phone.price }}</h2>
<button @click="changeName">修改名称</button>
<button @click="changePrice">修改价格</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive} from 'vue'
let phone=reactive({name:'小米',price:3000})
function changeName(){
phone.name="苹果"
}
function changePrice(){
phone.price+=1000
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
点击修改名称和修改价格后
当我们要进行整体替换的时候我们需要用到Object
ref创建:对象类型的响应式数据
<template>
<div class="person">
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
<button @click="changeFirst">修改第一个游戏的名称</button>
<button @click="changeTwo">修改第二个游戏的名称</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref} from 'vue'
let games=ref([
{id:"1",name:"英雄联盟"},
{id:"2",name:"CSGO"},
{id:"3",name:"无畏契约"}
])
function changeFirst(){
games.value[0].name='王者荣耀'
}
function changeTwo(){
games.value[2].name='金铲铲之战'
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
点击修改后 我们可以看到 页面发生了改变
ref 对比 reactive
ref :既可以用来定义基本类型数据 又可以用来定义对象型类型数据
reactive:只可以用来定义对象数据
ref 创建的变量需要进行修改的时候 必须使用.value
<template>
<div class="person">
<h2>有一部{{phone.name}}手机,价格为{{ phone.price }}</h2>
<button @click="changeName">修改名称</button>
<button @click="changePrice">修改价格</button>
<button @click="changePhone">修改手机</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref} from 'vue'
let phone=ref({name:'小米',price:3000})
function changeName(){
phone.value.name="苹果"
}
function changePrice(){
phone.value.price+=1000
}
function changePhone(){
phone.value={name:"苹果",price:6000}
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
在ref中 直接修改即可
当我们点击修改手机时 页面发生了改变
reactive重新分配一个新的对象的时候 会失去响应式 我们可以使用Object.assign去整体替换
<template>
<div class="person">
<h2>有一部{{phone.name}}手机,价格为{{ phone.price }}</h2>
<button @click="changeName">修改名称</button>
<button @click="changePrice">修改价格</button>
<button @click="changePhone">修改手机</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive} from 'vue'
let phone=reactive({name:'小米',price:3000})
function changeName(){
phone.name="苹果"
}
function changePrice(){
phone.price+=1000
}
function changePhone(){
Object.assign(phone,{name:"苹果",price:"6000"})
}
</script>
<style>
.person{
background-color: rebeccapurple;
box-shadow: 0 0 10px;
padding: 20px;
border-radius: 10px;
}
button{
margin: 0 6px;
}
</style>
点击修改手机后 页面发生了改变