【问题标题】:Nuxt plugin property does not exist on type 'CombinedVueInstanceNuxt 插件属性在“CombinedVueInstance”类型上不存在
【发布时间】:2022-01-03 18:15:57
【问题描述】:

我创建了一个插件并想在我的一个组件中使用它。 位于~/plugins/socket.client.ts下的插件代码:

import { io } from 'socket.io-client'
import { Plugin } from '@nuxt/types'

const socketIOPlugin: Plugin = (_, inject) => {
  const socketUrl: string | undefined = process.env.socket_url

  if (!socketUrl || socketUrl.length <= 0) {
    throw new Error('socketUrl is undefined.')
  }

  const socket = io(socketUrl)
  inject('socket', socket)
}

export default socketIOPlugin

在 nuxt.config.js 中注册。 plugins: ['~/plugins/socket.client']

我在我的组件中这样使用它:

import Vue from 'vue'

export default Vue.extend({
  mounted() {
    this.$socket.on("example:hello", (data: any) => {
      console.log(data);
    });
  },
})

但是,当我启动 nuxt 时,我收到以下错误: Property '$socket' does not exist on type 'CombinedVueInstance&lt;Vue, unknown, unknown, unknown, Readonly&lt;Record&lt;never, any&gt;&gt;&gt;'.

我已经尝试添加一个 vue-shim.d.ts 文件,但仍然没有任何变化。

declare module "*.vue" {
  import Vue from 'vue'
  export default Vue
}

declare module "vue/types/vue" {
  import { Socket } from "socket.io-client";
  interface Vue {
    $socket: Socket;
  }
}

我似乎找不到解决这个问题的方法。谁能帮帮我?

【问题讨论】:

    标签: typescript vue.js nuxt.js


    【解决方案1】:

    declare module "vue/types/vue" 是一个module augmentation - 为了使扩充功能正常工作,它需要放在包含至少 一个 顶级导入/导出的 TS 文件中(更多详细信息 @987654322 @)

    所以我的建议是将代码从 vue-shim.d.ts 直接移动到 socket.client.ts

    【讨论】:

    • 我已将声明模块部分放在我的 const socketIOPlugin... 代码之上,但我仍然收到相同的错误消息。
    【解决方案2】:

    我终于通过稍微重构我的代码让它工作了。

    免责声明;这个解决方案对我有用,因为它允许我以另一种方式使用插件。这不是问题的具体答案。这个问题的答案可以通过使用下面的插件代码并稍微更改 index.d.ts 来实现,以便在 vue 组件中也可以访问 $socket。阅读更多关于此here 的信息。

    ~/plugins/socket.client.ts

    import { Plugin } from '@nuxt/types'
    import { io, Socket } from 'socket.io-client'
    
    function getSocketConnection(): Socket {
      const socketUrl: string | undefined = process.env.socket_url
    
      if (!socketUrl || socketUrl.length <= 0) {
        throw new Error('socketUrl is undefined.')
      }
    
      return io(socketUrl)
    }
    
    const socketIOPlugin: Plugin = (_, inject) => {
      inject('socket', getSocketConnection())
    }
    
    export default socketIOPlugin
    export const socket = getSocketConnection()
    

    我还将 vue-shim.d.ts 重命名为 index.d.ts 并添加了以下几行:

    import { accessorType } from '~/store'
    import { socket } from '~/plugins/socket.client'
    
    declare module 'vuex/types/index' {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      interface Store<S> {
        $socket: typeof socket
      }
    }
    
    declare module 'vue/types/vue' {
      interface Vue {
        $accessor: typeof accessorType
      }
    }
    
    declare module '@nuxt/types' {
      interface NuxtAppOptions {
        $accessor: typeof accessorType
      }
    }
    

    我没有在我的组件中使用 socket.io 插件,而是创建了一个存储 ~/store/index.ts 来处理所有套接字事件。

    import type { ActionTree, GetterTree, MutationTree } from 'vuex'
    import { getAccessorType } from 'typed-vuex'
    
    export const state = () => ({
      posts: [] as any[],
    })
    
    export type RootState = ReturnType<typeof state>
    
    export const getters: GetterTree<RootState, RootState> = {
      posts: (state) => state.posts,
    }
    
    export const mutations: MutationTree<RootState> = {
      SET_POSTS: (state: RootState, posts: any[]) => (state.posts = posts),
    }
    
    export const actions: ActionTree<RootState, RootState> = {
      fetchPosts({ commit }) {
        this.$socket.emit('example:getPosts')
        this.$socket.once('example:posts', (data: any) => {
          commit('SET_POSTS', data)
        })
      },
    }
    
    export const accessorType = getAccessorType({
      state,
      getters,
      mutations,
      actions,
      modules: {},
    })
    

    现在使用起来容易多了,一切都更新了使用 vuex 的方式。

    ~/pages/index.vue

    <script lang='ts'>
    import { Component, Vue } from 'nuxt-property-decorator'
    
    @Component
    export default class Index extends Vue {
      get posts() {
        return this.$accessor.posts
      }
    
      fetchPosts() {
        this.$accessor.fetchPosts()
      }
    }
    </script>
    

    要让一切正常工作,您需要安装以下 npm 包:

    【讨论】:

      猜你喜欢
      • 2019-09-23
      • 2021-03-24
      • 2021-01-09
      • 2017-08-15
      • 2021-07-26
      • 2021-07-10
      • 2021-02-18
      • 2018-11-05
      相关资源
      最近更新 更多