diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 3d349af51d..695024e47b 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -147,24 +147,7 @@ If a statement consists entirely of an assignment to an undeclared variable, Sve --- -A *store* is any object that allows reactive access to a value via a simple *store contract*. - -The [`svelte/store` module](docs#svelte_store) contains minimal store implementations which fulfil this contract. You can use these as the basis for your own stores, or you can implement your stores from scratch. - -A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. The `.subscribe` method must also return an unsubscription function. Calling an unsubscription function must stop its subscription, and its corresponding subscription function must not be called again by the store. - -A store may optionally contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a *writable store*. - -```js -const unsubscribe = store.subscribe(value => { - console.log(value); -}); // logs `value` - -// later... -unsubscribe(); -``` - ---- +A *store* is an object that allows reactive access to a value via a simple *store contract*. The [`svelte/store` module](docs#svelte_store) contains minimal store implementations which fulfil this contract. Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, and set up a store subscription that will be unsubscribed when appropriate. @@ -189,6 +172,53 @@ Local variables (that do not represent store values) must *not* have a `$` prefi ``` +--- + +You can create your own stores without relying on [`svelte/store`](docs#svelte_store), by implementing the **store contract**: + +1) A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. +2) The `.subscribe` method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store. +3) A store may *optionally* contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a *writable store*. + +```js + +/* Example: a custom writable store for `location.hash` */ + +const subscriptions = []; + +let lastHash; + +const callSubscriptions = () => { + if (location.hash !== lastHash) { + lastHash = location.hash; + for (const subscription of subscriptions) { + subscription(location.hash); + } + } +}; + +window.addEventListener('hashchange', callSubscriptions); + +const hashStore = { + subscribe(subscription) { + subscription(location.hash); // Call subscription with current value + subscriptions.push(subscription); // Subscribe to future values + return () => { // Return an "unsubscribe" function + const index = subscriptions.indexOf(subscription); + if (index !== -1) { + subscriptions.splice(index, 1); // Remove the subscription + } + }; + }, + set(hash) { + location.hash = hash; // Set the value + callSubscriptions(); // Synchronously notify all subscriptions + } +}; + + +``` + ### <script context="module">