Omi原理-Hello Omi


Hello Omi

Omi框架的每個組件都繼承自Omi.Component,本篇會去完成Omi的Component的基本錐形,讓其能夠渲染第一個組件。

omi.js實現

var Omi = {};
Omi._instanceId = 0;
Omi.getInstanceId = function () {
    return Omi._instanceId++;
};

Omi.render = function(component, renderTo){
    component.renderTo = typeof renderTo === "string" ? document.querySelector(renderTo) : renderTo;
    component._render();
    return component;
};

module.exports = Omi;
  • Omi.getInstanceId 用來給每個組件生成自增的ID
  • Omi.render 用來把組件渲染到頁面

基類Omi.Component實現

所有的組件都是繼承自Omi.Component。

import Omi from './omi.js';

class Component {
    constructor(data) {
        this.data = data || {};
        this.id = Omi.getInstanceId();
        this.HTML = null;
        this.renderTo = null;
    }

    _render() {
        this.HTML = this.render();
        this.renderTo.innerHTML = this.HTML;
    }
}

export default Component;
  • Omi使用完全面向對象的方式去開發組件,這里約定好帶有下划線的方法是用於內部實現調用,不建議Omi框架的使用者去調用。
  • 其中,_render為私有方法用於內部實現調用,會去調用組件的真正render方法用於生成HTML,並且把生成的HTML插入到renderTo容器里面。
  • 注意,這里目前沒有引入dom diff,不管第幾次渲染都是無腦設置innerHTML,復雜HTML結構對瀏覽器的開銷很大,這里后續會引入diff。

index.js整合

import Omi from './omi.js';
import Component from './component.js';

Omi.Component = Component;

window.Omi = Omi;
module.exports = Omi;

這里把Omi給直接暴露在window下,因為每個組件都生成了唯一的ID,后續實現事件作用域以及對象實例獲取都要通過window下的Omi獲取。

最后使用

實現完omi.js和component.js以及index.js之后,你就可以實現Hello Omi拉:

import Omi from 'index.js'; 
//或者使用webpack build之后的omi.js 
//import Omi from 'omi.js';

class Hello extends Omi.Component {
    constructor(data) {
        super(data);
    }
    render() {
        return  `
      <div>
      	<h1>Hello ,`+ this.data.name +`!</h1>
      </div>
  		`;

    }
}

Omi.render(new Hello({ name : 'Omi' }),"#container");

什么?都2017年了還在拼接字符串?!雖然ES6+的template string讓多行字符串拼接更加得心應手,但是template string+模板引擎可以讓更加優雅方便。既然用了template string,也可以寫成這樣子:

class Hello extends Omi.Component {
    constructor(data) {
        super(data);
    }
    render() {
        return  `
      <div>
        <h1>Hello ,${this.data.name}!</h1>
      </div>
        `;

    }
}

Omi.render(new Hello({ name : 'Omi' }),"#container");

引入mustachejs模板引擎

Omi支持任意模板引擎。可以看到,上面是通過拼接字符串的形式生成HTML,這里當然可以使用模板引擎。

修改一下index.js:

import Omi from './omi.js';
import Mustache from './mustache.js';
import Component from './component.js';

Omi.template = Mustache.render;
Omi.Component = Component;

window.Omi=Omi;
module.exports = Omi;

這里把Mustache.render掛載在Omi.template下。再修改一下component.js:

import Omi from './omi.js';

class Component {
    constructor(data) {
        this.data = data || {};
        this.id = Omi.getInstanceId();
        this.HTML = null;
    }

    _render() {
        this.HTML = Omi.template(this.render(), this.data);
        this.renderTo.innerHTML = this.HTML;
    }
}

export default Component;

Omi.template(即Mustache.render)需要接受兩個參數,第一個參數是模板,第二個參數是模板使用的數據。

現在,你便可以使用mustachejs模板引擎的語法了:

class Hello extends Omi.Component {
    constructor(data) {
        super(data);
    }
    render() {
        return  `
      <div>
      	<h1>Hello ,{{name}}!</h1>
      </div>
  		`;

    }
}

從上面的代碼可以看到,你完全可以重寫Omi.template方法去使用任意模板引擎。重寫Omi.template的話,建議使用omi.lite.js,因為omi.lite.js是不包含任何模板引擎的。那么怎么build出兩個版本的omi?且看webpack里設置的多入口:

 entry: {
    omi: './src/index.js',
    'omi.lite': './src/index.lite.js'
},
output: {
    path: 'dist/',
    library:'Omi',
    libraryTarget: 'umd',
    filename:  '[name].js'
},

index.lite.js的代碼如下:

import Omi from './omi.js';
import Component from './component.js';

Omi.template = function(tpl, data){
    return tpl;
}

Omi.Component = Component;

window.Omi=Omi;
module.exports = Omi;

可以看到Omi.template沒有對tpl做任何處理直接返回,開發者可以重寫該方法。

總結

到目前為止,已經實現了:

  • 第一個組件的渲染
  • 模板引擎的接入
  • 多入口打包omi.js和omi.lite.js

下片,將介紹《Omi原理-局部CSS》,歡迎關注...

招募計划


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM