VUE3 操作文档
一、vue2和vue3区别
(1) Vue2简介
Vue2是Options(选项式)风格
缺陷: 1.Options 的 API,数据(data)、方法(method)、**计算属性(computed)**是分散开的
2.若修改需求则需要分别修改 Options的各API,不方便维护和复用。
(2) Vue3简介
Vue3是Composition的API(组合式式)


优势: 可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。
二、Setup
(1) setup简介
vue2中script中包含method、data、computed等API,在vue3中用setup来代替。
(2) Vue3的script框架
js
<script setup lang='ts' name='VUE3'> //此处使用ts语言
let age =18 // 数据定义(类似于Vue2中的Data数据定义)
function changeName(){ //定义函数 (类似于Vue2中的Method函数方法)
age+=1
}
//但触发该事件,页面数据不会发生改变 因为age 不是响应式
//由此介绍创建Vue3的基本响应式数据的API:"ref" 和 ""reactive""
</script>
三、Ref和Reactive
(1) Ref (基本类型数据)
js
<template>
<div class="app">
<h1>{{a}}</h1> //渲染时则不需要 '.value'
<button @click="test">点击+1</button>
</div>
</template>
<script setup lang="ts" name='app'>
import {ref} from 'vue'
let a = ref(11) //定义数据
let car =ref([ //定义数组
{id:'111',name:'a'},
{id:'222',name:'b'},
])
function test() {
a.value+=1 //ref 的响应式数据要添加 '.value'才能对他进行修改
console.log(car.value[0]) // 数组输出的格式
}
</script>
打印的数据样式为:
(2) Reactive (对象类型数据)
js
<template>
<div class="app">
<h2>一辆{{car.name}}价值{{ car.price }}万</h2>
<button @click="changePrice">点击改变价格</button>
</div>
</template>
<script setup lang="ts" name='app'>
import {ref,reactive} from 'vue'
let car = reactive({name:'迈凯伦Speedtail',price:1000})
function changePrice(){
car.price=1010 // reactive 不需要添加 ‘ .value ’
console.log(car);
}
</script>
打印的数据样式为:
注:reactive响应式数据为深层次的
js
<template>
<div class="app">
<h2>{{car.a.b.c}}</h2>
<button @click="changePrice">点击改变价格</button>
</div>
</template>
<script setup lang="ts" name='app'>
import {ref, reactive} from 'vue'
let car = reactive(
{a:{ b:{c:11} } } //多重数据
)
function changePrice(){
car.a.b.c=1010 //reactive可以修改深层次数据
console.log(car);
}
</script>
(3) Ref 与 Reactive区别
1.当reactive对象在函数中被重新定义后,将不再是响应式对象,而是普通对象。
js
let car = reactive({brand:'奔驰;,price:100}) //响应式对象
function changeCar(){
car = {brand:'法拉利',price:1} //变为普通对象
}
2.使用原则
- 若需要一个基本类型的响应式数据,必须要使用ref。
- 若需要一个响应式对象,层次不慎,ref,reactive都可以用。
- 若需要一个响应式对象,且层级较深,推荐使用reactive。
四、toRefs和Reactive
1.toRefs(定义多个数据)
js
<template>
<div class="app">
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<button @click="changePrice">点击改变价格</button>
</div>
</template>
<script setup lang="ts" name='app'>
import {toRefs,reactive} from 'vue'
let person = reactive({
name:'张三',
age:18
})
let {name,age}= person // 该命名后为普通数据
let {name,age}=toRefs(person)
//此处的值来自于person,其中一个数值发生变化时,另外一个的数值会随之改变
// toRefs命名后为响应式数据,使用上述 可以简化数据的使用
function changePrice(){
name.value+='~' //修改后,person数据也会发生改变
}
</script>
注:toRefs是把reactive里面的定义的响应式对象的每一组、单独的拿出来,再组成一个新的响应式对象.
2.toRef (定义单一)
使用方法:
js
let n1 =toRef(person,'age)
console.log(n1.value)
五、computed
computed: 计算属性有缓存效果,多处地方使用同一个参数时,不需要重复调用(为Ref定义的响应式数据)
method: 多处地方使用同一个参数时,需要重复调用
js
<template>
<div class="app">
姓名:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span><br>
全名:<span>{{fullName}}</span>
</div>
</template>
<script setup lang="ts" name='app'>
import { computed, ref } from "vue"
let firstName =ref('zhang')
let lastName =ref('san')
// 这么定义的fullName是只读的,不可修改
// 不可修改(原因解释) : 输入框修改时 变化的是firstName的值 从而影响fullName发生改变
let fullName = computed(() => {
console.log(1); // 只会输出一次 具有缓存效果 当fullName发生改变时重新调用
return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+'1'+lastName.value
})
// 这么定义的fullName是可读可写的
get(){
return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+'1'+lastName.value
},
set(){
console.log(111);
//在此需要再结构赋值 拆分开后分别给给firstName 和 lastName赋值
//fullName才会发生改变(fullName是根据firstName,lastName计算来的)
}
</script>
六、watch
作用: 监视数据的变化 (和中 作用基本一致)
特点: 只能监视以下四种数据
- ref 定义的数据
- reactive 定于的数据
- 函数返回值
- 一个包含上述内容的数值
监视 watch(参数,回调函数=>{},配置对象) watch的第一个参数是:被监视的数据 watch的第二个参数是:监视的回调 watch的第三个参数是:配置对象(deep、immediate等等.....)
情况一
监视 ref 定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。
js
<template>
<div class="person">
<h1>情况一:监视【ref】定义的【基本类型】数据</h1>
<h2>当前求和为:{{sum}}</h2>
<button @click="changeSum">点我sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
// 数据
let sum = ref(0)
// 方法
function changeSum(){
sum.value += 1
}
// 监视,情况一:监视【ref】定义的【基本类型】数据
const stopWatch = watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
if(newValue >= 10){
stopWatch()
}
})
</script>
情况二
监视 ref 定义的【对象类型】数据:直接写数据名,监视的是对象的 ,若想监视对象内部的数据,要手动开启深度监视。
js
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
// 数据
let person = ref({
name:'张三',
age:18
})
// 方法
//若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
function changeAge(){
person.value.age += 1
}
//若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
function changePerson(){
person.value = {name:'李四',age:90}
}
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:true}) //添加deep可以开启深度监视
</script>
情况三
监视reactive定义的【对象类型】数据,且默认开启了深度监视。
js
<template>
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let obj = reactive({
a:{
b:{
c:666
}
}
})
// 方法
function test(){
obj.a.b.c = 888
}
// 监视,情况三:监视【reactive】定义的【对象类型】数据
// 且默认是开启深度监视的。并且无法关闭
watch(obj,(newValue,oldValue)=>{
console.log('Obj变化了',newValue,oldValue)
})
</script>
情况四
监视ref或reactive定义的【对象类型】数据中的某个属性,注意点如下:
js
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18,
car:{
c1:'奔驰',
c2:'宝马'
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changeC1(){
person.car.c1 = '奥迪'
}
function changeC2(){
person.car.c2 = '大众'
}
//如果不用()=>person.car的函数式 监视的不是地址值 则监视不到变化
function changeCar(){
person.car = {c1:'雅迪',c2:'爱玛'}
}
// 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
//函数式:getter函数(能返回值的函数)-> ()=>属性
//例:watch(()=> person.name,(newValueoldValue)=>{})
// 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
watch(()=>person.car,(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
</script>
情况五
js
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18,
car:{
c1:'奔驰',
c2:'宝马'
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changeC1(){
person.car.c1 = '奥迪'
}
function changeC2(){
person.car.c2 = '大众'
}
function changeCar(){
person.car = {c1:'雅迪',c2:'爱玛'}
}
// 监视,情况五:监视上述的多个数据 用数组形式填写到监视参数位置
watch([()=>person.name,person.car],(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
</script>
七、watchEffect
- 官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
- watch对比watchEffect
html
1.都能监听响应式数据的变化,不同的是监听数据变化的方式不同
2.watch:要明确指出监视的数据
3.watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。 //自动监视
- 案例
js
<script lang="ts" setup name="Person">
import {ref,watch,watchEffect} from 'vue'
// 用watch实现,需要明确的指出要监视:temp、height
watch([temp,height],(value)=>{
// 从value中获取最新的temp值、height值
const [newTemp,newHeight] = value
// 室温达到50℃,或水位达到20cm,立刻联系服务器
if(newTemp >= 50 || newHeight >= 20){
console.log('联系服务器')
}
})
// 用watchEffect实现,不用 (自动监视)
const stopWtach = watchEffect(()=>{
// 室温达到50℃,或水位达到20cm,立刻联系服务器
if(temp.value >= 50 || height.value >= 20){
console.log(document.getElementById('demo')?.innerText)
console.log('联系服务器')
}
// 水温达到100,或水位达到50,取消监视
if(temp.value === 100 || height.value === 50){
console.log('清理了')
stopWtach()
}
})
</script>
八、ref
- 组件标签
js
<!-- 父组件App.vue -->
<template>
<Person ref="ren"/>
<button @click="test">测试</button>
</template>
<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import {ref} from 'vue'
let ren = ref() //给打上标签
function test(){// 获取子组件用defineExpose暴露的数据
console.log(ren.value.name)
console.log(ren.value.age)
}
</script>
<!-- 子组件Person.vue中要使用defineExpose暴露内容 -->
<script lang="ts" setup name="Person">
import {ref,defineExpose} from 'vue'
// 数据
let name = ref('张三')
let age = ref(18)
// 使用defineExpose将组件中的数据交给外部
defineExpose({name,age})
</script>
- 普通DOM标签
js
<template>
<div class="person">
<h1 ref="title1">尚硅谷</h1>
<h2 ref="title2">前端</h2>
<h3 ref="title3">Vue</h3>
<input type="text" ref="inpt"> <br><br>
<button @click="showLog">点我打印内容</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref} from 'vue'
let title1 = ref()
let title2 = ref()
let title3 = ref()
function showLog(){
// 通过id获取元素
const t1 = document.getElementById('title1')
// 打印内容
console.log((t1 as HTMLElement).innerText)
console.log((<HTMLElement>t1).innerText)
console.log(t1?.innerText)
// 通过ref获取元素
console.log(title1.value)
console.log(title2.value)
console.log(title3.value)
}
</script>