📦 Fast, Simple, and Lightweight State Manager for Vue 3.0 built with composition API, inspired by Vuex.

Overview

v-bucket codecov Code Grade Maintainability License Last updar

NPM STATUS: npm size download

📦 Fast, Simple, and Lightweight State Management for Vue 3.0 built with composition API, inspired by Vuex.

Table of Contents

Main features

Access modules

Advanced

Examples

Running the examples:

$ npm run dev
$ yarn dev

Running tests

$ npm run test
$ yarn test

installation

install this package from NPM:

$ npm install @mediv0/v-bucket

or yarn:

$ yarn add @mediv0/v-bucket

usage

first you need to create your bucket. create an index.js file, then import createBucket from v-bucket to start creating your store, like this:

import { createBucket } from "@mediv0/v-bucket";

const bucket = createBucket({
    states: {
        // your states here
    },
    mutations: {
        // your mutations here
    },
    getters: {
        // your getters here
    },
    modules: {
        // your modules here
    }
});
export default bucket;

then import it in your app entry point, main.js like this:

import { createApp } from "vue";
import App from "./dev.vue";
// importing your bucket
import bucket from "./bucket/index";

createApp(App)
    .use(bucket)
    .mount("#app");

using with composition api

for using v-bucket inside the setup() function you need to import useBucket first. like this:

<script>
import { useBucket } from "@mediv0/v-bucket"
export default {
    setup() {
        // get access to the v-bucket
        const bucket = useBucket();

        // ...

        return {
            // ....
        };
    }
};
</script>

using with option api

like vue 2.X apps you can access v-bucket on the vue instance outside of the setup() function. like this:

<script>
export default {
    mounted() {
        // accessing bucket on this
        this.$bucket

        // ...
    },
    methods: {
      click() {
        this.$bucket.commit("SET_ID", this.id);

        // ...
      }
    }
};
</script>

you only import useBucket when you want to use it inside setup() function

states

this is a single object contains all your application states.

accessing states:

 mounted() {
    // accessing id state in the root level
    this.$bucket.state.id

    // ...

    // accessing name state in the nested tree
    this.$bucket.state.module1.name
 },

declare states inside your bucket (index.js):

import { createBucket } from "@mediv0/v-bucket";

const bucket = createBucket({
    states: {
        id: 1,
        name: "mahdi",
        phone: 120304
    },
    mutations: {
        // your mutations here
    },
    getters: {
        // your getters here
    },
    modules: {
        // your modules here
    }
});
export default bucket;

NOTE: states object will be reactive by default. that means they will react to changes and update based on it.

NOTE: it's better to use mutations or getters to access states.

mutations

use mutations when you need to change a state value, all mutations will take 2 parameter:

  • state
  • payload
const bucket = createBucket({
    mutations: {
        SET_ID(state, payload)
    },
});

with state, you can have access to states object and change its value by passing payload.

NOTE: payload is optional.

const bucket = createBucket({
    states: {
      id: 0,
      count: 0
    }
    mutations: {
        SET_ID(state, payload) {
          // changing id value
          state.id = payload
        }
        COUNT_UP(state) {
          // without payload
          state.count++;
        }
    },
});

you can't access mutations directly. you have to call them with commit method. like this:

methods: {
   click() {

     this.$bucket.commit("SET_ID", 5);
     this.$bucket.state.id // must be 5 now!

     // ...

     this.$bucket.commit("SET_ID"); // calling without a payload

   }
 }

getters

you can use getters to access states and their values. getters are like Vue computed methods, they will cache the state and return it only when the state value change.

const bucket = createBucket({
    states: {
      id: 0,
      name: "mahdi",
      phone: 893729837
    }
    getters: {
      GET_ID(state) {
        return state.id
      }
    },
});

all getters will take 1 parameter:

  • state (using to access states object)

using it in your vue app:

methods: {
   click() {

     this.$bucket.getters["GET_ID"] // will return id state

     // ...
   }
 }

actions

Actions are like mutations. the difference is:

  • They can handle asynchronous operations
  • Instead of mutating the state, actions commit mutations.
const bucket = createBucket({
    states: {
      count: 0
    }
    mutations: {
      increment(state) {
        state.count++
      }
    },
    actions: {
      increment(context) {
        context.commit("increment");
      }

      // or using argument destructuring to simplify the code.
      anotherAction({ commit }) {
        // do some action!
        commit("someMutation");
      }
    }
});

also you can call other actions with context.dispatch. like this:

const bucket = createBucket({
    actions: {
      actionOne(context) {
        context.commit("someMutation");
      }
      actionTwo(context) {
        context.dispatch("actionOne"); // dispatching actionOne from another action!
      }
    }
});

