如果直接在方法中进行更改变量,数据是没有响应式的,也就是说,数据是改了但是不会渲染到主屏幕
ref 实现
// 导入
import {ref} from "vue";
export default {
setup() {
// 定义的变量使用 ref 进行报错
let name = ref('123')
// 在使用或者更改的时候使用以下方式
name.value = '456'
return {name}
}
}在模板语法中可以直接使用,不需要 .value
当 data 是对象的时候,可以采让 ref 包裹住对象的方式
import {ref} from "vue";
export default {
setup() {
// 使用 ref 包裹住对象
let user = ref({
name: '张三',
age: 18
hobby: ["足球", "篮球", "羽毛球"]
})
// 当调用方法是进行响应式更改
function getName() {
// 使用以下方式进行更改
user.value.name = '李四'
user.value.age = 19
user.value.hobby[0] = "乒乓球"
}
return {user, getName}
}
}ref 适合基本数据类型
reactive 实现
reactive 是一个函数,这个实现不能用于基本数据类型,这个函数是专门用于对象类型的
import {reactive} from "vue";
export default {
setup() {
// 使用 reactive 包裹
let user = reactive({
name: '张三',
age: 18,
hobby: ["足球", "篮球", "羽毛球"]
})
function getName() {
// 在修改的时候不需要使用 value 就可以直接修改
user.name = '李四'
user.age = 19
user.hobby[0] = "乒乓球"
}
return {user, getName}
}
}使用以上的方式也可以对盒子套盒子的对象进行改变,并且对于 中途添加一个属性、中途删除一个属性(使用 delete 对象.属性)、通过数组下标直接访问 也是可以响应式的
浅层次的响应式(shallow)
shallowReactive:对象第一层支持响应式,第二层就不再支持了
shallowRef:只给基本数据类型添加响应式,如果是对象,则不会给它添加响应式
深只读与浅只读
组合式API:readonly 和 shallowReadonly
场景:如果从其他组件传递过来的数据不希望修改,那么最好加上一个只读
深只读:具有响应式的对象中所有的属性,包括子对象中的子对象中的属性,它的所有值都是只读的不可修改的
使用方法只需要对要被只读的数据用 readonly 进行包裹
浅只读:具有响应式的对象第一层的值是只读的
响应式数据的判断
isRef:检查是否为ref对象
isReactive:检查是否是由 reactive() 或者 shallowReadonly() 创建的代理
isProxy:检查一个值是否是由 reactive() 、readonly() 、shallowReactive() 或 shallowReadonly() 创建的代理
isReadonly :检查传入的值是否为只读对象
使用:从 vue 中导入相对应的内容然后直接使用即可
toRef 与 toRefs
在使用插值语法的的时候输入某些值时前面需要写很长的属性(xxx.xxx.xxx.age),如果要省略这些 xxx 那么可以在 return 返回的时候使用键值对的方式返回
let user = reactive({
name: "IKun",
age: 3,
hobby: {
h1: "唱",
h2: "跳",
h3: "rap",
h4: "打篮球"
}
})
return {
h1: user.hobby.h1,
h2: user.hobby.h2,
h3: user.hobby.h3,
}toRef
按照以上的方式就可以直接使用 h1 进行访问内容了,但是这种方法没有响应式,也就是说,更改 h1 的值 user 中的值不会更改。也可以直接使用 ref 再次进行包裹(h1: ref(user.hobby.h1))这种方式倒是有响应式,但是相当于新建的一个响应式对象,更改的也是这个新的,不会对老的 user 进行更改
在这种情况下就可以使用 toRef 进行包裹住,这样返回的数据不仅仅是老数据的而且也具有响应式
return {
h1: toRef(user.hobby, "h1"),
h2: toRef(user.hobby, "h2"),
h3: toRef(user.hobby, "h3"),
h4: toRef(user.hobby, "h4"),
}toRef 的使用的两个参数,第一个参数是对象,第二个参数是对象中的属性名
toRefs
上面的方式有点过于繁琐,所以又有一个叫 toRefs 的内容
return {
...toRefs(user.hobby)
}在 toRefs 中填入 user 的话,那么会给 user 的所有内容做代理。使用时,需要从当前层次进行使用,如上所示,在上面的写法中只给 user 内的 hobby 做了代理,使用时只能使用 hobby 内的数据,使用时直接使用属性名即可,如果单纯给 user 做代理,那么想要访问 h1 就得写成 hobby.h1 的形式
由于 toRefs 返回的是对象,所以采用 es6 语法(...xxx)进行添加返回
以上方式对 ref 和 reactive 都有相同的效果
(转换 | 标记)为原始
(转换 | 标记)为原始意思就是把响应式数据(转换 | 标记)成普通对象或者数据
转换(toRaw):将响应式对象转换为普通对象。只适用于reactive 生成的响应式对象
标记(markRaw):标记某个对象,让这个对象永远都不具备响应式
使用:直接对对象进行包裹并接收即可
