Vue3-API
- 其它 API
- 【shallowRef 与 shallowReactive 】
- shallowRef
- shallowReactive
- 总结
- 【readonly 与 shallowReadonly】
- readonly
- shallowReadonly
- 【toRaw 与 markRaw】
- toRaw
- markRaw
- 【customRef】
- Vue3新组件
- 【Teleport】
- 【Suspense】
- 【全局API转移到应用对象】
- 【其他】
其它 API
【shallowRef 与 shallowReactive 】
shallowRef
-
作用:创建一个响应式数据,但只对顶层属性进行响应式处理。
浅层次的ref:只处理第一层的数据
-
用法:
import {shallowRef} from 'vue' let myVar = shallowRef(initialValue); myVar.value
-
特点:只跟踪引用值的变化,不关心值内部的属性变化。
-
作用
- 示例
<template>
<div class="app">
<h2>求和为:{{ sum }}</h2>
<h2>名字为:{{ person.name }}</h2>
<h2>年龄为为:{{ person.age }}</h2>
<button @click="changeSum">sum+1</button>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改整个人</button>
</div>
</template>
<script lang="ts" setup name="App">
import {ref, shallowRef} from 'vue'
let sum = shallowRef(0)
let person = shallowRef({
name: '张三',
age: 18
})
function changeSum() {
sum.value += 1
}
function changeName() {
person.value.name = '李四'
}
function changeAge() {
person.value.age = 20
}
function changePerson() {
person.value = {name: 'tony', age: 100}
}
shallowReactive
-
作用:创建一个浅层响应式对象,只会使对象的最顶层属性变成响应式的,对象内部的嵌套属性则不会变成响应式的
-
用法:
const myObj = shallowReactive({ ... });
-
特点:对象的顶层属性是响应式的,但嵌套对象的属性不是。
总结
通过使用
shallowRef()
和shallowReactive()
来绕开深度响应。浅层式API
创建的状态只在其顶层是响应式的,对所有深层的对象不会做任何处理,避免了对每一个内部属性做响应式所带来的性能成本,这使得属性的访问变得更快,可提升性能。
【readonly 与 shallowReadonly】
readonly
-
作用:用于创建一个对象的只读副本。
-
用法:ref、reactive都可以用
// 可以用在 ref reactive 上 import { reactive,readonly } from 'vue' const original = reactive({ ... }); const readOnlyCopy = readonly(original); import { ref,readonly } from 'vue' const o = ref({ ... }); const readOnlyCopy = readonly(original);
-
特点:
- 对象的所有嵌套属性都将变为只读。
- 任何尝试修改这个对象的操作都会被阻止(在开发模式下,还会在控制台中发出警告)。
-
应用场景:
- 创建不可变的状态快照。
- 保护全局状态或配置不被修改。
-
注意不是一锤子买卖,原本关联的数据变化它也会变,但是单独对其修改就不可以
- 示例
<template>
<div class="app">
<h2>当前sum1为:{{ sum1 }}</h2>
<h2>当前sum2为:{{ sum2 }}</h2>
<button @click="changeSum1">sum1+1</button>
<button @click="changeSum2">sum2+1</button>
</div>
</template>
<script setup lang="ts" name="App">
import { ref,readonly } from 'vue'
let sum1 = ref(0)
let sum2 = readonly(sum1) // 这里会自动补上 .value,但是不可以
// 要求必须是响应式对象
function changeSum1 (){
sum1.value += 1
}
function changeSum2 (){
sum2.value += 1 // 这一行会报错
}
</script>
shallowReadonly
-
作用:与
readonly
类似,但只作用于对象的顶层属性。 -
用法:
const original = reactive({ ... }); const shallowReadOnlyCopy = shallowReadonly(original);
-
特点:
-
只将对象的顶层属性设置为只读,对象内部的嵌套属性仍然是可变的。
-
适用于只需保护对象顶层属性的场景。
-
【toRaw 与 markRaw】
toRaw
-
作用:用于获取一个响应式对象的原始对象,
toRaw
返回的对象不再是响应式的,不会触发视图更新。官网描述:这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。
何时使用? —— 在需要将响应式对象传递给非
Vue
的库或外部系统时,使用toRaw
可以确保它们收到的是普通对象 -
具体编码:
import { reactive,toRaw,markRaw,isReactive } from "vue"; /* toRaw */ // 响应式对象 let person = reactive({name:'tony',age:18}) // 原始对象 let rawPerson = toRaw(person)
markRaw
-
作用:标记一个对象,使其永远不会变成响应式的。
-
编码:
import { reactive,markRaw,isReactive } from "vue"; /* markRaw */ // 比如 中国直辖城市就这几个,不发生改变 let citysd = markRaw([ {id:'asdda01',name:'北京'}, {id:'asdda02',name:'上海'}, {id:'asdda03',name:'天津'}, {id:'asdda04',name:'重庆'} ]) // 根据原始对象citys去创建响应式对象citys2 —— 【!创建失败】,因为citys被markRaw标记了 let citys2 = reactive(citys) console.log(isReactive(citys)) console.log(isReactive(citys2))
-
使用场景:例如使用
mockjs
时,为了防止误把mockjs
变为响应式对象,可以使用markRaw
去标记mockjs
① npm i mockjs
import mockjs from 'mockjs'
let mockJs = markRaw(mockjs)
【customRef】
作用:创建一个自定义的ref
,并对其依赖项跟踪和更新触发进行逻辑控制。
<template>
<div class="app">
<h2>{{ msg }}</h2>
<input type="text" v-model="msg">
</div>
</template>
<script setup lang="ts" name="App">
import {ref,customRef} from 'vue'
// import useMsgRef from './useMsgRef'
//(1)
// 使用Vue提供的默认ref定义响应式数据,数据一变,页面就更新
// let msg = ref('你好')
//(2)
// 使用Vue提供的 customRef 定义响应式数据
let initValue = '你好'
// track跟踪 trigger触发
let msg = customRef((track,trigger)=>{
return {
// msg被读取的时候调用get
get(){
track() //告诉vue数据msg很重要.你要对msg持续关注,一旦msg变化就去更新
//getter要返回值
return initValue
},
// msg被修改时调用set
set(value){
initValue = value
trigger() // 通知vue数据msg变化了
}
}
})
</script>
一般会把自定义ref(custonRef)封装到hooks中
实现防抖效果(useSumRef.ts
):
import {customRef } from "vue";
// 初始值 和 延迟时间 由外部定义
export default function(initValue:string,delay:number){
let msg = customRef((track,trigger)=>{
let timer:number
return {
get(){
track() // 告诉Vue数据msg很重要,要对msg持续关注,一旦变化就更新
return initValue
},
set(value){
clearTimeout(timer)
timer = setTimeout(() => {
initValue = value
trigger() //通知Vue数据msg变化了
}, delay);
}
}
})
return {msg}
}
Vue3新组件
【Teleport】
-
什么是Teleport?传送门的意思
—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。
引入:我们自定义了一个模态框组件,希望点击之后它弹出来。但是有时候因为父组件的一些CSS设置,position定位会不准。如果用 <teleport to='body' >
就可以解决这个问题。
to后面可以直接写body,定位到HTML中的body,或者类选择器 ID选择器 to=“.demo” to=“#app”
<teleport to='body' >
<div class="modal" v-show="isShow">
<h2>我是一个弹窗</h2>
<p>我是弹窗中的一些内容</p>
<button @click="isShow = false">关闭弹窗</button>
</div>
</teleport>
【Suspense】
- 等待异步组件时渲染一些额外内容,让应用有更好的用户体验
- 使用步骤:
- 异步引入组件
- 使用
Suspense
包裹组件,并配置好default
与fallback
<script setup lang="ts" name="App">
import {Suspense} from 'vue'
import Child from './Child.vue'
</script>
<template>
<div class="app">
<h3>我是App组件</h3>
<Suspense>
<template v-slot:default>
<Child/>
</template>
<template v-slot:fallback>
<h3>加载中.......</h3>
</template>
</Suspense>
</div>
</template>
-
示例
子组件有异步任务(以网络请求为例)
直接得到 axios 的结果可以用 await,但是 外层函数本应该需要 async,如下文所示,没有外层函数。setup语法糖没法加上 async,此时顶级async就不用管了,还是会拿到结果的。
但是问题出在页面上无法呈现子组件(收到了异步任务的影响)
<template> <div class="child"> <h2>我是Child组件</h2> <h3>当前求和为:{{ sum }}</h3> </div> </template> <script setup lang="ts"> import {ref} from 'vue' import axios from 'axios' let sum = ref(0) let {data:{content}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json') console.log(content) </script>
父组件:
default:异步任务成功时呈现。fallback:异步任务失败的时候呈现。
<template> <div class="app"> <h2>我是App组件</h2> <Suspense> <!--suspense包裹--> <template v-slot:default> <!--插槽实现--> <Child/> </template> <template v-slot:fallback> <!--插槽实现--> <h2>加载中......</h2> </template> </Suspense> </div> </template> <script setup lang="ts" name="App"> import {Suspense} from 'vue' import Child from './Child.vue' </script>
【全局API转移到应用对象】
-
app.component
:vue3注册全局组件在vue2中 Vue.component注册全局组件
在vue3中 注册全局组件 app.component(main.ts)
-
app.config
配置对象app.config.globalProperties.x = 9 全局属性
-
app.directive
注册全局指令
<h4 v-beauty>好开心</h4>
-
app.mount
-
app.unmount
卸载 -
app.use
安装插件pinia vue-router
【其他】
看官网中的非兼容性区别
https://v3-migration.vuejs.org/zh/breaking-changes/
-
过渡类名
v-enter
修改为v-enter-from
、过渡类名v-leave
修改为v-leave-from
。 -
keyCode
作为v-on
修饰符的支持。 -
v-model
指令在组件上的使用已经被重新设计,替换掉了v-bind.sync。
-
v-if
和v-for
在同一个元素身上使用时的优先级发生了变化。 -
移除了
$on
、$off
和$once
实例方法。 -
移除了过滤器
filter
。 -
移除了
$children
实例propert
。…