Vue3 - ComponsitionAPI(一)

温故知新,常看常记

setup 函数

参数一:props

props 是父组件传递过来的属性对象

1.对于props定义的类型,和vue2的规则是一样的,在props的选项中定义。
2.在template中也可以正常去用

参数二:context

context 也称之为是一个SetupContext,包含三个属性
  1. attrs:所有非props的attribute(自定义属性)
  2. slots: 父组件传递过来的插槽(render的时候用)
  3. emit: 当组件内部需要发出事件时会用到emit

App.vue

	<template>
		<home message = '哈哈哈'>
			<template #default>
				<h2>哈哈哈哈哈</h2>
			</template>
		</home>
	</template>
	<script>
		import Home from './Home.vue'
		export default{
			components:{Home}
			setup(){
				
			}
		}
	</script>

Home.vue

	<template>
	</template>
	<script>
		export default{
			props:{
				message:{
					type:String
				}
			},
			//setup(props,context){
			setup(props,{attrs,slots,emit}){
				...
			}
		}
	</script>

setup 函数的返回值

setup 的返回值:1.可以在模版template中使用;2.可以通过setup的返回值来替代data选项;3.也可以返回一个执行函数来替代methods中定义的方法。

	<script>
		const name = ' toamto '
		let counter = 0
		const increment = () => coutner++
		const decrement = () => counter--
		return {
			name,
			increment,
			decrement
		}
	</script>

但是上面这种写法并不能实现界面的响应式,默认情况下Vue并不会跟踪一个定义的变量来更新界面

setup 不可以使用this

官方的描述:

  • this并没有指向当前组件实例
  • 并且在setup被调用之前,data、methods、computed等都没有被解析所以无法在setup中使用this

reactive API

如果想为在setup函数中定义的数据提供响应式的特性,可以使用reactive函数

	import {reactive} from 'vue'
	const state = reactive({
		name:"tomato",
		age:18
	})

当我们使用reactive函数处理我们的数据之后,数据再次被使用时就会进行依赖收集,当数据发生改变时,所有收集到的依赖都会进行对应的响应式操作 (比如更新界面)。
事实上,我们编写的data选项,也是在内部交给了reactive函数将其变成响应式对象的。

reactive 补充的api

  1. isProxy 检查对象是否由reactive 或 readonly 创建的proxy
  2. isReactive
    • 检查对象是否由reactive创建的
    • 如果是readonly包裹了另一个reactive创建的响应式代理也返回true
  3. isReadonly检查对象是否由readonly创建
  4. toRaw 返回reactive 或readonly代理的原始对象
  5. shallowReactive : 创建一个响应式代理,跟踪其自身的property的响应性,但不执行嵌套对象的深层响应式转换(深层还是原声对象)
  6. shallowReadonly : 创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深度只读转换(深层还是可读可写的)

ref API

reactive API 对传入的数据类型是有限制的,它要求我们必须传入的是一个对象或者数组类型。如果传入基本数据类型(string,number,boolean)会报警告。
“value cannot be made reactive:xxx"

这个时候Vue3提供了ref API:

  1. ref 会返回一个可变的响应式对象,该对象作为一个响应式的引用维护着它内部的值
  2. ref内部的值是在ref的value属性中被维护的
	import { ref } from 'vue'
	setup(){
		const message = ref("Hello world")
		return{ message }
	}	

⚠️注意

  • 在template中引入ref的值时,vue会自动帮助我们进行解包,所以在模版中不需要通过ref.value 来使用
  • 但是在setup函数内部,它依然是一个ref引用,所以对其进行操作时,还是要使用ref.value来操作它

ref 补充的api

  1. unref : 获取一个ref引用中的value,如果参数是一个ref,返回内部的值,否则返回参数本身
	语法糖函数
	val = isRef(val) ? val.value : val 
	
	const { name, age} = toRefs(obj);
	unref(name) // tomato
  1. isRef 判断值是否是一个ref对象
  2. shallowRef 创建一个浅层的ref对象
  3. triggerRef 手动出发和shallowRef相关联的副作用
	const info = shallowRef({name:"lili"})
	// 下面的修改不再是响应式的了
	const changeInfo = () => {
		info.value.name = ' tomato' 
		
		//需要手动触发
		triggerRef(info)
	}

readonly

通过reactive 或者ref 可以获取到一个响应式的对象。但是某些情况下哎,我们传入给组件的这个响应式对象希望被其他的组件使用,但是不能被修改,这个时候就使用readonly

  • vue3 位我们提供了readonly方法
  • readonly会返回原生对象的只读代理(也就是它依然是一个Proxy,但是这个proxy的set方法被劫持,并且不能对其进行修改)
	const infoProxy = new Proxy(info,{
		get(target,key){
			retirm target[key]
		},
		set(target,key,value){
			warmomg("不允许修改不可变的值")
		}
	})
	const name = infoProxy.name
	infoProxy.name = 'tomato'
readonly传入的参数
  1. 类型一:普通对象
  2. 类型二:reactive返回的对象
  3. 类型三:ref返回的对象
readonly 使用规则
  1. readonly返回的对象都是不允许修改的
  2. 经过readonly处理的原对象是被允许修改的
	const	obj = {
		name:"lili",
	}
	const readonlyInfo = readonly(boj) // readonlyInfo 对象不允许被修改
	obj.name = 'tomato' // obj 可以修改,修改后readonlyInfo的值也会被更新
  1. 我们传递给其他组件数据时,不允许它们修改就用readonly

App.vue

	<header :info = 'readonlyInfo" />
	<home :info = 'info' />
	<script>
		import {reactive,ref,readonly} from 'vue'
		export default{
			components:{Header,Home},
			setup(){
				const info = reactive({
					name:"tomato",
					age:18
				})
				const readonlyInfo = readonly(info)
				return {
					info,
					readonlyInfo
				}
			}
		}
	</script>

toRefs

  1. 如果我们使用ES6的解构语法,对reactive返回的对象进行解构获取值,数据会变成非响应式的
  2. 使用toRefs 让解构出来的属性变成响应式的
	import {toRefs} from 'vue'	
	const {name,age} = toRefs(info)
	return {
		name,
		age
	}

toRef

只希望转换一个reactive对象中的属性

	import {toRef} from 'vue'
	const name = toRef(info,'name')
	const {age} = info
	const changeName = () => {
		name.value = 'tomato'
		或者
		info.name = 'tomato'
	}
上一篇:Vue3-ref函数和reactive函数


下一篇:ref的使用和理解