付费悬赏:svelte的store和snapshot问题

第一个,store的subscribe(订阅)功能失灵

在开发页签(tab)功能时,我尝试了五六天,查阅了很多外部文档,依然无法解决关闭最后一个页签时页签重置的问题。

问题描述:如下图所示,一共有4个页签,关闭前3个都没有问题,能够正确关闭,不会影响其他页签。但是,只要关闭最后一个页面,就会自动关闭其他页签,只保留默认的前2个。百思不得其解!

img


store.js

import {writable}from 'svelte/store';

let menus = [{u:'/home',n:'首页'},{u:'/home/program',n:'项目管理'}]

function openedTab(obj)

{const {subscribe,update} =writable(menus)

return {subscribe,open: (obj) =>update(() => {menus.push({u: obj.url,n: obj.name})return menus        }),

close: (obj) =>update(() => {let index =0;for (let item of menus) {if (item.u === obj.u) {break;}index++;}if (index > -1)menus.splice(index,1);return menus;})}}

export const opened_tab =openedTab()


+page.svelte

<script>

import Header from "../layout/Header.svelte";

import LeftMenu from "../layout/SideBar.svelte";

import Tab_item from "./items/Tab_item.svelte";

/* 同步打开页面 */

import {opened_tab} from "../../store/stores.js";

</script>

<div class="sticky"> <Header/></div><div class="flex flex-row"> <div class="basis-1/8 ml-3 mt-3"> <LeftMenu/> </div> <div class="basis-7/8 mx-3 my-3">

<main>

<div class="w-full px-3 bg-slate-100 mt-1 rounded-t-lg">

 {#each $opened_tab as m}

<Tab_item url={m.u} name={m.n}>

</Tab_item>

{/each}

</div> <slot> </slot>

</main> </div></div>

**
第二个,snapshot功能失灵。**

问题描述:当打开多个项目信息页面时,编辑其中输入框,此时切换至其他页面时,需要不丢失已输入信息。官方给出的解决方案是使用snapshot(快照)。参照官方案子,经过多轮多天尝试,该功能在使用浏览器自带的前一页、后一页操作是有效的,但是使用goto或href是无效的!

img



+page.svelte



/** @type {import('./$types').Snapshot<string>} */

export let form;$:comment = null

/* 添加$:,用于保护(preserve)前一路由页面数据 */

$:proinfo = data.data[0]

export const snapshot = { capture: () => comment, restore: (value1) => comment = value1};

<label for="comment">Comment</label><textarea id="comment" bind:value={comment}></textarea>

采用chatgpt:
对于商店订阅功能的第一个问题出在 store.js 中的openTab 函数上。 您应该使用 writable([...menus]) 来创建菜单数组的副本,而不是使用 writable(menus)。 否则,菜单数组将在多个订阅之间共享,从而导致关闭最后一个选项卡时出现意外行为。

这是更正后的 opensTab 函数:

import { writable } from 'svelte/store';

let menus = [{ u: '/home', n: '首页' }, { u: '/home/program', n: '项目管理' }];

function openedTab(obj) {
  const { subscribe, update } = writable([...menus]); // Use spread operator to create a copy

  return {
    subscribe,
    open: (obj) =>
      update(() => {
        menus.push({ u: obj.url, n: obj.name });
        return menus;
      }),

    close: (obj) =>
      update(() => {
        let index = 0;
        for (let item of menus) {
          if (item.u === obj.u) {
            break;
          }
          index++;
        }
        if (index > -1) menus.splice(index, 1);
        return menus;
      }),
  };
}

export const opened_tab = openedTab();

对于快照功能的第二个问题,您似乎没有正确使用快照功能。 要使用快照,您需要在要捕获其状态并稍后恢复它的特定组件上定义它。

以下是如何使用快照功能:

首先,将快照存储添加到 page.svelte 组件中。

import { page } from 'svelte-snapshot';
export const snapshot = page;

然后,在 page.svelte 组件中,将快照添加到要保留状态的特定部分。 例如,如果你想保留评论输入,你可以这样做:

// page.svelte

<script>
  import Header from "../layout/Header.svelte";
  import LeftMenu from "../layout/SideBar.svelte";

  /* Add the snapshot feature */
  import { page } from 'svelte-snapshot';
  export const snapshot = page;

  /** @type {import('./$types').Snapshot<string>} */
  export let form;
  $: comment = null;

  /* 添加$:,用于保护(preserve)前一路由页面数据 */
  $: proinfo = data.data[0];
</script>

<!-- Rest of the template -->

现在,快照功能应该按预期工作,并且使用浏览器的后退和前进按钮在页面之间导航时将保留评论输入值。

使用 goto 或 href 时,它可能不会触发浏览器的后退和前进事件,这可以解释为什么快照功能在这些情况下无法按预期工作。 相反,最好使用内置的 Svelte 路由器或其他一些可以正确管理浏览器历史记录的路由库。

1.store的subscribe(订阅)功能失灵
store的值是不是在某些地方被重置了,你使用update方法来更新下你的store的值
2.snapshot功能失灵
参考 https://stackoverflow.com/questions/71564541/going-back-to-the-previous-page-with-goto-sveltekit-navigation

你的第一个问题可以看看这篇博客:

你这个问题,使用错误导致的

第一个问题
你在store.js中定义了一个openedTab函数,但在返回对象时没有正确使用get方法来获取存储的值。在你的openedTab函数中,应该使用get方法来获取menus数组的当前值,并在open和close方法中使用set方法来更新该值。

svelte的store和snapshot问题
可以参考下


Svelte 原理浅析与评测_落落落落克的博客-CSDN博客 简介Svelte 是一个构建 web 应用程序的工具,与 React 和 Vue 等 JavaScript 框架类似,都怀揣着一颗让构建交互式用户界面变得更容易的心。但是有一个关键的区别:..._carbon components svelte https://blog.csdn.net/qq_34998786/article/details/123059573

需要调试下你关闭标签那部分的代码,应该是有问题的。修改为如下代码看行不行:

close: (obj) => update(() => {  
    let index = menus.findIndex(item => item.u === obj.u);  
    if (index > -1) {  
        menus.splice(index, 1);  
    }  
    return menus;  
})

检查一下页面重置逻辑代码有没有问题

关闭标签的业务代码检查一下