1. ref
ref 用于为数据添加响应式状态,可以让某一个变量具备响应式的能力。由于reactive只能传入对象类型的参数,而对于基本数据类型要添加响应式状态就只能用ref了,同样返回一个具有响应式状态的副本。
- 在 js 中使用 ref 的值必须使用 .value 获取,在 Vue 的模板中使用 ref 的值不需要通过 value 获取
- 语法:const xxx=ref(initValue),创建了一个包含响应式数据的引用对象
- 接收的数据可以是:基本类型、对象类型,对于基本数据类型,ref是自己的实现方式且性能优于reactive;而对于对象类型,ref仍然是通过reactive包装实现的
- 参数可以传递任意数据类型,传递对象类型时也能保持深度响应式,所以适用性更广。
- vue 3.0 setup里定义数据时推荐优先使用ref,方便逻辑拆分和业务解耦。
import { ref } from "vue";
setup() {
const msg = "张晓明";
let age = ref(18);
function add() {
age.value += 1;
}
return { msg, age, add };
}
2. reactive
经过reactive函数处理后的对象能变成响应式的对象,类似于option api里面的data属性的值,它主要是处理你的对象让它经过 Proxy 的加工变为一个响应式的对象。
注意点:
语法:
const 代理对象=reactive(源对象),接收一个对象(或数组),返回一个代理对象(proxy对象)如果想要保持对象内容的响应式能力,在 return 的时候必须把整个
reactive()对象返回出去在引用的时候也必须对整个对象进行引用而无法解构,否则这个对象内容的响应式能力将会丢失。
reactive()只能包装对象,基本类型不要用它,要用ref函数reactive定义的响应式数据是深层次的,内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作
<template>
<div class="home">
名字:{{ state.name }} 价格:{{ state.price }}
购买数量:{{state.count}}
<button @click="add">点我加1</button>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
name: "Home",
components: {
},
setup() {
//响应式对象
const state = reactive({
count: 0,
name:"商品1",
price:100
});
//修改响应式对象
function add() {
state.count += 1;
}
return { state, add };
},
}
</script>
3. isRef & toRefs & toRef
a) isRef
用来判断某个值是否为ref创建出来的对象。
import { ref, isRef } from 'vue';
export default {
setup () {
const count = ref(1);
const unwrappend = isRef(count) ? count.value : count;
return {
count,
unwrappend
};
}
}
b) toRefs
但是在具体的业务中,如果无法使用解构取出 reactive() 对象的值,每次都需要通过 state. 操作符访问它里面的属性会是非常麻烦的,所以官方提供了 toRefs() 函数来为我们填好这个坑。只要使用 toRefs() 把 reactive() 对象包装一下,就能够通过解构单独使用它里面的内容了。
toRefs 用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref。
- toRefs之后得到的ref引用在获取数据值的时候需要加.value
- toRefs后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
- 作用其实和 toRef 类似,只不过 toRef 是一个个手动赋值,而 toRefs 是自动赋值。
<template>
<div class="home">
名字:{{ name }} 价格:{{ price }}
购买数量:{{count}}
<button @click="add">点我加1</button>
</div>
</template>
<script>
import { ref, reactive,toRefs } from "vue";
export default {
name: "Home",
components: {
},
setup() {
//响应式对象
const state = reactive({
count: 0,
name:"商品1",
price:100
});
//修改响应式对象
function add() {
//下面两种写法等效
state.count += 1;
// stateRefs.count.value+=1;
}
const stateRefs = toRefs(state)
return { ...stateRefs, add };
},
}
</script>
c) toRef
概念:为源响应式对象上的某个属性创建一个ref对象,二者内部操作的是同一个数据值,更新时二者是同步的。相当于浅拷贝一个属性。
- toRef之后得到的ref属性在获取数据值的时候需要加.value
- toRef后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
<template>
<div class="home">
名字:{{ name }} 价格:{{ price }}
购买数量:{{count}}
<button @click="add">点我加1</button>
</div>
</template>
<script>
import { ref, reactive,toRef } from "vue";
export default {
name: "Home",
components: {
},
setup() {
//响应式对象
const state = reactive({
count: 0,
name:"商品1",
price:100
});
//修改响应式对象
function add() {
//下面两种写法等效
//state.count += 1;
count.value += 1;
}
const count = toRef(state, "count");
return { count, add };
},
}
</script>
d) ref reactive toRefs 和 toRef的比较
**ref : **原始数据没有变化,而ref“包裹的数据”变成了一个新的对象,而且模板有变化(相当于深拷贝)
**reactive : **reactive处理的数据无论是原始数据,“包裹后的数据”,还是模板,都有变化(代理模式)
toRef : toRef处理的数据会有变化,而原始数据也有变化,如果toRef处理是非响应式数据,此时模板没有变化 (相当于浅拷贝,引用关系)
toRefs : toRefs处理的数据响应变化,原始数据也响应变化,如果toRefs处理是非响应式数据,此时模板并没有变化(相当于浅拷贝,引用关系)

备注:ref也可以用来定义对象或数组,但内部会自动通过reactive转为代理对象
