Omi教程-元件

【當耐特】發表於2017-02-10

元件

Omi框架完全基於元件體系設計,我們希望開發者可以像搭積木一樣製作Web程式,一切皆是元件,元件也可以巢狀子元件形成新的元件,新的元件又可以當作子元件巢狀至任意元件形成新的元件...

Omi教程-元件

簡單元件

這裡使用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教程-元件

相關文章