【问题标题】:Object is possibly 'null'. on a ref(null)对象可能为“空”。在 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" /> 那样使用它跨度>

标签: typescript vue.js vuejs3 vue-composition-api


【解决方案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()
            

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

            【讨论】:

              猜你喜欢
              • 2021-04-14
              • 2017-10-24
              • 2022-01-04
              • 1970-01-01
              • 2021-02-14
              • 2021-07-25
              • 2022-11-24
              • 2020-08-23
              相关资源
              最近更新 更多