vue3核心语法
一.OptionsAPI与CompositionAPI
Vue2的API设计是Options(配置)风格的。
弊端:
Options类型的 API,数据、方法、计算属性等,是分散在:data、methods、computed中的,若想新增或者修改一个需求,就需要分别修改:data、methods、computed,不便于维护和复用。
Vue3的API设计是Composition(组合)风格的。
优势:
可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。
二.setup概述
setup值是一个函数,组件中所用到的:数据、方法、计算属性、监视…等,均配置在setup中。
特点:
- setup函数返回的对象中的内容,可直接在模板中使用。
- setup中访问this是undefined。
- setup函数会在beforeCreate之前调用,它是“领先”所有钩子执行的。
使用
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
setup(){
// 数据,原来写在data中(注意:此时的name、age、tel数据都不是响应式数据)
let name = '张三'
let age = 18
let tel = '13888888888'
// 方法,原来写在methods中
function changeName(){
name = 'zhang-san' //注意:此时这么修改name页面是不变化的
console.log(name)
}
function changeAge(){
age += 1 //注意:此时这么修改age页面是不变化的
console.log(age)
}
function showTel(){
alert(tel)
}
// 返回一个对象,对象中的内容,模板中可以直接使用
return {name,age,tel,changeName,changeAge,showTel}
}
}
</script>
</script>
setup 与 Options API 的关系
- Vue2 的配置(data、methos…)中可以访问到 setup中的属性、方法。
- 但在setup中不能访问到Vue2的配置(data、methos…)。
- 如果与Vue2冲突,则setup优先。
setup语法糖
script标签上添加setup
不用每次返回数据
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changName">修改名字</button>
<button @click="changAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
}
</script>
<!-- 下面的写法是setup语法糖 -->
<script setup lang="ts">
console.log(this) //undefined
// 数据(注意:此时的name、age、tel都不是响应式数据)
let name = '张三'
let age = 18
let tel = '13888888888'
// 方法
function changName(){
name = '李四'//注意:此时这么修改name页面是不变化的
}
function changAge(){
console.log(age)
age += 1 //注意:此时这么修改age页面是不变化的
}
function showTel(){
alert(tel)
}
</script>
扩展
上述代码,还需要编写一个不写setup的script标签,去指定组件名字,比较麻烦,我们可以借助vite中的插件简化。组件名字写script 标签上
- 第一步安装插件:npm i vite-plugin-vue-setup-extend -D
- 第二步引入:vite.config.ts
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [ VueSetupExtend() ]
})
第三步:<script setup lang=“ts” name=“Person”
三.ref和reactive创建响应式数据
(1).ref创建基本类型的响应式数据
语法:let xxx = ref(初始值)。
返回值:一个RefImpl的实例对象,简称ref对象或ref,ref对象的value属性是响应式的。
注意点:
tS中操作数据需要:xxx.value,但模板中不需要.value,直接使用即可。
何时需要.value?模板中不需要;包裹在响应式对象里面的ref不需要;未包裹的ref需要。
对于let name = ref(‘张三’)来说,name不是响应式的,name.value是响应式的。
(2).reactive创建对象类型的响应式数据
基本类型不能用
语法:let 响应式对象= reactive(源对象)。
返回值:一个Proxy的实例对象,简称:响应式对象。
注意点:reactive定义的响应式数据是“深层次”的。
(3).ref创建对象类型的响应式数据
- 其实ref接收的数据可以是:基本类型、对象类型。
- 若ref接收的是对象类型,内部其实也是调用了reactive函数。
(4).ref对比reactive
- ref创建的变量必须使用.value(可以使用volar插件自动添加.value)
- reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。
function changeCar(){
// car = {brand:'奥拓',price:1} //这么写页面不更新的
// car = reactive({brand:'奥拓',price:1}) //这么写页面不更新的
// 下面这个写法页面可以更新
Object.assign(car,{brand:'奥拓',price:1})
}
四.toRefs和toRef
作用:将一个响应式对象中的每一个属性,转换为ref对象。并且改变解构的值,也会影响到原响应式对象的值。
备注:toRefs与toRef功能一致,但toRefs可以批量转换。
// 数据
let person = reactive({name:'张三', age:18, gender:'男'})
// 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
//改变name和gender的值,也会影响到person里面的值
let {name,gender} = toRefs(person)
// 通过toRef将person对象中的age属性取出,且依然保持响应式的能力
let age = toRef(person,'age')
五.computed
作用:根据已有数据计算出新数据
实现相同的功能,function没有缓存,模板调用几次,函数就执行几次。
计算属性computed有缓存,模板调用多次,实际上只执行一次。
计算属性实际上是一个ref响应式对象,因此赋值的时候需要加上.value
可以只读取不修改,也可以既读取又修改
<template>
<div class="person">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
全名:<span>{{fullName}}</span> <br>
全名:<span>{{fullName}}</span> <br>
<button @click="changeFullName">全名改为:li-si</button>
</div>
</template>
<script setup lang="ts" name="App">
import {ref,computed} from 'vue' //引入computed
let firstName = ref('zhang')
let lastName = ref('san')
// 计算属性——只读取,不修改
//里面是箭头函数
/* let fullName = computed(()=>{
return firstName.value + '-' + lastName.value
}) */
// 计算属性——既读取又修改
//里面是对象
let fullName = computed({
// 读取
get(){
return firstName.value + '-' + lastName.value
},
// 修改
set(val){
console.log('有人修改了fullName',val)
firstName.value = val.split('-')[0]
lastName.value = val.split('-')[1]
//第二种写法
//const [str1,str2] = val.split('-')
//firstName.value = str1
//lastName.value = str2
}
})
function changeFullName(){
fullName.value = 'li-si' //引起set的val变化
}
</script>