Skip to content

Instantly share code, notes, and snippets.

@husa
Created December 25, 2015 10:57
Show Gist options
  • Save husa/d1c487568b848f9ec7e7 to your computer and use it in GitHub Desktop.
Save husa/d1c487568b848f9ec7e7 to your computer and use it in GitHub Desktop.
ES2015 observable model
class Events {
constructor () {
this._events = {};
}
on (name, listener, context) {
// support multiple event names
this._events[name] = this._events[name] || [];
// check if already present
this._events[name].push({listener, context});
}
off (name, listener) {
if (name == null) this._events = {};
if (!this._events[name]) return;
if (listener == null) this._events[name] = [];
let index = this._events[name].findIndex(o => o.listener === listener);
if (index !== -1) this._events[name].splice(index, 1);
}
trigger (name, ...args) {
if (!this._events[name]) return
this._events[name].slice(0).forEach(e => {
e.listener.call(e.context || null, ...args);
});
}
}
class Model extends Events {
constructor() {
super();
this._props = {};
}
inherit(props) {
this._props = Object.assign({}, this._props, props);
}
observe() {
let props = Object.assign(this._props, this.constructor.props);
this._props = props;
Object.keys(props).forEach( prop => {
Object.defineProperty(this, prop, {
set (value) {
this.trigger(`change:${prop}`, value, this);
this._props[prop] = value;
},
get () {
return this._props[prop];
}
})
this[prop] = props[prop];
}, this);
}
}
class A extends Model {
static props = {
prop_1: -1
}
}
class A1 extends A {
static props = {
prop1: 10
}
constructor () {
super()
this.inherit(super.constructor.props);
}
}
class A2 extends A1 {
static props = {
prop2: 20
}
constructor() {
super();
this.inherit(super.constructor.props);
}
}
class Store extends A2 {
static props = {
prop3: 30
}
constructor() {
super();
this.inherit(super.constructor.props);
this.observe()
}
}
let b = new Store
b.on('change:prop1', function () {
console.log(arguments);
})
b.prop1 = 20;
class BaseModel extends Events {
observe (props = {}) {
this._props = props;
Object.keys(props).forEach( prop => {
Object.defineProperty(this, prop, {
set (value) {
this.trigger(`change:${prop}`, value, this);
this._props[prop] = value;
},
get () {
return this._props[prop];
}
})
this[prop] = props[prop];
}, this);
}
}
class Model extends BaseModel {
constructor () {
super()
this.observe({
a: 10,
b: 20
});
this.on('change:a', console.log.bind(console));
this.a = 30
console.log(this.a)
}
}
let m = new Model
class MyModel extends Model {
static properties = {
// name: type
firstName: 'string',
// name: [type, default, required]
lastName: ['string', 'Doe', false],
age: ['number', 0]
// name: object(extended)
hero: {
type: 'string',
default: 'regular-hero',
required: false,
// possible values
values: ['regular-hero', 'super-hero', 'mega-hero']
}
// getters and setters
fullName: {
get () {
return `${this.firstName} ${this.lastName}`
}
set (value = '') {
value = value.split(' ')
this.firstName = value[0]
this.lastName = value[1]
}
}
}
constructor () {
super()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment