【问题标题】:Svelte SPA Router - Invalid component object errorSvelte SPA 路由器 - 无效的组件对象错误
【发布时间】:2021-12-30 09:27:08
【问题描述】:

我正在使用 SvelteKit 和 svelte-spa-router

我的文件结构如下:

src/
├─ assets/
├─ lib/
│  ├─ Navbar.svelte
│  ├─ Sidebar.svelte
├─ routes/
│  ├─ about/
│  │  ├─ index.svelte
│  ├─ contact/
│  │  ├─ index.svelte
│  ├─ products/
│  │  ├─ index.svelte
│  ├─ Test.svelte
│  ├─ index.svelte
│  ├─ __layout.svelte
├─ app.css
├─ app.html

__layout.svelte:

(根据上面链接中的示例。)

<script>
  import Router from 'svelte-spa-router'
  import Navbar from "$lib/Navbar.svelte";
  import Sidebar from "$lib/Sidebar.svelte";
  import Home from './index.svelte'
  import About from './about/index.svelte'
  import Contact from './contact/index.svelte'
  import Products from './products/index.svelte'
  import Test from './Test.svelte';

  const routes = {
    // Exact path
    '/': Home,
    '/about': About,
    '/contact': Contact,
    '/products': Products,
    '/test': Test
  }
</script>

<Navbar />

<Sidebar />

<Router {routes} />

<style>
</style>

错误:

Error: Invalid component object
    at new RouteItem (Router.svelte:303:23)
    at Router.svelte:432:28
    at Array.forEach (<anonymous>)
    at Router.svelte:431:31
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (/src/routes/__layout.svelte:62:85)
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (eval at instantiateModule ([Path to project]/node_modules/vite/dist/node/chunks/dep-fcec4469.js:67775:28), <anonymous>:55:122)
    at $$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at Object.render ([Path to project]/node_modules/svelte/internal/index.js:1710:26)

控制台:

如果我删除&lt;Router {routes} /&gt; 并使用&lt;slot&gt;&lt;/slot&gt;,一切正常。

我设法找到的关于此错误的唯一信息是Router.svelte 的源代码this GitHub#301 行),但并没有太大帮助。

我尝试像示例中那样更改组件的名称,但仍然抛出错误(我认为它们都被称为相同的事实可能是一个错误,我不知道......) .

通过localhost:3000/[path] 手动导航也会引发错误,包括与__layout.svelte 位于同一路径之外的/test 路径。我提到后者是因为在我提供的第一个链接中作者说:

要显示路由器,在一个 Svelte 组件(通常是 App.svelte)中, 先导入路由组件...

通常从我看到的示例中,您通常放入App.svelte 的结构进入__layout.svelte,然后作为“主页”/“登陆”页面的index.svelte 自动进入默认情况下,位于__layout.svelte 中的&lt;slot /&gt;(以及您可能拥有的任何其他路线)中。

最后但同样重要的是,动态导入它们也不起作用。 请参阅 --> Edit 3

我知道我尝试过的很多事情可能与问题无关,但问题本身对我来说毫无意义。比如,为什么组件作为Router 不理解的类型的对象传递? Test.svelte 实际上只有 &lt;h1&gt;TEST COMPONENT&lt;/h1&gt;

编辑:

将以下代码添加到我的__layout.svelte&lt;script&gt;&lt;/script&gt; 部分:

// Contains logging information used by tests
let logbox = ''
// Handles the "conditionsFailed" event dispatched by the router when a component can't be loaded because one of its pre-condition failed
function conditionsFailed(event) {
  // eslint-disable-next-line no-console
  console.error('Caught event conditionsFailed', event.detail)
  logbox += 'conditionsFailed - ' + JSON.stringify(event.detail) + '\n'
  // Replace the route
  replace('/wild/conditions-failed')
}
// Handles the "routeLoaded" event dispatched by the router after a route has been successfully loaded
function routeLoaded(event) {
  // eslint-disable-next-line no-console
  console.info('Caught event routeLoaded', event.detail)
  logbox += 'routeLoaded - ' + JSON.stringify(event.detail) + '\n'
}
// Handles the "routeLoading" event dispatched by the router whie a route is being loaded
// If the route is dynamically imported, such as with the `import()` syntax, then there might be a delay before the route is loaded
function routeLoading(event) {
  // eslint-disable-next-line no-console
  console.info('Caught event routeLoading', event.detail)
  logbox += 'routeLoading - ' + JSON.stringify(event.detail) + '\n'
}
// Handles event bubbling up from nested routes
function routeEvent(event) {
  // eslint-disable-next-line no-console
  console.info('Caught event routeEvent', event.detail)
  logbox += 'routeEvent - ' + JSON.stringify(event.detail) + '\n'
}

之后我在它下面放了以下内容,如this test example所示:

<Router 
  {routes} 
  on:conditionsFailed={conditionsFailed}
  on:routeLoaded={routeLoaded}
  on:routeLoading={routeLoading}
  on:routeEvent={routeEvent}
/>

这些都没有被调用,只有上图中看到的红色控制台消息。

编辑 2:

按照 Thomas Heennes 的建议,我将 &lt;Router {routes} /&gt; 替换为 __layout.svelte 文件中的每个组件,如下所示:

<script>
  import Router from 'svelte-spa-router'
  import Navbar from "$lib/Navbar.svelte";
  import Sidebar from "$lib/Sidebar.svelte";
  import Home from './index.svelte'
  import About from './about/index.svelte'
  import Contact from './contact/index.svelte'
  import Products from './products/index.svelte'
  import Test from './Test.svelte';

  const routes = {
    // Exact path
    '/': Home,
    //'/about': About,
    //'/contact': Contact,
    //'/products': Products,
    //'/test': Test
  }
