这里为什么要使用ref呢?
来源:3-14 模块化结合typescript - 泛型改造
慕莱坞0998854
2020-10-04
老师在演示useURLLoader的时候,有如下的代码:
function useURLLoader<T>(url: string) {
const result = ref<T | null>(null);
const loading = ref(true);
const loaded = ref(false);
const error = ref(null);
axios
.get(url)
.then((rawData) => {
loading.value = false;
loaded.value = true;
result.value = rawData.data;
})
.catch((e) => {
loading.value = false;
error.value = e;
});
return {
result,
loading,
error,
loaded,
};
}
我在看课程的时候产生了疑问,由于不清楚ref和reactive的具体实现,我只是这样死记下来: 原始类型用ref,对象的话用reactive.
那么这里令我疑惑,为什么这里的result明明是一个对象,却用了ref来包裹呢?
然后我就改写了一下,虽然能成功,但是还是有问题不懂:
function useURLLoader<T extends Object>(url: string) {
// 问题1
// reactive<T>(param) ref<T>(param)
// 上面这两个式子均表示param是T类型的,对吧?
// 问题2
// 为什么以下注释的写法会报错?
// let result:T = reactive({})
// 使用Object.create(null)却是可以的?
let result:T = reactive(Object.create(null))
const loading = ref(true);
const loaded = ref(false);
const error = ref(null);
axios
.get(url)
.then((rawData) => {
loading.value = false;
loaded.value = true;
// 问题三
// 把鼠标放在rawData上面 显示它的类型为AxiosResponse<any>
// 那么raw.data的类型也是any
// 可是我在之前声明了result要为T类型并且T extends Object
// 这TS总该提示我一下吧?
// 可是这也没提示啊
result = rawData.data
})
.catch((e) => {
loading.value = false;
error.value = e;
});
return {
result,
loading,
error,
loaded,
};
}
写回答
1回答
-
张轩
2020-10-05
同学你好 谢谢你很长的问题
问题 一 理解是正确的,其实可以去看定义文件,看了就清楚很多啦
问题二 Object.create(null) 返回的是 any 类型,而 { } 就是一个 { } 类型, { } 类型不等于 T 类型。 所以第一个不会报错. 而且你这里写法有点问题,不一样指定 let result:T 它为 T 类型,这里类型推论会帮助你的,去掉这个定义你可以看到它真实被推断的类型
问题三 你的result 确实是 T extends Object 的,我这里是能自动联想出 Object 上的一些方法的。
最后,关于 ref 和 reactive,没必要死记硬背,我们完全可以对照 js 的概念来记。我在课中也讲过了
const a = 1 || {} || '1' 也可以等于对象 各种类型都可以 对应 ref const obj = { name: 'a', age: 20 } 一个对象,对应 reactive
这样理解就非常清楚了
012020-10-06
相似问题