vue3核心语法
- 一.OptionsAPI与CompositionAPI
- 二.setup概述
- 三.ref和reactive创建响应式数据
- (1).ref创建基本类型的响应式数据
- (2).reactive创建对象类型的响应式数据
- (3).ref创建对象类型的响应式数据
- (4).ref对比reactive
- 四.toRefs和toRef
- 五.computed
一.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 = 18let 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 = 18let 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' //引入computedlet 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>