使类实例在Svelte中使用存储进行反应



我正在通过创建简单的应用程序来学习Svelte。

该逻辑是使用类编写的。其思想是,所需的所有数据都来自类实例属性。实例不应实例化多次。我正在使用存储提供组件这个实例。

问题是,使用这种方法我无法获得反应性。我尝试了可读写存储,但没有任何帮助。使用OOP仍然可以获得反应性,我能做什么?重新分配和创建新实例的成本将很高。

编辑

我不能在REPL中编这个例子,因为这个类太大了。

Parser.js

export default class Parser {
constructor() {
this._history = [];
}
parse(string) {
this._history.push(string)
}
get history() {
return this._history;
}
}

在这里,我将实例传递给商店。

parserStore.js

import writable from "svelte/store";
import Parser from "Parser.js"
export const parserStore = writable(new Parser());

在这个组件中,我获得了实例并反应性地使用了一个方法。

Component_1.svelte*

import { parserStore } from "parserStore.js";
$: result = parserStore.parse(binded_input_value);

我想要得到的是使用类方法更新的最新历史属性:

组件2.svelte

import { parserStore } from "parserStore.js";
$: history = parserStore.history;
{#each history as ... }

我知道,这不是最好的例子,但我想要的是通过商店提供的反应类实例。实际上,这些值是最新的,但不会导致组件的重新渲染。当组件被挂载时,数据是最新的,但在什么都没有之后,即使实例的属性发生了更改,也会重新渲染。

简短回答

据我所知,你不能这样做。

更长的答案

根据某些因素(如偏好、现有库等(,可能会有绕过它的方法

解决方案1:使用类中的存储

第一个也是最直接的一个是在类本身中使用存储:

Parser.js

import { writable } from 'svelte/store'
class Parser {
constructor() {
this._history = writable([])
}
parse(string) {
console.log(string)
this._history.update(v => [...v, string])
}
get history() {
return this._history;
}
}

parserStore.js

import { Parser } from './Parser.js'¨
export const parser = new Parser()

组件1.svelte

<script>
import { parser } from './parserStore.js';
let value
let { history } = parser

$: parser.parse(value);
</script>
<input bind:value />
{#each $history as h}<p>{h}</p>{/each}

注意这个类中只有history部分是存储区。

解决方案2:使用自定义存储重写

从本质上讲,这种方法与以前的方法非常接近,但在Svelte社区中更为常见。从技术上讲,它只是包装了内置商店,以获得一些额外的功能。

parserStore.js

import { writable } from 'svelte/store'
export const parser = (() => {
const P = writable([])  
const { set, subscribe, update } = P    

function parse(string) {
P.update(arr => [...arr, string])
}

return {
parse,
subscribe
}
})()

组件1.svelte

<script>
import { parser } from './parserStore.js';
let value
$: parser.parse(value)
</script>
<input bind:value />
{#each $parser as h}<p>{h}</p>{/each}

请注意,这里不再有history属性,您可以直接在parser上迭代,如果您仍然想要历史属性,则必须稍微调整代码:

parserStore.js

...
return {
parse,
history: { subscribe }
}

组件1.svelte

<script>
...
const { history } = parser
...
</script>
{#each $history as h}<p>{h}</p>{/each}

遇到了同样的问题,并找到了一个解决方案,即如何使用"反应性";苗条的课堂。

在svelte中,任何具有订阅功能的东西都是一个商店。因此,如果你想为商店创建一个类,你必须实现一个订阅函数。

import { writable } from 'svelte/store';
class ClassStore {
constructor() {
this._history = writable([])
}
parse(string) {
this._history.update(v => [...v, string])
}

subscribe(run) {
return this._history.subscribe(run);
}
}
export const classStore = new ClassStore();

以下是一个工作示例:https://svelte.dev/repl/8e3f4f664cc14710afce0c9683e04652?version=3.42.6

请注意:
这里似乎有一个更复杂的例子,带有类AND自定义存储(!(:

https://gist.github.com/3lpsy/55da83779a50f603a78ae8331e360a37

有趣:

/*
I recently jumped into svelte programming and wanted to create a class/singleton that could double as a reactive writable store. 
I did things very wrong until people on the discord confirmed how wrong my implementation was so I wanted to provide a simple example.
So below is a simple account store you can use. I'm not sure if it's optimal or even correct, but it's better than my first attempt. 
Feel free to provide feedback.
*/
...

编辑,
并且这个:

6.7使用类商店

https://livebook.manning.com/book/svelte-and-sapper-in-action/chapter-6/v-5/106
来自曼宁关于斯维尔特的书
链接中的代码部分是可见的,您只需创建一个新帐户就可以免费获得整个章节(如果出现弹出窗口(。

潜水员:
https://devlinduldulao.pro/svelte-in-a-nutshell-with-store-code-sample/https://medium.com/geekculture/svelte-stores-352c61759a88

还有另一种方法可以将可写的添加到类本身。添加save()方法:

Parser.js

export default class Parser {
constructor() {
this._history = [];
}
parse(string) {
this._history.push(string)
}
get history() {
return this._history;
}

save() {
return this;
}
}

组件1.svelte

import { Parser } from "Parser.js";
import writable from "svelte/store";
// create new class instance
const p = new Parser();
// add some values
p.parse(binded_input_value);
// save that class instance
const parserStore = writable(p.save());
// can be called after page is loaded
function showHistory() {
console.log(get(parserStore).history);
}

您可以在页面加载后保留该值,可以将p.save()传递给子组件,或者如果组件2不是子组件,则可以使用setContext()getContext()。。。

重点是在任何给定时刻保存类的状态。。。

相关内容

  • 没有找到相关文章

最新更新