”ref<HTMLElement>() ”写法问题,请教大佬?
const nav = ref<HTMLElement>()const nav = ref<HTMLElement|null>(null)
const nav = ref(null)
const nav = ref('')
在nav标签上加ref的话,这几种定义写法有啥区别?都可以吗?※现在用的是第二种写法
我在使用这个nav时候,ts提示我 navWidth = nav.value.clientWidth
这样的写法不对,应该是 navWidth = nav.value?.clientWidth
但是在使用navWidth这个变量时候,navWidth可能为定义。这种情况该怎么写好点呢?
必须这样加if判断条件吗 if(nav.value){}
问题2
假如我想定义一个div
的关联ref
,那我用HTMLElement
和HTMLDivElement
都可以是吧?有啥好的规约吗?像 nav
这种标签是没有HTMLNavHTML
这样的接口,这种时候怎么办嘞?既然都是HTMLElement的子类,为啥要HTMLDivElement
呢,每次在定义时候都用HTMLElement
?
回答:
既然你是用在 TS 里的,后两种写法等于直接丧失了类型信息,直接排除。
其次直接 ref<HTMLElement>()
就好,用不着声明成 ref<HTMLElement | null>
。
因为 ref()
这个方法的函数签名本身就已经是 function ref<T = any>(): Ref<T | undefined>
了,Vue 已经帮你做好了值可能是未定义的处理了,用不着你多此一举声明出来。
// 没有初始值,此时 a 的类型为 Ref<number | undefined>let a = ref<number>();
// 有初始值,此时 b 的类型为 Ref<number>
let b = ref<number>(1);
我理解为你这个 ref 是要用在 template 里绑定到一个元素或组件的,那么它在 mount 之前确实会是 undefined 的。但如果你确认你的调用一定是在 mount 之后、并且这个元素本身也不存在 v-if 之类的会导致它有可能被销毁,那么直接用非空断言符 !
即可:
nav.value!.balabala
只用你不能确定的情况下,才需要判断一下是否非空。
HTMLDivElement
比 HTMLElement
多了一个 align
属性。如果你并非用到某个特定元素类型的特有成员(常见于 HTMLImageElement
、HTMLVideoElement
等),一律声明成 HTMLElement
即可,可以减轻心智负担。
回答:
首先,我们来看一下这几种写法的区别:
const nav = ref<HTMLElement>(): 此写法创建了一个 ref,期望它的值为 HTMLElement 类型。但是,这种写法会引发一个错误,因为 TypeScript 需要一个初始值,而此处未提供初始值。
const nav = ref<HTMLElement|null>(null): 此写法创建了一个 ref,期望它的值为 HTMLElement 类型或 null。初始值为 null。这是一个合适的写法,因为在组件挂载之前,ref 可能是 null。
const nav = ref(null): 此写法创建了一个 ref,初始值为 null,但未明确指定类型。TypeScript 可能会推断出类型 Ref<null>,这可能会导致后续使用时的类型错误。
const nav = ref(''): 此写法创建了一个 ref,初始值为空字符串。然而,此写法并不正确,因为期望的值应该是 HTMLElement 类型或 null,而非字符串类型。
建议使用第二种写法。
关于 navWidth 的问题,您可以使用 TypeScript 的非空断言操作符(!),表示 nav.value 一定不是 null 或 undefined:
`
navWidth = nav.value!.clientWidth;`
这样,当使用 navWidth 变量时,它将被视为已定义。但请注意,确保在使用非空断言操作符之前,nav.value 确实不为 null 或 undefined。
问题2:
是的,当定义一个与 div 关联的 ref 时,你可以使用 HTMLElement 或 HTMLDivElement。通常,如果你不需要访问特定于某种 HTML 元素类型的属性或方法,可以使用更通用的 HTMLElement。然而,如果你需要访问特定于 div 元素的属性或方法(例如,可能在将来的 HTML 规范中添加的内容),则可以使用 HTMLDivElement。
对于没有特定 HTML 接口的元素(如 nav 标签),可以使用 HTMLElement 类型。在实际操作中,这样做通常足够满足需求。使用 HTMLDivElement 或其他特定类型的优点在于,它们提供了针对特定元素的属性和方法,从而使得类型检查更加严格,帮助避免潜在的错误。
回答:
总结起来你的问题应该是 泛型参数有什么作用;
举个栗子:
假设我们写了一个使用id
来获取页面上的一个element
的方法
function getElement(id: string): HTMLElement | null { return document.getElementById(id);
}
然后,使用它
<input type='text' id='input1' value='value1' />
const element = getElement('input1');// 但是因为 HTMLElement 不具备 value 属性,这样写报错
// const v = element.value;
// 可我们知道它就是input,所以可以把它类型转换一下,并顺利拿到值
const v = (element as HTMLInputElement).value;
这个 getElement
用起来是不是挺麻烦的?
在我们预知类型的情况下,还要自己做转换,直接帮我转换了不就得了!
改造一下
function getElement<TElement>(id: string): TElement { return document.getElementById(id) as TElement;
}
再使用它
// 因为我们知道input1是确实存在且是 HTMLInputElement 类型的,所以直接代入类型const element = getElement<HTMLInputElement>('input1');
// 拿到的 element 就是 HTMLInputElement 类型的,直接取值
const v = element.value;
现在,再去看 ref
的类型参数该怎么代入是不是就明白了?ref
代入什么类型对应的就是它 value
的类型,大概如下
function ref<T>(...): T { return ({ value: ... as T });
}
回答:
问题1
是的,这么写更好。
问题2
是的 HTMLDivElement 会比 HTMLElement 多一些属性。虽然你可能用不上。
以上是 ”ref<HTMLElement>() ”写法问题,请教大佬? 的全部内容, 来源链接: utcz.com/p/934049.html