从零开始的vue3的世界(一)学习使用ref,reactive,toRef
ref
官方介绍: 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value。
基本使用:
- 这里我们以实现一个简单的计数器为例:
const count = ref(0);
const increase = () => {
count.value++;
};
// computed 计算属性
const doubleCount = computed(() => {
return count.value * 2;
});
return {
count,
increase,
doubleCount,
};
<div>
计数器:{{ count }}
<br />
double:{{ doubleCount }}
<br />
<button @click="increase">count ➕➕</button>
</div>
这时我们每点击一次按钮,count的value值都会+1
注意事项:
- 当我们要对做类型推断的时候,我们就需要用到
Ref<T>
示例:我们的函数要返回一个鼠标监听后返回的对象,代码如下:
interface mousePosition {
x: Ref<number>;
y: Ref<number>;
}
// 如果没有指明返回值,有时候eslint会报错
// 解决报错(没有返回值) warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
function useMousePosition(): mousePosition {
//...
return { x, y };
}
- 当我们的count的value值是一个复杂类型是,我们要在调用 ref 覆盖默认推断时传递一个泛型参数
const count = ref<string | number>('123') // count 的类型:Ref<string | number>
foo.value = 123
reactive
官方介绍:
1. 如果将对象分配为 ref 值,则可以通过 reactive 方法使该对象具有高度的响应式。
2. reactive返回对象的响应式副本。
基本使用:
使用方法一:
//官方案例:
//reactive 将解构所有深层的 refs,同时维持 ref 的响应性。
const count = ref(1)
const obj = reactive({ count })
// ref 会被解构
console.log(obj.count === count.value) // true
// 它会更新 `obj.value`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2
// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
//重要:当将 ref 分配给 reactive property 时,ref 将被自动解构。
const count = ref(1)
const obj = reactive({})
obj.count = count
console.log(obj.count) // 1
console.log(obj.count === count.value) // true
- 这里我们再次以实现一个简单的计数器为例:
const count = ref(0);
const increase = () => {
count.value++;
};
// computed 计算属性
const doubleCount = computed(() => {
return count.value * 2;
});
const data = reactive({
count,
increase,
doubleCount,
})
return {
data
};
计数器:{{ data.count }}
<br />
double:{{ data.doubleCount }}
<br />
<button @click="data.increase">➕➕</button>
使用方法二:
interface dataProps {
count: number;
increase: () => void;
doubleCount: number;
}
const _data: dataProps = reactive({
count: 0,
increase: () => {
_data.count++;
},
doubleCount: computed(() => _data.count * 2), // computed中使用 data.count ,会造成类型推断的循环
});
// data.count ==> (property) dataProps.count: number 丧失响应性
const refData = toRefs(_data); //保持对象具有响应性
// refData.count ==> vscode 提示变成响应式的ref对象了 (property) count: Ref<number>
return {
// reactive
refData,
// or
...refData
}
不解构refData的值return { refData }
计数器:{{ refData.count.value }}
<br />
double:{{ refData.doubleCount.value }}
<br />
<button @click="refData.increase.value">➕➕</button>
所有的值都需要.value
来获取
解构refData的值return { ...refData }
计数器:{{ count }}
<br />
double:{{ doubleCount }}
<br />
<button @click="increase">➕➕</button>
注意事项:
- 如果你想把一个逻辑中的所有属性聚合到一个对象中推荐使用方法一的写法。
- 如果使用方法二时候要注意对象的响应性,使用
toRefs()
和期中计算属性之类的类型推断的问题