Minimalist view layer for the web.
Keet specific goal is to offer less APIs, familiar/vanilla code structures and a possible remedy to choice paralysis. It was never intended superior in features compare to most major web frameworks and waste no effort to become such. Generally Keet is more flexible, decent render performance with loose coupling, less complicated design and workflow. You might surprise with the logic and small learning curve it offers. It's also only 5kb gzip in size. Under the hood it use morphdom to do
DOM-diffing
.
To try out Keet is to include it from a CDN or npm.
Create a HTML file:-
<html>
<head>
<script src="//cdn.rawgit.com/syarul/keet/master/keet-min.js"></script>
</head>
<body>
<div id="app"></div>
</body>
<script>
// your codes goes here
</script>
</html>
Or from npm:-
npm install keet
Start by constructing a class expression as child of Keet
. Supply a string argument
to the component method mount
. Within the string, you can assign a state within handlebars i.e: {{<myState>}}
.
NOTE: You also may use ternary expression as your state i.e:
{{<ternaryState>?show:hide}}
where<ternaryState>
is aboolean
value
import Keet from 'keet'
class App extends Keet {
state = 'World'
}
const app = new App()
app.mount('Hello {{state}}').link('app')
Basic idea how we can create a simple counter
import Keet from 'keet'
import { html } from 'keet/utils'
class App extends Keet {
count = 0
add (evt) {
this.count++
}
}
const app = new App()
app.mount(html`
<button id="counter" k-click="add()">
{{count}}
</button>
`).link('app')
The traditional way, is you assign display:none
to style attributes or use css, which still use resources. To use it wrap your html string with {{?<state>}}<myDynamicNode>{{/<state>}}
and assign boolean value to the state.
NOTE: With dynamic nodes it complete remove your node from the DOM and free up your resources which is good on mobile devices.
import Keet from 'keet'
import { html } from 'keet/utils'
class App extends Keet {
show = false
toggle () {
this.show = !this.show
}
}
const app = new App()
app.mount(html`
<button id="toggle" k-click="toggle()" attr="{{show?foo:bar}}" style="color: {{show?red:blue}};" {{show?testme:test}}>toggle</button>
<div id="1">one</div>
<!-- {{?show}} -->
<div id="2">two</div>
<div id="3">three</div>
<div id="4">four</div>
<!-- {{/show}} -->
<div id="5">five</div>
`).link('app')
To map an array to elements use the {{model:<myModelName>}}<myModelTemplate>{{/model:<myModelName>}}
. It has basic methods add/update/remove. To go beyond that requirement you could extend
the class
method of createModel
NOTE: Only mutation methods has attached listener, so usage of
map
filter
reduce
concat
or directly reassigned new value to thelist
is encouraged and does not affect thedom-diffing
efficiency.
import Keet from 'keet'
import { html, createModel as CreateModel } from 'keet/utils'
let task = new CreateModel()
class App extends Keet {
task = task
componentWillMount () {
// callBatchPoolUpdate - custom method to inform changes in the model.
// If the component has other states that reflect the model value changes
// we can safely ignore calling this method.
this.task.subscribe(model =>
this.callBatchPoolUpdate()
)
}
}
const app = new App()
app.mount(html`
<ul id="list">
<!-- {{model:task}} -->
<li id="{{id}}">
{{taskName}}
<input type="checkbox" checked="{{complete?checked:null}}">
</li>
<!-- {{/model:task}} -->
</ul>
`).link('app')
let taskName = ['run', 'jog', 'walk', 'swim', 'roll']
for (let i = 0; i < taskName.length; i++) {
app.task.add({
id: i,
taskName: taskName[i],
complete: i % 2 !== 0
})
}
// update a task
app.task.update('id', {
id: 0,
taskName: 'sleep',
complete: true
})
app.task.destroy('taskName', 'roll')
Writing everything in a single file is not advisable, where you should split multiple components. To have multiple components together, use the sub-component feature with {{component:<mySubComponent>}}
.
NOTE: Always has a root-element with id on sub-components html template literal, so the main component able to lookup for insertion.
import Keet from 'keet'
import { html } from 'keet/utils'
class Sub extends Keet {
// provide the node id where this sub will rendered
el = 'sub'
}
const sub = new Sub()
sub.mount(html`
<div id="sub">
this is a sub-component
</div>
`)
class App extends Keet {
subc = sub
}
const app = new App()
app.mount(html`
<div id="container">
<div>parent</div>
<!-- {{component:subc}} -->
</div>
`).link('app')
For more usage cases visit the examples directory
The MIT License (MIT)
Copyright (c) 2018 Shahrul Nizam Selamat