setup 中实现响应式数据
<template>
<img alt="Vue logo" src="./assets/logo.png">
<h2>a:{{a}}</h2>
<button @click="add">vue3</button>
</template>
<script>
import { defineComponent,reactive,ref } from 'vue';
export default defineComponent({
name: 'App',
setup(){
//ref的作用为定义一个响应式的数据 返回的是一个Ref对象 对象中有一个value属性存着()中的值
let a= ref(2)
//reactive 创建一个响应式的对象
let b=reactive({x:1,y:2})
// heml模板中不需要使用 .value属性
const add=()=>{
a.value++
b.x++
}
/*function add(){
a.value++
b.x++
}*/
return{
a,add,b
}
}
});
</script>
setup是在beforeCreate之前执行 所以this为undefined
以下在setup中使用均需进行引入
import { computed, defineComponent,watch, reactive, ref } from 'vue'
setup(props,context){} ()中的属性
//父
//html
<He2 :a=a b=1 :xxx='aaa'></He2>
//script
setup(){
let a=ref(2)
const aaa=()=>{
a.value++
}
return{a,aaa}
}
//子
//html
<h2>{{a}}</h2>
<button @click="onxxx">add</button>
//script
setup(props,context){
//props为在props:[]中定义的属性的对象集 例props=['a','b'] props=Proxy {a: 2 , b:1}
//context中有attrs emit slots
//attrs:未在props中定义接受的所有对象
//emit:分发从父级接收的事件
//slots: 插槽对象
const onxxx=()=>{
context.emit('xxx') //当触发onxxx事件时,执行父组件传来的xxx事件
}
return{onxxx}
}
setup中的计算属性computed
setup(){
let user=reactive({
fname:'东方',
lname:'不败'
})
// computed(()=>{}) 只有一个回调函数则为get computed({get(){},set(){}}) get set均有
const newuser= computed (()=>{
return user.fname+'_'+user.lname //返回 拼接后的字符串
})
const newuser1=computed({
get(){
return user.fname+'_'+user.lname //功能同上
},
set(val:string){
const name=val.split('_') //将更改的值转为数组以 _ 分隔
// console.log(name);
user.fname=name[0] //重新赋值
user.lname=name[1]
}
})
return{user,newuser,newuser1}
}
})
setup中watch 监视
let user=reactive({
fname:'东方',
lname:'不败'
})
const refname=ref(' ')
watch(user,(val)=>{
// console.log(val); 值为Proxy {fname: '东方', lname: '不败'}
refname.value=val.fname+'_'+val.lname
},{immediate:true}) // immediate:true 自动触发一次watch
//watch可监视多个数据
watch([user,xxxx],(val)=>{ })
//要监视非响应式数据
toRef
setup(){
const user=reactive({
name:'zs',
age:20
})
return{...toRefs(user)} //此时返回的为 name age
//toRefs可对对象进行分解 且不丢失响应式的特性 ...user会成为非响应式数据
}
通过ref获得html元素
<input type="text" ref="inputref">
setup(){
const inputref=ref<HTMLElement|null>(null) //名与上述ref='xx' 中的值相同
onMounted(()=>{
inputref.value && inputref.value.focus() //自动获得焦点
})
return{
inputref
}
}
toRef
//为对象某个属性创建一个ref对象,两者操作的是同一个数据,更新时会同步更新
//和ref的区别为 更改通过ref创建的数据不会影响原数据
//在 自用于父传子 props时尤其好用 会动态改变
setup(){
const user=reactive({
name:'李虎',
age:20
})
const name=toRef(user,'name')
let age=toRef(user,'age')
const updata=()=>{
user.name='zs' // 此时 name='zs'
age.value=30 // 此时 user.age=30
}
return {
user,name,age,updata
}
customRef((track,trigger)=>)}{} 实现防抖
//(1)customRef 用于自定义返回一个ref对象,可以显式地控制依赖追踪和触发响应,接受工厂函数
//(2)两个参数分别是用于追踪的 track 与用于触发响应的 trigger,并返回一个一个带有 get 和 set 属性的对象
<template>
<input type="text" v-model="data">
<h3>{{data}}</h3>
</template>
<script lang="ts">
import { customRef, defineComponent ,ref} from 'vue'
function data1<t,x>(a:t,wait:number){ //传入数据及等待时间
let timer:number
return customRef((tarck,trigger)=>{
return{
get(){
tarck() //追踪当前数据
return a
},
set(nval:t){
clearTimeout(timer)
timer=setTimeout(()=>{
a=nval
trigger() //触发响应 即更新页面
},wait)
}
}
})
}
export default defineComponent({
setup(){
const data=data1('abc',220)
return{data}
}
})
</script>
provide和 inject 多用于多级嵌套 爷孙及孙孙等数据通信
//爷
setup(){
const a=ref('red')
provide('color',a) //子类组件中使用color属性名来接收a的值
return{a}
},
//子孙组件
setup(){
const color= inject('color') //通过inject 来接受爷组件传来的值 并将其赋给color
return {color}
}
Teleport(瞬移)让组件的html渲染到父组件界面外的特定标签(body)
// 将 1 渲染到body标签中 而不再是 id为app的div标签中
<Teleport to='body'>1</Teleport>
Suspense组件 当使用异步请求时会出现空白
<Suspense>
//v-solt:defult 默认显示
<template v-slot:default>
<Child></Child>
</template>
//v-solt:defult 加载过程中需要显示的内容
<template v-slot:fallback>
<h2>loading</h2>
</template>
</Suspense>