const 声明的变量不可以被修改,但是 ref 创建对象可以实现数据的响应式更新
在 JavaScript 中,const 关键字作用是声明常量,用 const 声明的数组不能重新赋值。这意味着 const 声明的常量一旦被赋值后,其不能被重新赋值。然而,在 Vue 的响应式系统中,const 声明的变量可以使用 ref 函数来创建响应式数据,且该响应式数据可以在作用域内被多次修改。这是因为 ref 函数创建的响应式数据是一个特殊的对象,它对内部值进行了封装和代理,从而实现了在修改值时能够触发视图更新的效果。
ref
用法
主要用来声明基础类型的响应式数据,也可以接受对象类型描述
ref用于将一个基础类型的值(String,Number,Boolean,Undefined,Null)转换成一个响应式对象。ref声明的是一个包含value属性的普通对象,可以直接读取和修改value属性的值。使用ref来声明一个参数,Vue会确保这个参数是响应式的,即当其值改变时,任何依赖于这个值的部分都会被重新渲染。注意
- 修改响应式数据不影响以前的数据;数据改变,界面自动更新
- 如果参数是对象类型时,其实底层的本质还是
reactive,vue自动完成转换- 在
template中访问,系统会自动添加.value;在脚本中需要手动.value- 创建的都是递归响应的,将每一层的json 数据解析成一个proxy对象,类似
reactive,区别shallowRef与shallowReactive
<template>
<div>{{num}}</div> // 直接num便可获取值,不需要.value
</template>
<script setup lang="ts">
import { ref,reactive } from 'vue'
let num = 1
let num1 = ref(1)// 将num变量包装成响应式
console.log('num 的值是:', num)
console.log('num1 的值是:', num1)
console.log('num1.value 的值是:', num1.value)
num1.value = 11 // 修改值需要.value
console.log('num1.value 修改后的值是:', num1.value)
</script>
reactive
用法
主要用来声明引用类型的响应式数据, 不接受非Object类型的数据描述
Reactive用于将一个普通对象转换成一个响应式对象。reactive返回的是一个响应式对象,可以直接读取和修改对象的属性值注意
Reactive的本质是将每一层的数都解析成proxy对象,Reactive的响应式默认都是递归的,改变某一层的值都会递归的调用一遍,重新渲染dom。- 创建的都是递归响应的,将每一层的json 数据解析成一个proxy对象,类似
ref,区别shallowRef与shallowReactive
<template>
<div>{{obj.num}}</div>
</template>
<script setup lang="ts">
import { ref,reactive } from 'vue'
let obj = {num: 1}
let obj1 = reactive({num: 1}) // 将obj变量包装成响应式
console.log('obj 的值是:', obj)
console.log('obj1 的值是:', obj1)
obj1.num = 11 // 修改值
console.log('obj1修改后的值是:', obj1)
</script>
toRef
作用
修改响应式数据会影响以前的数据;数据改变,界面不自动更新描述
- 将对象某一个属性,作为引用返回
- 如果使用ref 创建的响应式变量,不会与源数据关联,如果想要与源数据关联但数据更改不更新UI,就要使用toRef创建
<script setup lang="ts">
import { toRef, reactive } from 'vue'
// 定义方式,声明普通变量
let one = {num: 1,name:'渺渺空空'}
let one1:any = toRef(one, 'num') // 这东西在这非常的鸡肋,有它没它效果是一样的,有了它后改变成了ObjectRefImpl数据格式
console.log('one的值:', one);
console.log('one1的值:', one1);
console.log('one1.value的值:', one1.value);
const btnOne = () => {
one1.value ++
console.log('one的值:', one); // 数据发生改变,页面没有更新
console.log('one1的值:', one1.value); // 数据发生改变,页面没有更新
}
// 定义方式,声明响应式变量
let two = reactive({num: 1,name:'渺渺空空'})
let two1:any = toRef(two, 'num') // 真没看出来啥作用
console.log('two的值:', two);
console.log('two1的值:', two1.value);
const btnTwo = () => {
two1.value ++
console.log('two的值:', two); // 数据发生改变,页面及时更新
console.log('two1的值:', two1.value); // 数据发生改变,页面及时更新
}
</script>
<template>
<div>
<span>普通变量</span>
<span>one.name: {{ one.num }}</span>
<span>one1:{{ one1 }}</span>
<button @click="btnOne">修改</button>
</div>
<div>
<span>响应式变量</span>
<span>one.name: {{ two.num }}</span>
<span>one1:{{ two1 }}</span>
<button @click="btnTwo">修改</button>
</div>
</template>
toRefs
作用
toRefs就是在toRef的基础上,将响应式对象的每个属性都转化为Ref对象,修改每个Ref对象就需要去修改其.value,然后用展开运算符就能始终不失去响应式
<script setup lang="ts">
import { shallowRef, triggerRef } from 'vue'
let toRefsObj = reactive({num: 1,name:'渺渺空空'})
let toRefsObj1:any = toRefs(toRefsObj) // 直接放入对象
console.log('toRefsObj的值:', toRefsObj);
console.log('toRefsObj1的值:', toRefsObj1); // 可以在控制台看看输出的两个是不一样的
const btntoRefsObj = () => {
toRefsObj1.num.value ++
console.log('toRefsObj的值:', toRefsObj);
console.log('toRefsObj1的值:', toRefsObj1);
}
</script>
<template>
<div>
<span>toRefs</span>
<span>toRefsObj.num: {{ toRefsObj.num }}</span>
<span>toRefsObj1:{{ toRefsObj1 }}</span>
<button @click="btntoRefsObj">修改</button>
</div>
</template>
shallowRef
作用
创建的是非递归的响应对象,类似shallowReactive,区别ref与Reactive描述
- 通过
shallowRef创建的响应式对象,需要修改整个value才能重新渲染dom- 如果使用了
shallowRef想要只更新某一层的数据可以使用triggerRef
<script setup lang="ts">
import { shallowRef, triggerRef } from 'vue'
let shallowRefobj = shallowRef({ num: 1, name: '渺渺空空' }) // 将shallowRefobj变量包装成响应式
console.log('shallowRefobj的值:', shallowRefobj);
console.log('shallowRefobj.value的值:', shallowRefobj.value);
// 方式1
shallowRefobj.value.num = 11 // 此时不会触发页面更新, 此处和ref一致,需要.value
console.log('方式1shallowRefobj.value的值:', shallowRefobj.value);
triggerRef(shallowRefobj) // 此时页面就会重新渲染
// 方式2
shallowRefobj.value = { num: 11, name: '渺渺空空' } // 此时会触发页面更新
console.log('方式2shallowRefobj.value的值:', shallowRefobj.value);
</script>
shallowReactive
作用
- 创建的是非递归的响应对象,改变第一层的数据会导致页面重新渲染
描述
- 创建的是非递归的响应对象,类似
shallowReactive,区别ref与Reactive
<script setup lang="ts">
import { shallowReactive } from 'vue'
let obj = shallowRef({num: 1,info: {name:'渺渺空空'}}) // 将obj变量包装成响应式
// 方式1
obj.num = 11 // 此时会触发页面更新
// 方式2
obj.info.name = 'aaa' // 此时不会触发页面更新
</script>
toRaw
作用
如果只想修改响应式的数据不想引起页面渲染可以使用toRaw这个方法描述
只修改数据不渲染页面
<script setup lang="ts">
import { toRaw, reactive } from 'vue'
let toRawObj = reactive({num: 1,name:'渺渺空空'})
let toRawObj1:any = toRaw(toRawObj) // 直接放入对象
console.log('toRawObj的值:', toRawObj);
console.log('toRawObj1的值:', toRawObj1); // 可以在控制台看看输出的两个是不一样的
const btntoRawObj = () => {
toRawObj1.num.value ++
console.log('toRawObj的值:', toRawObj);
console.log('toRawObj1的值:', toRawObj1);
}
</script>
<template>
<div>
<span>toRaw</span>
<span>toRawObj.num: {{ toRawObj.num }}</span>
<span>toRawObj1:{{ toRawObj1 }}</span>
<button @click="btntoRawObj">修改</button>
</div>
</template>
markRaw
作用
让数据变不成响应式数据
let markRawObj = markRaw({ num: 1, name: '渺渺空空' })
console.log('markRawObj的值:', markRawObj)
let markRawObj2 = reactive(markRawObj) // 此时markRawObj2已经是非响应数据了
console.log('markRawObj2的值:', markRawObj2)
markRawObj.num = 11
console.log('markRawObj修改的值:', markRawObj)
markRawObj2.num = 11
console.log('markRawObj2修改的值:', markRawObj)
customRef
作用
通过customRef这个方法可以自定义一个响应式的ref方法
function mycustomRef(value){
/*
customRef函数返回一个对象,对象里面有2个方法,get/set方法,创建的对象获取数据的时候能 访问到get方法,创建的对象修改值的时候会触发set 方法
customRef函数有2个参数,track/trigger,track参数是追踪的意思,get 的方法里面调用,可以随时追踪数据改变。trigger参数 是触发响应的意思,set 方法里面调用可以更新UI界面
*/
return customRef((track,trigger)=>{
return {
get(){
track()//追踪数据
return value
},
set(newVal){
value = newVal
trigger()//更新UI界面
}
}
})
}
setup(){
var num = myRef(1)
num.value = 11
}