”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,那我用HTMLElementHTMLDivElement都可以是吧?有啥好的规约吗?像 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

只用你不能确定的情况下,才需要判断一下是否非空。


HTMLDivElementHTMLElement 多了一个 align 属性。如果你并非用到某个特定元素类型的特有成员(常见于 HTMLImageElementHTMLVideoElement 等),一律声明成 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&lt;HTMLElement&gt;() ”写法问题,请教大佬? 的全部内容, 来源链接: utcz.com/p/934049.html

回到顶部