setup函数是组合API的入口函数
ref函数
-
ref和reactive一样,用来实现响应式数据的方法
-
由于reactive必须传递一个对象,所以提供了ref方法,实现对简单值的监听
-
本质还是reactive,系统会自动将值转换 ref(xx) -> reactive({value:xx})
-
在Vue中使用ref的值不需要通过value获取 在js中使用ref的值必须通过value获取
<template> <p>{{count}}</p> <button @click="myFn">按钮</button> </template> <script> import {ref} from 'vue' export default { name: "vue3.0", //setup函数是组合API的入口函数 setup() { //ref函数只能处理简单类型的变化,不能监听复杂类型的变化(对象/数组) let count = ref(0); //在组合API中,如果想定义方法,不用定义到methods中,直接定义即可 function myFn() { alert(123) count.value += 1 } //在组合API中定义的变量/方法,要想外界使用,必须通过return{xx, xx}暴露出去 return {count, myFn} } } </script>
reactive函数
-
reactive是Vue3中提供的实现响应式数据的方法 Vue2中是通过defineProperty实现 Vue3中是通过ES6的Proxy实现
-
参数必须是对象(json/arr)
-
如果传递其他对象 默认情况下修改对象,界面不会自动更新,可通过重新赋值的方式更新
<template> <div> <form> <input type="text" v-model="state2.stu.id"> <input type="text" v-model="state2.stu.name"> <input type="text" v-model="state2.stu.age"> <input type="button" @click="addStu"> </form> <ul> <li v-for="(stu, index) in state.stus" :key="stu.id" @click="remStu(index)"> {{stu.name}} - {{stu.age}} </li> </ul> </div> </template> <script> import {reactive} from "vue"; export default { name: "app1", setup() { let {state, remStu} = userRemoveStudent(); let {state2, addStu} = userAddStudent(state); return {state, remStu, state2, addStu} } } function userRemoveStudent() { let state = reactive({ stus: [ {id:1, name:'zs', age:10}, {id:2, name:'ls', age:20}, {id:3, name:'ww', age:30}, ] }); function remStu(index) { state.stus = state.stus.filter((stu, idx) => idx !== index) } return {state, remStu} } function userAddStudent(state) { let state2 = reactive({ stu: { id:'', name:'', age:'' } }) function addStu(e) { e.preventDefault() const stu = Object.assign({}, state2.stu); state.stus.push(stu) state2.stu.id = '' state2.stu.name = '' state2.stu.age = '' } return {state2, addStu} } </script>
-
可将函数封装到js文件,通过import引用
-
Composition API 可和 Option API混合使用()
-
setup执行时机,
beforecreate
钩子之前完成的 还未执行Created生命周期方法,在setup中无法使用data和methods -
setup中this指向
undefined
-
setup函数只能是同步的
判断当前数据是否是ref类型
通过当前数据的__v_ref
来判断,如果有这个私有属性,并取值为true
,那么就代表是一个ref类型数据
递归监听
-
默认情况下,无论通过ref还是reactive都是递归监听
-
如果数据量比较大,非常消耗性能
非递归监听
一般情况下使用ref和reactive即可,只有在需要监听的数据量比较大时,才使用shallowReactive/shallowRef
-
shallowReactive 此方法Vue监听的是第一层的变化
-
shallowRef 此方法Vue监听的是.value的变化,因为底层调用shallowReactive,value才是第一层
-
triggerRef主动触发界面更新 Vue3只提供了triggerRef,没有提供triggerReactive
toRaw
<script> import {reactive, toRaw, ref} from 'vue' export default { name: "app2", setup() { /* ref/reactive数据 每次修改都会被追踪,都会更新UI界面,但是这样是非常消耗性能 所以如果有一些操作不需要追踪,不需要更新UI界面,就可以通过toRaw方法拿到它的原始数据 对原始数据进行修改,这样就不会被追踪,不会更新UI界面,性能就好了 * */ let obj = {name: 'zs', age:18} let state = reactive(obj) // let state = ref(obj) //如果想通过toRaw拿到ref类型的原始数据 //那么就必须明确告诉toRaw方法,要获取的是.value的值 let obj2 = toRaw(state) // let obj2 = toRaw(state.value) //state和obj的关系 //引用关系,state的本质是Proxy对象中引用了obj function myFn() { //如果直接修改obj,无法触发界面更新 //只有通过包装之后的对象来修改,才会触发界面更新 obj.name = 'ls'; console.log(obj);//{name: "ls", age: 18} console.log(obj2);//{name: "ls", age: 18} console.log(state);//{name: "ls", age: 18} } } } </script>
markRaw
让数据永远不被追踪,不变响应数据
let obj = {name: 'zs', age:18} obj = markRaw(obj)
toRef
-
如果利用ref将某一个对象中的属性变成响应式数据,我们修改响应式的数据是不会影响到原始数据的
-
如果利用toRef将某一个对象中的属性变成响应式数据,我们修改响应式的数据会影响到原始数据的 但是如果响应式的数据是通过toRef创建的,那么修改了数据并不会触发UI界面的更新
toRefs
利用toRefs将某一个对象中的多个属性变成响应式数据,我们修改响应式的数据会影响到原始数据的 但是如果响应式的数据是通过toRefs创建的,那么修改了数据并不会触发UI界面的更新