0.0.7 • Published 7 years ago

flue-vue v0.0.7

Weekly downloads
6
License
ISC
Repository
github
Last release
7 years ago

Flue - Flux + Vue

Yep, another flux implementation

Francesco Saverio Zuppichini

What it is?

Flue is flux-pattern based state management library for your Vue.js applications.

Be awere that Flue is still in Beta. Any feedback/comment about it are appreciated.

Installation

npm install -S flue-vue

And import in your root component.

import { flue } from 'flue-vue'

Vue.use(flue)

After that, Flue will be available as $store inside any component.

//SomeVueComponent.vue
export default {
    data() { ... }
    // inside a vue component
    this.$store
    this.$store.actions.something() // call an actions from a store
    this.$store.state // access the global shared state
}

To add a store to Flue

import yourStore from './YourStore.js'
import { flue } from 'flue-vue'
flue.addStore(yourStore) // add one
flue.addStores([yourStore, ...]) // add multiple

Introduction

Flue is flux-pattern based state management library for your Vue.js applications.

You do not know what Flux pattern is? Take a look here

Flue is a Object Oriented Framework that combines the Redux single state paradigm and stateless reducers into a friendly environment. It uses a Vue Virtual Machine in order to automatically make "reactive" the store's state so no binding/event emitting is needed. You take it, you put in your component and it works.

Quick Start

Let's show a short example in order to introduce you to the basic concepts. This is how you create a Store

import { flue, Store } from 'flue-vue'

// You need to extend the Store class
class WelcomeToFLue extends Store {
    constructor () {
        super()
        this.state.hasSaidWelcome = false
    }

    reduce (action) {
        this.reduceMap(action, {
            SAY_WELCOME: ({ text }) => {
                console.log("Welcome to Flue")
                this.state.hasSaidWelcome = true 
            }
        })
    }

    actions(ctx) {
        return {
            sayWelcome () {
                ctx.dispatchAction('SAY_WELCOME')
            },
        }
    }
}

const welcomeToFlue = new WelcomeToFLue()
// add it to flue
flue.addStore(welcomeToFlue)
// then the actions can be directly called
flue.actions.sayWelcome() // "Welcome to Flue"

console.log(flue.state.hasSaidWelcome) // true

Store

Each Store must be created by extending the Store class exposed by Flue, it provides a common interface to reduce and fire actions.

State

The state must be initialised into the constructor in order to make it reactive. Otherwise Vue.set() must be called everytime a new entry is added into it. In our example

constructor () {
        super()
        this.state.hasSaidWelcome = false
}

We initialize the state by setting hasSaidWelcome to false

The state can be also passed in the constructor

const initialState = { hasSaidWelcome: false }
new Store({ initialState })

Reduce

Each Store can implement the reduce method. It receives an action as argument and switch behavior accordingly on the its type. Usually, a switch statement is used.

By following our example:

    reduce (action) {
        switch (action.type) {
            case 'SAY_WELCOME': ({ text }) => {
                console.log("Welcome to Flue")
                this.state.hasSaidWelcome = true 
            }
        })
    }

reduceMap can be also used to create a map with an actions types and functions.

    reduce (action) {
        this.reduceMap(action, {
            SAY_WELCOME: ({ text }) => {
                console.log("Welcome to Flue")
                this.state.hasSaidWelcome = true 
            }
        })
    }

It makes the code faster to write. An other example:

this.reduceMap(action, {
    ADD_FOOD_TO_SHOPPING_CART: this.addFoodToShoppingCart,
    REMOVE_FOOD_FROM_SHOPPING_CART: this.removeFoodFromShoppingCart,
    CHECK_OUT: this.checkOut
})

Actions

Each Store can implement the actions function to return an Object of actions. In our example:

actions(ctx) {
    return {
        sayWelcome () {
            ctx.dispatchAction('SAY_WELCOME')
        },
    }
}

This special function is fetched by flue and flat into a common object in order to provide a global API interface for the components. Actions can be called directly from the $store pointer inside a component. Following our previous example:

export default {
    \\inside a component
    this.$store.actions.sayWelcome()
}

The context is passed to actions in order to call the store's method from the actions.

Remember that you can always create a single action and dispatch it using store.dispatch() method.

import { aStore } from 'aStore.js'

const anAction = { type: 'FOO', payload: {} } // the classic way
const anAction = new Action('FOO', {}) // the explicit way, when the payload can be removed if it is empty
const anAction = aStore.createAction('FOO', {})

aStore.dispatch(anAction)

//or you can use flue

import { flue } from 'flue-vue'

flue.dispatch(anAction)

Subscribe

For convenience is it possible to subscribe for updates in any store. Since we are using a promise base dispatcher, then also async operations are support and the listeners will be called at the right time.

flue.subscribe((store) => { console.log(store.state) }) \\ subscribe to the global store

aStore.subscribe((store) => { console.log(store.state) }) \\ subscribe to a specific store

What else?

For more deep understanding you can read the documentation page about the Store class.

Providers

It may be convenient to add some external package directly into Flue in order to make them available at all the stores and components. An example using axios a well know promised based HTTP client.

import axios from 'axios' 

flue.addProvider({ key: 'client', source: axios })

flue.providers.client.get(...)

Middleware

You can use Redux middleware. In the following example, you can see how to add the classic redux-logger middleware to Flue.

import { flue } from 'flue-vue'
import Store1 from './Store1.js'

import logger from 'redux-logger'

flue.addStore(Store1)
flue.applyGlobalMiddleware([apiMiddleware, logger]) // apply middlewere to all the stores

A full example that exposes all the APIs.

import { flue } from 'flue-vue'
import Store1 from './Store1.js'

import logger from 'redux-logger'
import { apiMiddleware } from 'redux-api-middleware'

flue.addStore(Store1)
flue.applyMiddlewareToStore(Store1, [logger]) // apply middleware to a specific store
flue.applyMiddlewareToStores([Store1,...], [logger]) // apply middleware to an flue of stores
flue.applyGlobalMiddleware([apiMiddleware, logger]) // apply middlewere to all the stores

To create a middleware just follow the redux tutorial.

Flue

Flue contains all the stores, it fetches each individual state making reactive and sharing it back. It is a single SuperStore instance. In order to add a Store to Flue you need to call SuperStore.addStore or SuperStore.addStores. Usually, this is done at the root of your application

import yourStore from './yourStore.js'

flue.addStore(yourStore) //now yourStore will be available

Actions

We also provide an Action class. Each action is composed of a type and a payload. You can always do what you want, just do not call reduceMap then.

Flue vs others

Redux

Flue was strongly influenced by Redux, but it has some main differences. First of all, in Flue the state is reactive meaning that each Vue component is automatically notified of the changes and there is no need to subscribe to notifications. Also, stores in Redux are created by the framework, in Flue the created store is added into it. Moreover, Flue supports Redux's middlewares since it implements the same API so there is no need to reinvent the wheel, e.g create a custom logger.

Vuex

Vuex has a strong set of constrains that are not present in Flue. Here the developer is freer, a Store can be implemented as preferred, there is no need to create getters or mutation. ALso, Flue allows writing a more pleasant code using ES6 classes.

Example

You can check out here in order to see a full real-life scenario (open the console to see the logger) or in the test/examples folder.

0.0.7

7 years ago

0.0.6

7 years ago

0.0.5

7 years ago

0.0.4

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.0

7 years ago

0.0.1

7 years ago

1.1.0

7 years ago

1.0.9

7 years ago

1.0.8

7 years ago

1.0.7

7 years ago

1.0.6

7 years ago

1.0.5

7 years ago

1.0.4

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago