AntonLapshin / proxy-observable

ES6 Proxy observable implementation. Object and Arrays

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

proxy-observable

ES6 Proxy observable implementation. Supports Arrays and Objects

Attention!

Please keep in mind that the implementation is based on ES6 Proxy feature which is a very slow thingy

Build Status Coverage Status Gemnasium Lib Size npm GitHub stars

Install

npm install proxy-observable --save

Usage

Just call observable() if you want an object or an array to be observable

API

import observable from "proxy-observable";

const soldier = {
  name: "Titus Pullo",
  age: 36,
  inventory: observable({
    sword: "Dagger",
    coins: 0
  }),
  friends: observable(["Gaius Octavian"])
};

console.log(JSON.stringify(soldier, null, 2)); 
{
  "name": "Titus Pullo",
  "age": 36,
  "inventory": {
    "sword": "Dagger",
    "coins": 0
  },
  "friends": [
    "Gaius Octavian"
  ]
}

Object

const onCoinsChanged = 
  soldier.inventory.on("coins", (value, prev) => {
    console.log(value, prev); // 100 0
  });
soldier.inventory.coins = 100; // onCoinsChanged will be called
soldier.inventory.off(onCoinsChanged);

Simply speaking soldier.inventory is still just a simple object, but it has additionally a few things:

  • method on Attach a handler to an event for the elements
  • method once Attach a handler to an event for the elements. The handler is executed at most once per element per event type
  • method off Remove an event handler
  • you can call just soldier.inventory.newProp = value to define a new prop, instead of soldier.inventory["newProp"] = value

Array

soldier.friends.on("change", item => {
  console.log(item); // "Lucius Vorenus" twice
});
soldier.friends.on("shift", item => {
  console.log(item); // "Gaius Octavian"
});
soldier.friends.push("Lucius Vorenus"); 
soldier.friends[0] = "Lucius Vorenus"
soldier.friends.shift();

soldier.friends is still just a simple array with on, once and off methods and predefined events

Array events

change - Fires when an item in an array is changed:

arr[0] = "new value";
// or
arr.push("new value");

pop - Fires when pop method is called:

arr.pop();

shift - Fires when shift method is called:

arr.shift();

any other Array's methods


any event

Do you want to track all the events? Just use any like this:

// object
soldier.inventory.on("any", (value, prev, prop) => {
  console.log(prop); // "coins", "shield"
});
soldier.inventory.coins = 1000;
// This way you can track when a new property is added to an object
soldier.inventory.shield = "Gold Shield"; 

// array
soldier.friends.on("any", (value, prev, e) => {
  // e is "change", "pop", "shift" or any other method of Array
  console.log(e); 
});
soldier.friends[0] = "Mark Antony";
soldier.friends.pop();

Browser Usage

<!-- ES6 not minified version -->
<script src="../node_modules/proxy-observable/bin/proxy.observable.es6.js"></script>
<!-- ES5 minified version -->
<!--<script src="../node_modules/proxy-observable/bin/proxy.observable.min.js"></script>-->

<script>
  const soldier = {
    name: "Titus Pullo",
    age: 36,
    inventory: observable({
      sword: "Dagger",
      coins: 0
    })
  };

  console.log(soldier.inventory.coins); // 0
  soldier.inventory.on("coins", (value, prev) => {
    console.log(value, prev); // 100 0
  });
  soldier.inventory.coins = 100;
</script>

One more example

const Frodo = observable({
  name: "Frodo Baggins",
  bag: observable([]),
  friends: observable([])
});

const Samwise = {
  name: "Samwise Gamgee",
  friends: [Frodo]
};

Frodo.friends.on("change", friend => {
  console.log(`Frodo has a new friend ${friend.name}! Cograts!`);
});

Frodo.bag.on("any", (item, prev, e) => {
  if (e === "change") {
    console.log("Frodo got a new item: " + item);
    if (item === "ring") {
      console.log("Oh! My Precious!");
    }
  } else if (e === "pop" || e === "shift"){
    console.log("Frodo lost an item: " + item);
    if (item === "ring") {
      console.log("Gollum! I'm coming to get you!");
    }        
  }
});

Frodo.friends.push(Samwise);
Frodo.bag.push("apple");
Frodo.bag.push("ring");
Frodo.bag.pop();
Frodo.friends.pop();

API

observable(ctx) => ctx

Makes an object or array observable

Returns: object|array - Observable object or array

Param Type Description
ctx object|array Input Object or Array

observable.on(e, callback) => callback

Subscribes on event (property changed)

Returns: function - Input callback for unsubscribing

Param Type Description
e string Event name or property name
callback function Callback

Callback signature

(value, prev, e) => {}

Param Type Description
value any Current value
prev any Previous value
e string Event name or property name

observable.once(e, callback) => callback

Subscribes once. The handler is executed at most once per element per event type

Returns: function - Input callback for unsubscribing

Param Type Description
e string Event name or property name
callback function Callback

observable.off(callback) => boolean

Removes event handler

Returns: boolean - True if unsubscribed

Param Type Description
callback function Callback

ES6 JavaScript Proxy MDN documentation

Browsers support made by godban

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
iOS Safari
iOS Safari
Chrome for Android
Chrome for Android
Edge last 3 versions last 10 versions last 5 versions last 4 versions last 2 versions last 3 versions

License

MIT

About

ES6 Proxy observable implementation. Object and Arrays

License:MIT License


Languages

Language:JavaScript 90.4%Language:HTML 9.6%