vue3 新特性详解(2)


自定义Hook函数

什么是hook?
本质是一个函数,把setup函数中使用的Compostion Api 进行了封装,类似于vue2中的mixin.
自定义hook的优势是复用了代码,让setup中的逻辑更清楚易懂。

实例:在多个页面中获取鼠标点击的坐标。
hook/index.ts

import {
    
     reactive,onMounted,onBeforeUnmount } from 'vue';
export default function () {
    
    
	    let print = reactive({
    
    
			x:0,y:0
		})
		function savePrint(e){
    
    
			print.x = e.pageX
			print.y = e.pageY
			console.log(e.pageX,e.pageY)
		}
		onMounted (){
    
    
			window.addEventListener("click",savePrint)
        }
		onBeforeUnmount(){
    
    
			window.removeEventListener("click",savePrint)
		}
	 return print
}

vue组件中使用

import usePrint from 'hook/index.ts'
export default {
    
    
	setup(){
    
    
		let print = usePrint()
		console.log(print)
	}
}

roRef

  • 作用:创建一个ref对象,其value指向另一个对象中的某个属性
  • 语法:const name = toRef(person,“name”)
  • 应用:要将响应式对象中的某个属性单纯提供给外部使用。
  • 扩展:toRefs 与 toRef 功能一致,但可以批量创建多个ref对象,语法 toRefs(person)

例子,将对象中的仅仅两个属性返回在页面

import {
    
    reactive,toRef,toRefs} from 'vue'
export default {
    
    
	setup(){
    
    
		let per = reactive({
    
    
			name:"",
			age:12,
			job:{
    
    
				jianzhi:{
    
    
					gongzi:10
				}
			}
		})
		
		let name = per.name
		name = "李四";// 这样name脱离了响应式,页面不会更新。
		let name2 = toRef(per,'name');//name2 是响应式的
		let gongzi = toRef(per.job.jianzhi,"gongzi")
		//let per1 = toRefs(per);
		return {
    
    
			name2,
			gongzi
		}
}
}

其它 Composition API

shallowReactive 与 shallowRef

  • shallowReactive :只处理对象最外层属性的响应式(浅响应式)
  • shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。
  • 使用场景:
  • 如果有一个对象数据,结构比较深,但变化时只是外层属性变化,就用shallowReactive
  • 如果有对象数据,后续功能不会修改对象中的属性,而是生成新的对象来替换,就用 shallowRef
import {
    
    reactive,shallowReactive,shallowRef} from 'vue'
export default {
    
    
	setup(){
    
    
	  // 只处理第一层响应式
		let obj = shallowReactive({
    
    
			a:"",
			b:{
    
    
				c:2, //  c 是改变了监听不到,因为不做响应式处理
			}
		})
		let aa = shallowRef({
    
     b: 23}) // 没有处理成响应式,因为shallowRef只处理基本类型。
	}
}

readonly 与 shallowReadonly

readonly 让一个响应式数据变为只读的(深只读)
shallowReadonly 让一个响应式数据变为只读的(浅只读)
应用场景:不希望数据被修改时。

toRaw 与 markRaw

  • towRaw

    • 作用:将一个由 reactive 生成的响应式对象转为普通对象。
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
  • markRaw:

    • 作用:标记一个对象,使其永远不会再成为响应式对象
    • 应用场景
    • 1.有些值不应被设置为响应式的,例如复杂的第三方类库等
    • 2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

customRef

创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。

实例:实现一个防抖的效果

<template>
  <input type="text" v-model="keyword"/>
  <h3> {
    
    {
    
    keyword}}</h3>
</template>
imput {
    
    customRef} from 'vue'
export default {
    
    
	setup(){
    
    
		// 自定义一个ref名为myRef
		function myRef(value){
    
    
	         let timer 
			const x = customRef((track,trigger)=>{
    
      // 函数必须返回一个对象
				return {
    
    
					get(){
    
    
					    track(); // 通知vue追踪value的变化,(提前和get商量一下,让他认为这个value是有用的)
						return value
					},set(newValue){
    
     
					   clearTimeout()
					   timer = setTimeout(()=>{
    
    
						   value = newValue;
					 	   trigger()// 通知vue去重新解析模板
						},500)
					}
				}
			}) 
			return x;
		}
		let keyword = myRef("");
		return {
    
    keyword}
	}
}

