Svelte 商店未在屏幕上更新

gre*_*ter 3 svelte svelte-store svelte-3

我是 Svelte 的新手,犯了一个菜鸟错误。我有一个到服务器的 websocket 连接,我正在记录数百条消息并将它们添加到商店,但页面根本不更新。

应用程序.svelte

<script>
    import Socket from "./Socket.svelte"
    import msgs from './stores'
</script>

<main>
    <Socket items="{$msgs}"/>
</main>
Run Code Online (Sandbox Code Playgroud)

Socket.svelte

<script>
    export let items
</script>

{items.length}
{#if items}
    {#each items as msg, i}
        <p>{i} {msg}</p>
    {/each}
{:else}
    <p class="loading">waiting...</p>
{/if}
Run Code Online (Sandbox Code Playgroud)

套接字.js

import { readable, writable } from 'svelte/store';

let msgs = []
const msgStore = readable(msgs)
export default msgStore

const socket = new WebSocket("ws://localhost:8080/socket");

socket.binaryType = "arraybuffer";

socket.onopen = function (event) {
  msgs = [...msgs, "Connected"];
};

socket.onmessage = function (event) {
  msgs = [...msgs, event];
  console.log(msgs.length)

  const msg = JSON.parse(event.data)
  const msgType = msg.messageType
  console.log(msgType)
};
Run Code Online (Sandbox Code Playgroud)

在浏览器中,我得到了0items 数组的初始长度,但它永远不会更新,即使消息正在流动。

rix*_*ixo 5

你实际上从来没有将任何东西推入msgStore,只是msgs数组......这本身不是反应性的。

在您的情况下最简单的是使用可写存储:

const msgs = []
export const msgStore = writable([])

socket.onmessage(e => {
  ...
  msgs.push(msg)
  msgStore.set(msgs)
})
Run Code Online (Sandbox Code Playgroud)

您可以通过导出其派生而不是可写存储来防止外部篡改:

export const publicMsgStore = derived(msgStore, x => x)
Run Code Online (Sandbox Code Playgroud)

或者,要使用可读存储一步完成此操作,您需要它来包装整个逻辑:

export const msgStore = readable([], set => {
  const msgs = []
  ...
  socket.onmessage(e => {
    ...
    msgs.push(msg)
    set(msgs) // <= UPDATE THE STORE!!
  })
})
Run Code Online (Sandbox Code Playgroud)

您需要调用注入的set函数来更改可读存储的值(或通知它其值已更改)。