組件
Omi框架完全基於組件體系設計,我們希望開發者可以像搭積木一樣制作Web程序,一切皆是組件,組件也可以嵌套子組件形成新的組件,新的組件又可以當作子組件嵌套至任意組件形成新的組件...
簡單組件
這里使用Todo的例子來講解Omi組件體系的使用。
class Todo extends Omi.Component {
constructor(data) {
super(data);
}
add (evt) {
evt.preventDefault();
this.data.items.push(this.data.text);
this.data.text = '';
this.update();
}
style () {
return `
h3 { color:red; }
button{ color:green;}
`;
}
handleChange(target){
this.data.text = target.value;
}
render () {
return `<div>
<h3>TODO</h3>
<ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>
<form onsubmit="add(event)" >
<input type="text" onchange="handleChange(this)" value="{{text}}" />
<button>Add #{{items.length}}</button>
</form>
</div>`;
}
}
Omi.render(new Todo({ items: [] ,text : '' }),"body");
組件生成的HTML最終會插入到body中。上面的例子展示了Omi的部分特性:
- data傳遞: new Todo(data,..)的data可以直接提供給render方法里的模板
- 局部CSS: h3只對render里的h3生效,不會污染外面的h3;button也是同樣的
- 聲明式事件綁定: onchange調用的就是組件內的handleChange,this可以拿到當然的DOM元素,還可以拿到當前的event
- 需要手動調用update方法才能更新組件
這里需要特別強調的是,為了更加的自由和靈活度。Omi沒有內置數據變更的自動更新,需要開發者自己調用update方法。
你也可以和oba或者mobx一起使用來實現自動更新。
組件嵌套
如果頁面超級簡單的話,可以沒有組件嵌套。但是絕大部分Web網頁或者Web應用,需要嵌套定義的組件來完成所有的功能和展示。比如上面的Todo,我們也是可以抽取出List。
這樣讓程序易維護、可擴展、方便復用。如,我們抽取出List:
class List extends Omi.Component {
constructor(data) {
super(data);
}
render () {
return `<ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>`;
}
}
怎么使用這個List?我們需要使用Omi.makeHTML把List制作成可以聲明式的標簽,在render方法中就能直接使用該標簽。如下所示:
import List from './list.js';
Omi.makeHTML('List', List);
class Todo extends Omi.Component {
constructor(data) {
super(data);
this.data.length = this.data.items.length;
this.listData = { items : this.data.items };
}
add (evt) {
evt.preventDefault();
this.list.data.items.push(this.data.text);
this.data.length = this.list.data.items.length;
this.data.text = '';
this.update();
}
style () {
return `
h3 { color:red; }
button{ color:green;}
`;
}
handleChange(target){
this.data.text = target.value;
}
render () {
return `<div>
<h3>TODO</h3>
<List name="list" data="listData" />
<form onsubmit="add(event)" >
<input type="text" onchange="handleChange(this)" value="{{text}}" />
<button>Add #{{length}}</button>
</form>
</div>`;
}
}
- 第3行,通過makeHTML方法把組件制作成可以在render中使用的標簽。當然Omi.makeHTML('List', List);也可以寫在List組件的代碼下面。
- 第34行,在父組件上定義listData屬性用來傳遞給子組件。
- 第34行,在render方法中使用List組件。其中name方法可以讓你在代碼里通過this快速方法到該組件的實例。data="listData"可以讓你把this.listData傳遞給子組件。
需要注意的是,父組件的this.listData會被通過Object.assign淺拷貝到子組件。
這樣做的目的主要是希望以后DOM的變更都盡量修改子組件自身的data,然后再調用其update方法,而不是去更改父組件的listData。
關於Omi組件通訊其實有4種方案,這個后續教程會專門來講。
招募計划
- Omi的Github地址https://github.com/AlloyTeam/omi
- 如果想體驗一下Omi框架,請點擊Omi Playground
- 如果想使用Omi框架,請閱讀 Omi使用文檔
- 如果想一起開發完善Omi框架,有更好的解決方案或者思路,請閱讀 從零一步步打造web組件化框架Omi
- 關於上面的兩類文檔,如果你想獲得更佳的閱讀體驗,可以訪問Docs Website
- 如果你懶得搭建項目腳手架,可以試試Scaffolding for Omi,npm安裝omis便可
- 如果你有Omi相關的問題可以New issue
- 如果想更加方便的交流關於Omi的一切可以加入QQ的Omi交流群(256426170)