also you can't access actions directly. you have to call them with dispatch method. like this:

methods: {
   click() {

     this.$bucket.dispatch("increment") // will call increment action

     // ...

   }
 }

the context parameter will return root instance of our bucket. this is useful when working with modules.

modules

from vuex docs:

  • Due to using a single state tree, all states of our application are contained inside one big object. However, as our application grows in scale, the store can get really bloated. To help with that, Vuex allows us to divide our store into modules.
const moduleA = {
  states: { ... },
  mutations: { ... },
  actions: { ... },
  modules: { ... }
}

const moduleB = {
  states: { ... },
  mutations: { ... },
  actions: { ... },
  modules: { ... }
}

const bucket = createBucket({
  modules: {
    // register modules
    moduleA,
    moduleB
  }
});

bucket.state.moduleA // `moduleA`'s state
bucket.state.moduleB // `moduleB`'s state

every modules also can have their own states, mutations, actions or even modules

how to access module states

all modules will be installed under the root module. so by accessing the root state you can also have access to its children. like this:

methods: {
   click() {

     this.$bucket.state.moduleA.name // `moduleA`'s name state
     this.$bucket.state.moduleB.id // `moduleB`'s id state

     // ...
   }
 }

how to access module getters

if you remember we used bracket notation to access getters, you can access your module's getter by defining its path. like this:

