简体   繁体   English

Svelte 是否具有仅监听嵌套属性更改的机制?

[英]Does Svelte have the mechanism to listen to only nested properties changes?

I need to do some logic on nested property change.我需要对嵌套属性更改做一些逻辑。 I only found that thing to do that我只找到那个东西来做那个

$: c, console.log('updated');

This approach was suggested by official svelte developer from this Twitter thread .这种方法是由Twitter 线程中的官方svelte开发人员建议的。 But svelte stores do not work properly with that.但是 svelte stores不能正常工作。 For instance I have following code:例如我有以下代码:

<script>
    import { writable } from 'svelte/store';
    const s = writable({ x: 1, y: 2 });

    $: $s && console.log('store updated');
    $: $s.x && console.log('store x updated');
</script>

<button on:click={() => $s.y++}>
    Update y
</button> 

The $: $sx part will be triggered on change of $sy . $: $sx部分将在$sy发生变化时触发。 How to avoid that??如何避免?

REPL to play around. REPL来玩。

PS VueJS has the feature @Watch('s.x') . PS VueJS具有@Watch('s.x')功能。

You can subscribe to the store per usual, but only do your logic if the property you're interested in changes like so:您可以像往常一样订阅商店,但只有在您感兴趣的属性发生如下变化时才执行您的逻辑:


    // this is the only bit relevant to this component
    let thingWeAreInterestedIn;
    
    // subscribe to changes in the store
    const unsubscribe = s.subscribe(val => {
        
        // but if there's no change to the property we're interested in. Do nothing
        if(val.y === thingWeAreInterestedIn) return;
        
        // else update it!
        thingWeAreInterestedIn = val.y
    })
    
    // this now only fires when $s.y is changed
    $: console.log('y updated', thingWeAreInterestedIn)

REPL here 在这里回复

You could work around that with the help of a reactive variable REPL您可以在反应变量REPL的帮助下解决这个问题

<script>
    import { writable } from 'svelte/store';
    const s = writable({ x: 1, y: 2 });

    $: $s && console.log('store updated');
    $: xRef = $s.x
    $: xRef && console.log('store x updated');
</script>

<button on:click={() => $s.y++}>
    Update y
</button>

Since the dependency xRef is now a primitive value who didn't change, the reactive log won't be triggered由于依赖xRef现在是未更改的原始值,因此不会触发反应日志

In addition to the options presented in other comments, there are also npm packages that can create a store linked to the property of an object in another store.除了其他评论中提供的选项外,还有 npm 包可以创建一个商店链接到另一个商店中的 object 的属性。 I make one such package, svelte-writable-derived .我做了一个这样的 package, svelte-writable-derived

import { propertyStore } from "svelte-writable-derived";
let xStore = propertyStore(s, "x");
let deepStore = propertyStore(s, ["deeply", "nested", "property"]);

If you prefer specifying a nested property by string instead of array, someone else made a svelte-keyed package that will do what you want.如果您更喜欢通过字符串而不是数组指定嵌套属性,其他人可以制作一个精巧svelte-keyed来满足您的需求。

Svelte by itself provides no such functionality as part of its philosophy to ship only as much code to end users as is needed, and no more. Svelte 本身不提供这样的功能,作为其理念的一部分,即只向最终用户提供所需的代码,仅此而已。 Sure, svelte-writable-derived is less than 1KB, but that's hundreds of bytes that developers who don't need this feature don't have to ship.当然, svelte-writable-derived不到 1KB,但不需要此功能的开发人员不必交付数百字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM