使用
import {unref,toRef,toRefs,isRef,isProxy,isRefs,isReactive,isReadonly} from 'vue'
(1)unref
判断是否是ref对象,是返回ref对象.value值,不是返回参数本身
语法糖:val = isRef(val) ? val.value : val
const xx=unref(x)
(2)readonly
接受一个对象(reactive响应式或js纯对象)或ref并返回原始对象的只读代理
只读代理是深层的:任何被访问的嵌套属性也是只读的。
使用ref的属性都会被代理自动解包
const copy = readonly(obj)
(3)shallowReadonly
为对象第一层属性创建浅层只读响应式代理,不会深层代理,使用ref的属性都不会被代理自动解包
const x=shallowReactive({x:'xx',xx:{xxx:'xxx'}})
x.x是只读的
x.xx.xxx不是只读的
(4)shallowRef
创建一个ref,将会追踪它的.value更改操作,但是并不会对变更后的.value做响应式代理转换(即变更不会调用reactive将新值进行转换).
只对值是对象时有用,值为普通值更改后依旧为响应式的
更改该对象属性无法被侦听器侦听
const foo = shallowRef({}) 会追踪foo的变更
只有改变foo.value会响应,添加属性等不会
isReactive(foo.value) false
(5)shallowReactive
为对象第一层属性创建浅层响应式代理,不会深层代理,并且使用ref的属性都不会被代理自动解包
const x=shallowReactive({x:'xx',xx:{xxx:'xxx'}})
x.xx.xxx是非响应式
(6)toRef
为一个reactive对象的属性创建一个ref,并返回该ref,即可通过返回值和reactive对象操作属性
可以创建返回一个不存在的属性
const x = reactive({xx:xxx})
const y=toRef(x,xx);
y.value和x.xx都可以操作xx属性
使用toRef(reactive,属性),返回的内容会保持对其源属性的响应式连接,即双方修改都会相互影响
使用ref转换reactive代理对象的属性则不会
(7)toRefs
把一个响应式对象转换成普通对象,该普通对象的每个属性都是一个ref对象,返回的内容会保持对其源属性的响应式连接,即双方修改都会相互影响
const x = reactive({xx:xxx})
const y=toRefs(x);
y.xx.value和x.xx都可操控属性
常用于解构赋值,使得元素不丢失响应性
const { foo, bar } =toRefs(reactive({foo:1,bar:2}))
(8)toRaw
返回由reactive或readonly方法代理的普通对象
这是一个“逃生舱”,可用于临时读取数据而无需承担代理访问/跟踪的开销,也可用于写入数据而避免触发更改。
不建议保留对原始对象的持久引用。请谨慎使用。
const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) true
(9)isRef
检查一个参数是否为一个 ref 对象。
(10)isProxy
检查一个对象是否是由reactive或者readonly方法创建的代理。
(11)isReactive
检查一个对象是否是由reactive创建的响应式代理
若reactive对象被readonly包裹,则也会返回true
isReactive(readonly(reactive({}))) true
(12)isReadonly
检查一个对象是否是由readonly创建的只读代理。
(13)markRaw
显式标记一个对象为“永远不会转为响应式代理”,函数返回这个对象本身
浅层标记,对嵌套属性无效。
即使在响应式对象中作属性,也依然不是响应式的
const foo = markRaw({})
console.log(isReactive(reactive(foo))) false
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) false
若
将嵌套在内的、未标记的原始对象添加进响应式对象,然后再次访问该响应式对象,就会得到原始对象被代理后的对象,与原对象不一致
const foo = markRaw({
nested: {}
})
const bar = reactive({
nested: foo.nested
})
console.log(foo.nested === bar.nested) false
(14)triggerRef
手动执行triggerRef(shallowRef)执行与shallowRef关联的任何副作用,即手动设置,使得对象属性的变化能够被侦听器侦听
const shallow = shallowRef({
greet: 'Hello, world'
})
第一次运行时记录一次 "Hello, world"
watchEffect(() => {
console.log(shallow.value.greet)
})
这不会触发作用effect,因为ref是浅层的
shallow.value.greet = 'Hello, universe'
记录"Hello, universe"
triggerRef(shallow)
代码示例:
<template>
<div>
<img src="./logo.png">
<h1>Hello Vue 3!</h1>
{{name}}{{obj.sex}}{{data}}
<button @click="inc" ref='btn'>Clicked {{ count }} times.</button>
<ul>
<li v-for='(item,index) in 3' :key=index :ref="el=>{divs[index]=el}">
{{item}}
</li>
</ul>
</div>
</template>
<script>
import { ref,reactive,computed,readonly,watchEffect,watch,onMounted, onUpdated, onUnmounted,onRenderTracked,onRenderTriggered,
inject,provide,render, onBeforeUpdate,unref,toRef,toRefs,isRef,isProxy,isRefs,isReactive,isReadonly
} from 'vue'
const ThemeSymbol = Symbol()
export default {
setup() {
let count = ref(0)
let count2=ref(2);
let normal='123'
let name = ref('jeff')
const obj=reactive({sex:'male'})
const robj=readonly(obj);
const divs = ref([])
let timer;
const btn =ref(null);
console.log(unref(normal));
const inc = () => {
count.value++;
name.value='jak'
}
onMounted(()=>{
})
return {
count,
inc,
name, //在setup返回对象中自动解套
obj,
btn,
divs
}
}
}
</script>
<style scoped>
img {
width: 200px;
}
h1 {
font-family: Arial, Helvetica, sans-serif;
}
</style>