methods: {
   click() {

     this.$bucket.getters["moduleA/get_id"]; // `moduleA`'s getter
     this.$bucket.getters["moduleB/get_name"]; // `moduleB`'s name state

     // you can go deep as many levels as you want
     this.$bucket.getters["moduleA/moduleB/moduleC/moduleH/...];


     // ...
   }
 }

they above code represent something like this:

-root

-----moduleA

-----moduleB

how to access module mutations

mutations are like getters, you can access your module's mutation by defining its path. like this:

methods: {
   click() {

     this.$bucket.commit("moduleA/set_id"); // we can access mutations by commit()
     this.$bucket.commit("moduleB/set_name"); // we can access mutations by commit()

     // ...
   }
 }

how to access module actions

actions are like getters, you can access your module's actions by defining its path. like this:

methods: {
   click() {

     this.$bucket.dispatch("moduleA/set_id"); // we can access mutations by dispatch()
     this.$bucket.dispatch("moduleB/set_name"); // we can access mutations by dispatch()

     // ...
   }
 }

sometimes you need to access another module's mutation or action within the current module

since the context parameter refer to the root module, you can access all of your modules by defining their path. like this:

// inside module a
const moduleA = {
  actions: {
    commitModuleB(context) {
      context.commit("moduleB/set_name"); // commiting in module b from module a
    }
    dispatchModuleB(context) {
      context.dispatch("moduleB/request"); // dispatching in module b from module a
    }

    dispatchRoot(context) {
      context.dispatch("rootMutation") //  dispatching in root from module a
    }
  }
};

NOTE: if you want to access a module from another module like example, you need to define your paths from root

plugins

v-bucket store accept the plugins option that exposes hooks for each mutation and actions. plugins will allow you to extend the functionality of v-bucket

a hello world plugin

const helloWorld = () => {
    // called when the store is initialized
    console.log("hello world");
    return bucket => {
        // access bucket store
    };
};

export const bucket = createBucket({
    // other options
    // ...
    plugins: [helloWorld()]
});

the function that has the responsibility to be a plugin, need to return another function. v-bucket will use that function to expose the root module and its hooks

plugin hooks

there are two hooks available:

bucket.onMutation(callback(mutation))

this function will be called after every mutation. also, it will return information about the mutation that has been fired.

this information contains: name, module and full path of that mutation.

bucket.onAction(callback(action))

this function will be called after every action. also, it will return information about the action that has been fired.

this information contains: name, module and full path of that action.

usage:

const myPlugin = socket => {
    return bucket => {
        socket.on("data", data => {
            store.commit("receiveData", data);
        });
        store.onMutation(mutation => {
            if ((mutation.name = "UPDATE_DATA")) {
                socket.emit("update", mutation.payload);
            }
        });
    };
};

if you want use Class syntaxt, no worries! do something like this:

Class Snapshot {
  // other methods and options
  // ...
  constructor() {
    this.snapshots = [];
  }

  plugin() {
    return bucket => {
      bucket.onMutation(mutation => {
        if (mutation.name = "UPDATE_SNAPSHOT") {
          this.snapshots.push(mutation.payload);
        }
      })
    }
  }
}

easy right?

and use it like this in your store:

export const bucket = createBucket({
    // other options
    // ...
    plugins: [new Snapshot().plugin()]
});

Since you have access to the bucket root module in the plugins, you also able to commit, dispatch and use getters.

Contribution

Please make sure to read the Contributing Guide before making a pull request.

feel free to request new features!

License

MIT

Todo

  • mapGetters
  • mapActions
  • optimization and refactoring
  • and more....
You might also like...
A util package to use Vuex with Composition API easily.

vuex-composition-helpers A util package to use Vuex with Composition API easily. Installation $ npm install vuex-composition-helpers This library is n

Simple, unopinionated, lightweight and extensible state management for Vue 3
Simple, unopinionated, lightweight and extensible state management for Vue 3

Simple, unopinionated, lightweight and extensible state management for Vue 3

Simple counter with Vue.js and Vuex as state management

vuex-counter Project setup npm install Compiles and hot-reloads for development npm run serve Compiles and minifies for production npm run build Li

Todos-VUEX - A todo list made using Vue, Vuex, Axios and JSON Placeholder API.

todos Project setup npm install Compiles and hot-reloads for development npm run serve Compiles and minifies for production npm run build Lints and

A project to demonstrate the use of Store and state, getters, mutations in Vuex and VueJS

Vuex State Sample 🎁 🎯 A project to demonstrate the use of Store and state, getters, mutations in Vuex and VueJS. Create Vuex Store and use it to hol

Redux bindings for VueJS inspired by Vuex.

redux-vuex Redux bindings for VueJS inspired by Vuex. 👉 For the old Vue 2 version check out the legacy branch 👈 First things first Why don't you use

💾 Persist and rehydrate your Vuex state between page reloads.
💾 Persist and rehydrate your Vuex state between page reloads.

vuex-persistedstate Persist and rehydrate your Vuex state between page reloads. Install npm install --save vuex-persistedstate The UMD build is also a

💾🔗🖥️ Share, synchronize and persist state between multiple tabs  with this plugin for Vuex. TypeScript types included.
💾🔗🖥️ Share, synchronize and persist state between multiple tabs with this plugin for Vuex. TypeScript types included.

vuex-multi-tab-state This Vuex plugin allows you to sync and share the status of your Vue application across multiple tabs or windows using the local

Vuex state persistance and synchronization between tabs/windows.

vuex-basement Vuex state persistance and synchronization between tabs/windows. Tested to work with Vue2. One Shortcomming (please read before use). Th

Owner
mehdi
🔥 summoning the devil .... 99%
mehdi
A state management library for react inspired by vue 3.0 reactivity api and immer

Welcome to costate ?? A state management library for react inspired by vue 3.0 reactivity api and immer costate is a tiny package that allows you to w

工业聚 7 Mar 29, 2022
Type safe state management inspired by Vuex

Sinai Type safe state management inspired by Vuex. This library includes many type level hacks. Use at your own risk and do not use if you are unsure

Katashin 110 Nov 27, 2022
Lightweight Vue 3 composition API-compatible store pattern library with built-in undo/redo functionality.

vue-store Lightweight Vue 3 composition API-compatible store pattern library. Offers a simple alternative that is on par with VueX in terms of feature

Korijn van Golen 23 Sep 27, 2022
A tiny state management library for Vue Composition API.

vue-unstated A tiny state management library for Vue Composition API based on unstated-next which is for React. ?? Demo ?? Installation $ npm install

Xuesu Li 30 Jan 28, 2023
E-Store built with Vue's Composition api script setup, mocked a server, vuex, vue-router

Frontend Mentor - E-commerce product page solution This is a solution to the E-commerce product page challenge on Frontend Mentor. Frontend Mentor cha

_Chi_ 0 Apr 8, 2022
A tiny (198 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores

A tiny (198 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores

Nano Stores 2.2k Dec 27, 2022
The state manager ☄️

☄️ effector The state manager Table of Contents Introduction Effector follows five basic principles: Installation Documentation Packages Articles Comm

effector ☄️ 4k Dec 28, 2022
Elm-inspired Application State Management for Vue.js.

VuElm It's a Vue state management inspired by Elm architecture. Concepts There are basically four elements on Elm architecture: Model, Actions, Update

Keuller Magalhães 36 May 5, 2021
Saving Quick Notes - Vue, Vuex, Vue Router, Vue Composition API

Saving Quick Notes - Vue Project setup yarn install Compiles and hot-reloads for development yarn run serve Compiles and minifies for production yar

Karol Fabjańczuk 5 Mar 31, 2022
A vue boiler plate with state management, vuex, vue-router that can be backed by a laravel restful api using jwt auth

Laravel 6 (LTS) Vue.js Frontend Boilerplate A Vue.js Frontend starter project kit template/boilerplate with Laravel 6 Backend API support. Features Re

MUWONGE HASSAN 2 Oct 12, 2021