我正在通过创建简单的应用程序来学习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()
。。。
重点是在任何给定时刻保存类的状态。。。