问题:Nuxt 插件属性在“CombinedVueInstance”类型上不存在

我创建了一个插件并想在我的一个组件中使用它。~/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<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.

我已经尝试添加一个 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;
  }
}

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

解答

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

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

~/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 包:

  • @nuxt/types

  • typed-vuex

  • vue-class-component

  • nuxt-property-decorator

  • nuxt-typed-vuex(不要忘记将此添加到您的 nuxt.config.ts buildModules)

Logo

前往低代码交流专区

更多推荐