npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

evex

v2.2.0

Published

Evex is a pattern to realize the Flux design pattern by means of DOM Events

Downloads

15

Readme

Evex v2.2.0

Build Status codecov Greenkeeper badge

Evex is a pattern to realize the Flux design pattern by means of DOM Events.

Evex is also a tool for building Evex pattern with capsid.js.

Explanation

In Evex, an event object works as Action in Flux pattern. Triggering an event on a DOM element corresponds to dispatching an action in Flux. The bubbling mechanism works as Dispatcher in Flux. The parent node which handles the bubbled events (actions) corresponds to Store. After handling events (actions), stores change their states and dispatch update events back to View. These steps consists the Flux loop.

| Flux | Evex | |----------------|----------------------------------------------| | Action | Event object | | Action Creator | Event Constructor | | Dispatcher | Event bubbling mechanism | | Store | DOM Element with action event handlers | | Store callback | event handler on Store | | View | DOM Element with update event handler |

Event as action

Event object works as an action in Evex. Here we call this type of event action-event.

An action-event should be an instance of CustomEvent. Action-event's name corresponds to the type of Action in terms of FSA. CustomEvent object has versatile detail property. In Evex, detail property works as the payload of the action. An action-event should be dispatched with bubbles option true to reach its corresponding Store and action callbacks.

Dispatching action-event

In Evex, there is no explicit dispatcher. Instead, the event bubbling mechanism works as the dispatcher. When an action is needed, the action-event is dispatched at the DOM element which the user interacted. The action-event bubbles up in the tree. The first parent node which knows the action's type catches it. This node is Store in Evex and this whole process works as Dispatcher in Evex.

Store in Evex

In Evex, Store is placed somewhere in the DOM tree. If you only needs one store like redux, it should be placed at body element or document.

The store reacts and change its state according to the bubbled events. So each handling of the action should be implemented as the event handler at the store's dom element.

After handling the action, the store should publish the event to its descendant nodes that subscribe to update event. This event shouldn't be bubbling to avoid multiple updates on nested structures.

Example store implementation in capsid.js:

const {
  component,
  on,
  notifies,
  emits
} = capsid

@component('store')
class Store {
  constructor () {
    this.count = 0
  }

  @on('increment')
  increment () {
    this.count++
    this.update()
  }

  @on('decrement')
  decrement () {
    this.count--
    this.update()
  }

  @notifies('update', '.store-observer')
  update () {
    return this.count
  }
}

@component('plus-button')
class PlusButton {
  @on.click
  @emits('increment')
  increment () {}
}

@component('minus-button')
class MinusButton {
  @on.click
  @emits('decrement')
  decrement () {}
}

@component('count-label')
class Label {
  @on('update')
  update ({ detail: count }) {
    this.el.textContent = count
  }
}
<body class="store">
  <button class="plus-button">+</button>
  <button class="minus-button">-</button>
  <p class="store-observer count-label">0</p>
</body>

See the working example in codepen.io.

In this example, Store implements two actions increment and decrement and it publishes update event to its descendant nodes that have store-observer class. In this example, having store-observer means the subscription to the store state.

Examples

Evex as a tool

evex is also a tool for realize Evex pattern with [capisd.js][]. Here is the explanation about how to use it.

:cd: Install

npm install evex

Usage

First create the store with @store decorator`. The store needs to be a capsid component as well.

const { component } = require('capsid')
const { store } = require('evex')

@component
@store
class Store {}

This is the store. Then you need to add actions to this store by adding @action decorator to methods.

const { component } = require('capsid')
const { action, store } = require('evex')

const CREATE_USER = 'action/CREATE_USER'

@component
@store
class Store {
  @action(CREATE_USER)
  createUser (store, event) {
    store.user = { name: event.detail }
  }
}

Then this store can handle action/CREATE_USER DOM event. For example, your component which emits CREATE_ACTION event invokes the CREATE_USER action on UserModule.

APIs

@store decorator

  • @param {Function[]} opts.modules

This creates the store class. Store class needs to be a capsid component.

const { component } = require('capsid')
const { store } = require('evex')

@component
@store
class MyStore {
}
<div class="my-store"></div>

You can additionally specify modules. The action in module classes works as the action of the store.

class Module {
  @action('foo')
  foo (store, action) {
    // do some action
  }
}

@store({ modules: [Module] })
class Store { ... }

@action decorator

@action decorator registers the method as an action.

@store
class Store {
  @action('foo')
  foo (store, action) {
  }
}

@action decorator can work both on Store and Module.

class Module {
  @action('bar')
  bar (store, action) {
  }
}

@store({ modules: [Module] })
class Store {
  ...
}

@dispatches decorator

@dispatches decorator adds dispatching of the action at the end of the action. If action returned the promise, then it dispatches after it resolved. The detail of the dispatched action object is returned value or resolved value.

class Module {
  @dispatches('bar')
  @action('foo')
  foo (store, action) {
    // do some action
    // after that 'bar' action will be dispatched
  }
}

History

  • 2017-12-20 v1.5.0 Add on method to store.
  • 2017-12-18 v1.4.0 Add dispatch method to store.
  • 2017-12-17 v1.2.0 Improve dispatches decorator.