Using Muxjs is easy to track the app state. What's state and it's tansition? When look back your codes, often find some logic are described as below:
if this condition and this other condition are met, then this value should be 'x'.
Here, vars of condition are state, and condition is transition, so 'x' is the transposition's result. Muxjs give the way to subscribe vars's changs and transition's result 'x''s changes.
Let's look at the diagram of an example case of an stateful application:
Left
of diagram is a view-controller with 5 state (circle) and 3 transition (rhombus).
Right
of disgram is an UI Page with 4 parts, each part depend on one state or transition.
If we can subscribe all changes of state and transition, so we can bind specified DOM opertion when state/transition change,
finally it implement the data to DOM binding , event can do more stuff for a completed MVVM framework such as Zect.
It's usefull, right?
browser:
- mux.js
- mux.min.js (4.1k when gzipped)
<script src="dist/mux.js"></script>
node.js:
npm install muxjs --save
- Zect Vue.js like
- virtual-dom-binding render view with virtual-dom
- data-dom-binding zepto do DOM maniputation
- Deep observe
- The imperfection of "Object.defineProperty"
- Compare defineproperties to looped defineproperty
- Can't observe array's indices
It is a constructor function that allows you to create Mux instance.options
see: Instance Options.
var author = new Mux({
props: {
name: 'firstName lastName'
},
computed: {
firstName: {
deps: ['name'],
fn: function () {
return this.name.split(' ')[0]
}
}
}
})
assert.equal(author.firstName, 'firstName')
- Return:
Function
Class
Create a subclass of the base Mux constructor. options
see: Instance Options.
Class can instance with param propsObj
which will set values to those observered properties of the instance.
var Person = Mux.extend({
props: {
profession: 'programer',
name: ''
}
})
var author = new Person({
name: 'switer'
})
assert.equal(author.profession, 'programer')
assert.equal(author.name, 'switer')
Global configure. Currently supported configurations:
* warn Boolean
if value is false
, don't show any warning log. Default is true
Mux.config({
warn: false // no warning log
})
- Params:
- context
Object
binding "this" tocontext
for event callbacks.
- context
Create a emitter instance.
var emitter = Mux.emitter()
emitter.on('change:name', function (name) {
// do something
}) // subscribe
emitter.off('change:name') // unsubscribe
emitter.emitter('change:name', 'switer') // publish message
- Type:
Function
|Object
Return the initial observed property object for this mux instance.Recommend to using function which return a object if you don't want to share props option's object in each instance:
var Person = Mux.extend({
props: function () {
return {
name: 'mux'
}
}
})
assert.equal((new person).name, 'mux')
props option could be an object:
var Person = new Mux({
props: {
name: 'mux'
}
})
assert.equal((new person).name, 'mux')
- Type:
Object
- Options:
- deps
Array
property dependencies. Restricton:deps
's item could be keyPath (contain.
and[]
, such as: "post.comments[0]"). - fn
Function
Compute function , using as a getter - enum
Boolean
Whether the computed property enumerable or not
- deps
Computed properties definition option. "fn"
will be called if one of dependencies has change, then will emit a change event if "fn"
returns result has change.
var mux = new Mux({
props: {
items: [1,2,3]
},
computed: {
count: {
deps: ['items'],
fn: function () {
return this.items.length
}
}
}
})
assert.equal(mux.cout, 3)
Watch computed property changes:
mux.$watch('count', function (next, pre) {
assert.equal(next, 3)
assert.equal(next, 4)
})
mux.items.push(4)
assert.equal(mux.count, 4)
- Type:
EventEmitter
Use custom emitter instance.
var emitter = Mux.emitter()
emitter.on('change:name', function (next) {
next // --> switer
})
var mux = new Mux({
emitter: emitter,
props: {
name: ''
}
})
mux.name = 'switer'
- Params:
- keyPath
String
property path , such as: "items[0].name" - value [optional]
- or
- props
Object
[optional] data structure as below:
{ "propertyName | keyPath": propertyValue }
- keyPath
- Return: this
Set value to property by property's keyPath or propertyName, which could trigger change event when value change or value is an object reference (instanceof Object). Notice: PropertyName shouldn't a keyPath (name string without contains "[", "]", "." )
var list = new Mux({
items: [{name: '1'}]
})
list.$set('items[0].name', '')
- Params:
- propname
String
only propertyname not keyPath (without contains "[", "]", ".")
- propname
- Return: value
Get property value. It's equal to using "." or "[]" to access value except computed properties.
var mux = new Mux({
props: {
replyUsers: [{
author: 'switer'
}]
}
})
assert.equal(mux.$get('replyUses[0].author', 'switer'))
Notice: Using "." or "[]" to access computed property's value will get a cached result, so you can use "$get()" to recompute the property's value whithout cache.
// define a computed property which use to get the first user of replyUsers
mux.$computed(firstReplyUser, ['replyUsers'], function () {
return this.replyUsers[0].author
})
var users = [{
author: 'switer'
}]
mux.$set('replyUsers', users)
user[0].author = 'guankaishe' // modify selft
assert.equal(post.firstReplyUser, 'switer'))
assert.equal(post.$get('firstReplyUser'), 'guankaishe'))
- Params:
- propname
String
- defaultValue [optional]
- or
- propnameArray
Array
- or
- propsObj
Object
- propname
- Return: this
Define an observerable property or multiple properties.
mux.$add('name', 'switer')
// or
mux.$add(['name']) // without default value
// or
mux.$add({ 'name': 'switer' })
- Params:
- propname
String
property name - deps
Array
Property's dependencies - get
Function
Getter function - set
Function
Setter function - enum
Boolean
whether the computed property enumerable or not - or
- computedPropsObj
Object
- propname
- Return: this
Define a computed property. deps and fn is necessary. If one of deps is observable of the instance, emitter a change event after define. computedPropsObj is using to define multiple computed properties in once, each key of computedPropsObj is property's name and value is a object contains "deps", "fn". Usage as below:
// before define computed
assert.equal(mux.commentCount, undefined)
mux.$computed('commentCount', ['comments'], function () {
return this.comments.length
})
// after define computed
assert.equal(mux.commentCount, 1)
- Params:
- propname
String
[optional] - callback
Function
- propname
- Return:
Function
unwatch handler
Subscribe property or computed property changes of the Mux instance.
var unwatch = mux.$watch('title', function (nextValue, preValue) {
// callback when title has change
})
unwatch() // cancel subscribe
if propname is not present, will watch all property or computed property changes:
mux.$watch(function (propname, nextValue, preValue) {
// callback when title has change
})
- Params:
- propname
String
[optional] - callback
Function
[optional]
- propname
- Return: this
Unsubscribe property or computed property changes of the Mux instance.
// subscribe
mux.$watch('name', handler)
// unsubscribe
mux.$unwatch('name', handler)
// unsubscribe all of specified propertyname
mux.$unwatch('name')
// unsubscribe all of the Mux instance
mux.$unwatch()
- Return:
Object
Return all properties of the instance. Properties do not contain computed properties(Only observed properties).
var mux = Mux({ props: { name: 'Muxjs' } })
mux.$props() // --> {name: 'Muxjs'}
- Return: this | emitter
Reset emitter of the mux instance. If arguments is empty, return the emitter of the instance.
var mux = Mux()
var em = Mux.emitter()
mux.$emitter(em)
var muxEmitter = mux.$emitter() // equal to em
Destroy the instance, remove all listener of the internal emiter of the instance, free all props references.
- Return: Boolean
Whether the instance is destroyed or not.
- 2016/10/14
- $set() will not return this.
- $set({ ... }) will emit in batch
MIT