对象可能为“空”。在 ref(null) 上

Posted

技术标签:

【中文标题】对象可能为“空”。在 ref(null) 上【英文标题】:Object is possibly 'null'. on a ref(null) 【发布时间】:2021-03-09 13:58:18 【问题描述】:

从我找到的文档中学习 Vue Composition API(和 TypeScript),我应该使用 ref(null) 来供我在 <template>...</template> 中的子组件使用。

这个子组件有open()之类的方法,我是这样访问它的:

setup() 
    const subcomponentRef= ref(null);
    subcomponentRef.value.open();
    return  subcomponentRef ;

我同意这可能会显示错误Object is possibly 'null'. 指向subcomponentRef.value,但奇怪的是即使我添加了条件if (subcomponentRef !== null && subcomponentRef.value !== null) ... ,它仍然显示该错误。 为什么?

还尝试像subcomponentRef?.value?.open() 一样访问它,但我收到此错误Property 'open' does not exist on type 'never'.

还尝试添加 非空断言,例如 confirmation.value!.open(); 并收到相同的错误 Property 'open' does not exist on type 'never'.

知道这里有什么问题吗?或者我应该用实际组件预定义它而不是使用ref(null)?但我不知道如何正确地做到这一点,在文档中找不到。

【问题讨论】:

您好像在引用一个组件,请分享您是如何导入它的 我正在使用 NuxtJS 及其自动注册组件的组件模块,但可以说我不使用它,我会像 import subcomponent from './subcomponent.vue'; 和模板 <subcomponent ref="subcomponentRef" /> 那样使用它跨度> 【参考方案1】:

尝试any,如果没有任何效果!

setup() 

const buttonRef= ref<any>(null); // <-- highlight

const buttonClicked = () =>  buttonRef.value.clicked = true 

return  buttonClicked, buttonRef 


【讨论】:

【参考方案2】:

如果您在这里使用 Typescript 在 vue 组合 API 中声明可为空的数字引用,

setup() 
  const foo = ref<number | null>(null);

  const someAction = () => 
      foo.value = 1
  

  return  foo, someAction ;

在上面的代码sn-p上, 您可以更改 number 数据类型以匹配您所需的数据类型。 此外,如果需要,您可以使用 | 运算符添加多种可能的数据类型。

【讨论】:

【参考方案3】:

您的基本问题是您没有输入 ref。如果 ref 不仅具有您最初使用的类型,您总是需要向 ref 添加一个类型。

假设您的组件是 MySubcomponent,您需要向 ref 添加一个类型

// In this case, you need to type
const subcomponentRef = ref<ComponentPublicInstance<typeof MySubcomponent> | null>(null);

// In this case not, type is inferred to Ref<number>
const myRef = ref(15)

然后您可以使用您的 if 并访问其中的组件实例的方法。请注意,您只能在设置完成后访问它,例如在事件监听器中,挂载的钩子,......

【讨论】:

【参考方案4】:

这应该很简单,你只需告诉 TS 它实际上不是空的,使用 non-null assertion operator:

setup() 
  const foo = ref(null);

  onMounted(() => 
    foo!.someMethod();
  

  return  foo ;

【讨论】:

只有在您的类型为 null | 时才有效其他类型。在这种情况下,类型为空。所以一会儿!告诉 typescript 它可能不为 null,TS 仍然没有关于实际类型的类型信息,并且会抱怨缺少 someMethod。【参考方案5】:

感谢您对此的帮助。这是我使用 Typescript 在 Vue 3 Composition API 中聚焦输入元素的简化解决方案:

<template>
   <input ref="inputField">
</template>

const inputField = ref(null)
inputField.value.focus()      // ERROR:  TS2531: Object is possibly 'null'

解决方案:

const inputField = ref<null |  focus: () => null >(null)
if(inputField.value)     
    inputField.value.focus()

确保定义了一个焦点函数。

【讨论】:

【参考方案6】:

您应该使用typeof yourComponentnull 使用组件类型,然后使用? 可选链接来访问方法/属性:

setup() 
    const subcomponentRef= ref < typeof subcomponent| null > (null);
    subcomponentRef.value?.open();
    return  subcomponentRef ;

【讨论】:

【参考方案7】:

好问题!我和你有同样的问题,偶然发现了这个answer。对我有用的是定义对象的形状(打字稿界面),所以 TS 知道什么存在什么不存在。

将这些知识应用到您的示例中:

setup() 
    const subcomponentRef = ref(null)
    subcomponentRef.value.open() // TS error here

变成:

setup() 
    const subcomponentRef = ref<null |  open: () => null >(null)
    subcomponentRef.value?.open()

TS 错误现在消失了,因为:

Typescript 知道函数 open 可以在 subcomponentRef 上使用,因为我们预先 declared 它 使用optional chaining,当subcomponentRef.valuenullundefined 时,我们告诉Typescript 不要再往下看。

通常这些接口已经在某处提供,不需要手动创建。所以就我而言,我只需要使用来自quasarQInput 接口来避免resetValidation 的TS 错误不可用:

import  QInput  from 'quasar'

const driverIdInput = ref<QInput>()
driverIdInput.value?.resetValidation()

我希望这有助于澄清问题并避免这些令人讨厌的错误。

【讨论】:

以上是关于对象可能为“空”。在 ref(null) 上的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:React Native useRef 给出错误“对象可能为空”

角度错误 TS2531:对象可能为“空”

笑话测试显示对象可能是“空”错误

访问有时为空对象的属性而不会出错[重复]

React Hooks 和 TypeScript Fetching API:对象可能为“空”

特例模式(Special Case Pattern)与空对象模式(Null Pointer Pattern)—— 返回特例对象而非 null