provide 与 inject

作用:实现组件与后代组件间(跨级组件)通信,其实父子组件也可以,但是父子组件一般用简单的props就可以了

父组件有一个provide 选项来提供数据,子组件有一个inject 选项来开始使用这些数据
组件A

<template>
  <div> 组件A (祖)</div>
  <B />
</template>
<script>
import {
    
    reactive,toRefs,provide} from 'vue'
import B form 'B.vue'
export default {
    
    
   name:'A',
   setup(){
    
    
	let car = reactive({
    
    
		name:"奔驰", price:"40w"
	})
	provide("car",car)
	return {
    
    ...toRefs(car) }
	}
   
}
</script>

组件B (子组件)

<template>
  <div> 组件B (子)</div>
  <C />
</template>
<script>
import C form 'C.vue'
export default {
    
    
   name:'b'
}
</script>

组件C (孙组件)

<template>
  <div> 组件C (孙)</div>
  <div> 获取到祖组件中数据 {
    
    {
    
    car.name}} -- {
    
    {
    
    car.price}} </div>
</template>
<script>
import {
    
    reactive,toRefs,inject} from 'vue'
export default {
    
    
   name:'C',
   setup(){
    
    
	let car = inject("car");
	console.log(car)
	return {
    
    car}
	}
}
</script>

响应式数据的判断

  • isRef:检查一个值是否为一个ref对象
  • isReactive:检查一个对象是否是由reactive 创建的响应式代理
  • isReadonly:检查一个对象是否是由readonly 创建的只读代理
  • isProxy:检查一个对象是否是由reactive 或者readonly 方法创建的代理
import {
    
    ref, reactive,toRefs,readonly,isRef,isReactive,isReadonly,isproxy ) from 'vue
export default (
	setup(){
    
    
		let car = reactive({
    
    name:'奔驰',price:'40w'})
		let sum = ref(0)
		let car2 = readonly(car)
		console.log(isRef(sum))  // true
		console.log(isReactive(car))  // true
		console.log(isReadonly(car2))  // true
		console.log(isProxy(car))  // true
		console.log(isProxy(sum ))  // false
		return {
    
    ...toRefs(car)]
	}
}

Composition Api 的优势。

使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改,
使用Composition Api 我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。
![在这里插入图片描述](https://img-blog.csdnimg.cn/90b2a0473f144259bf6af975579c2a12.png

在这里插入图片描述

新的组件

.Fragment

。在Vue2中:组件必须有一个根标签
。在Vue3中: 组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
。好处: 减少标签层级,减小内存占用

Teleport

什么是Teleport?- Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。类似于弹出对话框。

<teleport to="移动位置">
<div v-if="isShow"class="mask">
	<div class="dialog">
		<h3>我是一个弹窗</h3>
		<button @click="isShow = false">关闭弹窗</button>
		</div>
	</div>
</teleport>

Suspense

等待异步组件时渲染一些额外内容,让应用有更好的用户体验

<template>
	<div class="app">
		<h3>我是App组件</h3>
		<Suspense>
			<template v-slot:default>
				<Child/>
			<template>
			<template v-slot:fallback>
				<h3>稍等,加载中...</h3>
			</template>
		</Suspense>
	</div>
</template>
<script>
// import Child from./components/Child'//前态引入
import (defineAsyncComponent} from ‘vue’
const Child = defineAsyncComponentexport default(()=>import('./components/Child')) //异步引入
export default {
    
    
  name : 'App'
  components:{
    
    Child},
}
</script>

如果是使用Suspense 进行异步引入子组件,那么子组件中setup 是可以返回 async函数或者promise函数。

<template>
	<div class="child">
		<h3>我是child组件</h3>
		({
    
    sum))
	</div>
</template>
<script>
import (ref} from 'vue‘
export default {
    
    
	name:'Child'
	async setup()[
		let sum = ref(0)
		let p = new Promise((resolve,reject)=>(
			setTimeout(()=>{
    
    
				resolve({
    
    sum))
			}, 3000)
		return await p 
</script>

vue3 一些api的转移

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43506403/article/details/130763018