</script>

<Navbar />

<Sidebar />

<Routes {routes} />

<style>
</style>

它们都不起作用。

编辑 3:

有趣的是,我注意到动态导入路由会使我的本地服务器崩溃。 xD

const routes = {
  // Exact path
  '/': wrap({
        asyncComponent: () => import('./index.svelte')
  }),
  '/about': wrap({
        asyncComponent: () => import('./about/index.svelte')
  }),
  '/contact': wrap({
        asyncComponent: () => import('./contact/.svelte')
  }),
  '/products': wrap({
        asyncComponent: () => import('./products/.svelte')
  }),
  '/test': wrap({
        asyncComponent: () => import('./Test.svelte')
  }),
}

我导入哪一个都没有关系,如果我只导入其中一个或同时导入所有这些。

这是这次冒险的控制台输出:

window is not defined
ReferenceError: window is not defined
    at getLocation (Router.svelte:38:31)
    at start (Router.svelte:59:23)
    at Object.subscribe ([Path to project]/node_modules/svelte/store/index.js:51:20)
    at Router.svelte:493:36
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (/src/routes/__layout.svelte:112:85)
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (eval at instantiateModule ([Path to project]/node_modules/vite/dist/node/chunks/dep-fcec4469.js:67775:28), <anonymous>:55:122)
    at $$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at Object.render ([Path to project]/node_modules/svelte/internal/index.js:1710:26)
history is not defined
ReferenceError: history is not defined
    at Router.svelte:455:10
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (/src/routes/__layout.svelte:112:85)
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (eval at instantiateModule ([Path to project]/node_modules/vite/dist/node/chunks/dep-fcec4469.js:67775:28), <anonymous>:55:122)
    at $$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at Object.render ([Path to project]/node_modules/svelte/internal/index.js:1710:26)
    at render_response (file://[Path to project]/node_modules/@sveltejs/kit/dist/ssr.js:561:28)
    at async respond_with_error (file://[Path to project]/node_modules/@sveltejs/kit/dist/ssr.js:1148:10)
    at async respond$1 (file://[Path to project]/node_modules/@sveltejs/kit/dist/ssr.js:1392:4)
/node_modules/svelte-spa-router/Router.svelte:413
            const match = routesList[i].match(newLoc.location);
                                                     ^

TypeError: Cannot read properties of null (reading 'location')
    at eval (/node_modules/svelte-spa-router/Router.svelte:413:45)
    at Object.subscribe ([Path to project]/node_modules/svelte/store/index.js:53:9)
    at eval (/node_modules/svelte-spa-router/Router.svelte:406:29)
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (/src/routes/__layout.svelte:112:85)
    at Object.$$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at eval (eval at instantiateModule ([Path to project]/node_modules/vite/dist/node/chunks/dep-fcec4469.js:67775:28), <anonymous>:55:122)
    at $$render ([Path to project]/node_modules/svelte/internal/index.js:1702:22)
    at Object.render ([Path to project]/node_modules/svelte/internal/index.js:1710:26)
    at render_response (file://[Path to project]/node_modules/@sveltejs/kit/dist/ssr.js:561:28)

【问题讨论】:

  • 您是否尝试过将您的&lt;Router {routes} /&gt; 组件一一替换为所有单独的路由组件? IE。 &lt;Home /&gt; 然后 &lt;About /&gt; 等。它将帮助您隔离导致问题的组件并让您走上正确的道路。如果您仍需要帮助,请随时使用这些测试的结果更新您的问题。
  • @ThomasHennes 按照你的建议做了,但没有一个产生任何问题。
  • 那么当你的routes 对象中有一个单一的路由定义时,路由器实际上工作正常吗?我的想法是完全替换&lt;Router {routes} /&gt;语句,先用&lt;Home /&gt;,然后用&lt;About /&gt;等,以便单独测试每个组件,希望可能是某个组件坏了。但是,如果您的路由器单独适用于每条路由,那真的很奇怪。您是否尝试过增量添加路线?首先是routes = { '/': Home },然后是routes = { '/': Home, '/about': About },等等?
  • “那么当你的路由对象中有一个单一的路由定义时,路由器实际上可以正常工作吗?” - 不,我的意思是他们都没有工作,同样的错误仍然存​​在。我将编辑我的问题以澄清这一点。
  • 哦,我刚刚注意到您使用的是 SvelteKit 而不是 Svelte! svelte-spa-router 顾名思义,旨在为客户端 Svelte 项目(即不是 SvelteKit 项目)提供路由解决方案。 SvelteKit 提供了自己的处理路由的框架。更重要的是,svelte-spa-router 并不是要在服务器端运行,而 SvelteKit 会这样做(至少在初始页面加载时)。您应该参考 SvelteKit 路由并相应地调整您的代码。

标签: javascript svelte sveltekit


【解决方案1】:

svelte-spa-router 被设计为Svelte 项目(仅限客户端)的路由解决方案。它不适用于服务器端渲染的 SvelteKit 项目。

SvelteKit,这是一个通用(CSR + SSR)框架,提供its own routing solution,可以在客户端和服务器端工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-24
    • 2021-11-11
    • 2016-08-19
    • 2018-08-04
    • 2020-09-25
    • 2023-03-04
    • 1970-01-01
    • 2022-11-24
    相关资源
    最近更新 更多