A lightweight data-binding (or so-called mvvm) library, providing both declarative template and imperative call ways.
"domod" is named from "DOM", "Model" and their two-way relationship.
Philosophy
- Connection, relation, dependency. No matter it is data or dom, it is a tree. Tree and tree node relations make up graphs.
- Reactive programming.
Simple Application
A simple application:
const state = {
count: 0,
increase() {
this.count++
}
}
DMD.relate(state, {
negative: {
resultFrom() {
return this.count < 0
}
}
})
const view = `
<div>
<h1 m-style="{ color: $negative ? 'red' : 'green' }">{{$count}}</h1>
<button m-onclick="$count = $count - 1">-</button>
<button m-onclick="$increase()">+</button>
</div>
`
DMD('#app', view, state)
API
An online demo.
An example of a form:
<script src="path/to/domod.js" charset="utf-8"></script>
<form id="form1">
<div>
<label>gender:</label>
<input m-onclick="$form.gender = 'male'"
type="radio" name="gender" value="male" m-checked="$form.gender === 'male'">Male
<input m-onclick="$form.gender = 'female'"
type="radio" name="gender" value="female" m-checked="$form.gender === 'female'">Female
</div>
<div>
<label>mobile:</label>
<input type="text" name="mobile" m-value="$form.mobile">
<span m-style="{ display: !!$form.mobile ? 'inline' : 'none' }">
You input: {{$parse($form.mobile)}}.
</span>
<span m-class="['some-class', { red: !$mobileInputStatus }]"
m-style="{ display: !$mobileInputStatus ? 'inline' : 'none' }">
{{$form.mobile}} is {{$mobileInputStatus}}!
</span>
</div>
<div>
<label>age:</label>
<select name="age" m-value="$form.age.value">
<option m-each="$val in $form.age.options" m-value="$val">{{$val}}</option>
</select>
</div>
<div>
<label>city:</label>
<select name="city" m-value="$form.city.value">
<option m-each="($val, $key) in $form.city.options" m-value="$key">
{{$val.code}}.{{$val.name}}
</option>
</select>
</div>
</form>
<script>
var store = {
parse: function (v) {
return parseInt(v);
},
validateMobile: function () {
return /^1[3|4|5|8][0-9]\d{8}$/.test(this.form.mobile);
},
form: {
gender: 'female',
mobile: '15210001000',
age: {
value: '37-54',
options: [
'0-18',
'19-36',
'37-54',
'55-200'
]
},
city: {
value: '1',
options: [
{ code: 1, name: 'beijing' },
{ code: 2, name: 'newyork' },
{ code: 3, name: 'tokyo' },
{ code: 4, name: 'london' },
{ code: 5, name: 'paris' }
]
}
}
};
store.mobileInputStatus = store.validateMobile();
DMD.relate(store, {
'form.mobile': {
dnstream: 'mobileInputStatus',
resultIn: function (v) {
var newVal = store.validateMobile();
console.log(`mobile is ${newVal}`);
DMD.$(store, 'mobileInputStatus', newVal);
}
}
});
DMD('#form1', store);
</script>
Advance
Imperative Calling
Providing a data object:
var store = {
value: '1'
};
Now assign a property color
which would be computed from the property value
.
There are two methods available, kernel
and relate
.
The kernel
method, which is actually a constructor function, accepts two parameters besides the data object: the property and its relation object.
new domod.kernel(store, 'color', {
resultFrom: function () {
return isNaN(parseInt(store.value)) ? 'red' : 'green';
}
});
The relate
method, which is somehow a composition of kernel
, accepts one parameter besides the data object: an object representing a map from property names to relation objects.
domod.relate(store, {
color: {
resultFrom: function () {
return isNaN(parseInt(store.value)) ? 'red' : 'green';
}
}
});
Relation Object
A relation object can be declared with these properties:
Property | Effect |
---|
resultFrom | Do when the property is being got, and return the value computed. |
resultIn | Do when the property is being set. |
upstream | Other properties as the property's dependencies. |
dnstream | Other properties as the property's effects. |
Standalone Libraries
Kernel
See the code and doc for more.
ObservableArray
Also called OArray for short. See the code and doc for more.
License
MIT