vue-supply
Create resources that can automatically be activated and deactivated when used (like subscriptions)
Table of contents
Why do I need this?
Efficiently managing reactive and living data from an external source can become difficult in a large app or when using vuex. With vue-supply
, you can easily consume data and automatically activate or deactivate subscriptions.
The Vue+Meteor demo project demonstrate how to use Meteor reactive data easily with vue-supply
inside components and a vuex store.
What kind of data?
vue-supply
is suitable for any kind of reactive and realtime data. For example:
- meteor reactive data (tracker, minimongo...) and realtime subscriptions/publications
- apollo GraphQL subscriptions (using websockets)
- firebase realtime subscriptions
- ...
How does it work?
With vue-supply
, you create Vue instances extending the Supply
definition. You then define two methods: activate
and deactivate
. For example, you can subscribe to a realtime publication in the activate
method and destroy this subscription in the deactivate
method. When you will use this Supply
in your components (called 'consumers'), it will automatically activate itself when it is first used (with the grasp
method) or deactivate itself when no component use it anymore (with the release
method). You can also easily store the realtime data inside the Supply
and access it in the consumer components or in vuex getters. Anywhere in your code, you can wait for a Supply
to be activated with the ensureActive
method.
Supply
also understands the notion of loading the data: when your subscription is being processed, just increment the loading
property. When it's ready, decrement loading
. If all the operations are done (which means that loading
value is 0
), the Supply
will emit the is-ready
event you can listen to. You can also use the ready
property directly in your templates (or somewhere else). There is also a ensureReady
method that waits for the Supply
to be ready.
Installation
npm install --save vue-supply
Default import
Vue
Browser
The plugin should be auto-installed. If not, you can install it manually with the instructions below.
Vue
Usage
A supply is a Vue instance which is responsible for managing a piece of dynamic data (for example, a Meteor, GraphQL or Firebase subscription with data that may change and update from the server). It has an deactivated state (default), and an activated state when the data should be updated (for example, when a subscription is running).
To create a supply, write a Vue definition object extending the Supply
definition:
extends: Supply // Vue options here
Then you can manually create a supply with the Vue constructor:
const TestResource = TestResource
The two methods when using the supply are:
supply.grasp()
which incrementssupply.consumers
by1
supply.release()
which decrementssupply.consumers
by1
To activate or deactivate the supply, use the grasp
and release
methods where you need to access the supply:
console // 0TestResourceconsole // 1console // Access the dataTestResourceconsole // 0
The supply will emit a consumers
event with the count when it changes.
The supply is active if it has one or more consumers
. When it becomes active, it calls the activate
method, which you should override in the definition:
extends: Supply methods: { // Subscribe }
Also, the active
event is emitted on the supply, with a true
boolean argument, and the is-active
event.
TestResource
And when there are no more consumer for the supply, the deactivate
method is called:
extends: Supply methods: { // Subscribe } { // Unsubscribe }
Also, the active
event is emitted on the supply, with a false
boolean argument, and the is-not-active
event.
There is a active
computed boolean available that changes when the supply is activated or deactivated:
TestResource
You can also use the supply.ensureActive()
method which return a promise that resolves as soon as the supply is activated (or immediatly if it is already):
TestResource
Registration
It is recommended to register the supply definition to enable injection in components and in the vuew store.
Usage in components
Inside a component, add a mixin with use(name, manageKeepAlive = true)
to automatically grasp
and release
the supply when the component is created and destroyed, using the name used in the registration (see above):
// This component now uses TestResource mixins: // Use the values in computed properties computed: { return this$supplyTestResourcesomeData } // ...
Then you can use the supply data inside computed properties or inside methods with the this.$supply[name]
object:
// Use the values in computed propertiescomputed: { return this$supplyTestResourcesomeData }
Usage in Vuex store
Inside a vuex store, you can inject getters that use supplies:
supply: use: 'TestResource' getters: TestResourceitems getters: getters'all-items'length
Before creating the Vuex store, transform the options with the injectSupply(options, cache)
method:
const supplyCache = {}const suppliedStoreOptions = const store = suppliedStoreOptions
Provide the supply cache to the root Vue instance so that the supplies created for the store are reused in the components:
// ... supplyCache
Then to activate/deactivate the supply, you can either call the grasp
and release
methods inside actions:
supply: use: 'TestResource' getters: TestResourceitems actions: 'subscribe-action' // Request usage in the store // Ex: subscribing to a Meteor publication TestResource 'unsubscribe-action' // No longer used in the store // Ex: unsubscribing from a Meteor publication TestResource
Or with the mixins and the use
function inside components using the getter:
// This component now uses TestResource supply mixins: // Use getter that utilize the supply computed: ...
Asynchronous data
A loading system is included in the supply supplies. Change the loading
integer property:
0
means the supply is ready to be consumed (for example, data is loaded). This is the default value.1
or more means there is loading in progress
You should change the loading
property inside the activate
and deactive
methods:
You can get the loading state with the ready
computed property, a boolean which is true
when there are no loading in progress. It can directly used inside computed properties:
// Use the values in computed properties computed: { return TestResourceready }
There are the ready
(with a boolean argument), is-ready
and is-not-ready
events.
You can also use the supply.ensureReady()
method which return a promise that resolves as soon as the supply is ready (or immediatly if it is already):
TestResource
There is a useful function, consume
, which comes in handy when you only need to use the supply periodically. It both graspes and wait for ready and return a release
function:
// This will grasp and wait for the supply to be 'ready'const release = await // Count of active supply consumersconsole// When you are done with the supply, release it
Base supply definition
It's often useful to create a base definition for each supply.
Example for Meteor:
// base.js extends: Supply methods: { this } { this } meteor: $lazy: true
Example supply:
// Items.js extends: base { return items: } meteor: $subscribe: 'items': { return Items }
Examples
Basics
Create a supply:
extends: Supply { return someData: null } methods: { console // Use the integer `loading` property // 0 mean ready thisloading ++ // Faking a server request here :p } { console }
Register the supply:
Use the supply in components:
// This component now uses TestResource mixins: // Use the values in computed properties computed: { return this$supplyTestResourcesomeData } // ...
Or in the vuex store:
supply: use: 'TestResource' getters: // Use the supply data in getters TestResourcesomeData actions: 'subscribe-action' // Request usage in the store // Ex: subscribing to a Meteor publication TestResource 'unsubscribe-action' // No longer used in the store // Ex: unsubscribing from a Meteor publication TestResource async 'consume-action' commit // This will wait for the supply to be 'ready' const release = await // Count of active supply consumers console // When you are done with the supply, release it