Omi教程-元件通訊攻略大全

當耐特發表於2017-02-17

元件通訊

Omi框架組建間的通訊非常遍歷靈活,因為有許多可選方案進行通訊:

  • 通過在元件上宣告 data-* 傳遞給子節點
  • 通過在元件上宣告 data 傳遞給子節點 (支援複雜資料型別的對映)
  • 父容器設定 childrenData 自動傳遞給子節點
  • 宣告 group-data 傳遞(支援複雜資料型別的對映)
  • 完全物件導向,可以非常容易地拿到物件的例項,之後可以設定例項屬性和呼叫例項的方法

所以通訊變得暢通無阻,下面一一來舉例說明。

data-*通訊

class Hello extends Omi.Component {
    constructor(data) {
      super(data);
    }
    style () {
      return  `
      h1{
        cursor:pointer;
      }
      `;
    }
    handleClick(target, evt){
      alert(target.innerHTML);
    }
    render() {
      return  `
      <div>
        <h1 onclick="handleClick(this, event)">Hello ,{{name}}!</h1>
      </div>
        `;

    }
}

Omi.makeHTML('Hello', Hello);

class App extends Omi.Component {
    constructor(data) {
        super(data);
    }
  
    render() {
        return  `
        <div>
            <Hello data-name="Omi" />
        </div>
        `;
    }
}

Omi.render(new App(),"#container");

一般data-用來傳遞值型別,如string、number。值得注意的是,通過data-接收到的資料型別都是string,需要自行轉成number型別。
通常情況下,data-能滿足我們的要求,但是遇到複雜的資料型別是沒有辦法通過大量data-去表達,所以可以通過data通訊,請往下看。

data通訊

如上面程式碼所示,通過 data-name="Omi"可以把name傳遞給子元件。下面的程式碼也可以達到同樣的效果。

...
class App extends Omi.Component {
    constructor(data) {
      super(data);
      this.helloData = { name : 'Omi' };
    }
  
    render() {
        return  `
        <div>
            <Hello data="helloData" />
        </div>
        `;
    }
}

Omi.render(new App(),"#container");

使用data宣告,會去元件的instance(也就是this)下找對應的屬性,this下可以掛載任意複雜的物件。所以這也就突破了data-*的侷限性。

如果instance下面的某個屬性下面的某個屬性下面的某個陣列的第一個元素的某個屬性要作為data傳遞Hello怎麼辦?
沒關係,data宣告是支援複雜型別的,使用方式如下:

...
class App extends Omi.Component {
    constructor(data) {
        super(data);
        this.complexData ={
            a:{
                b:{
                    c:[
                        {
                            e:[{
                                name:'ComplexData Support1'
                            },{
                                name:'ComplexData Support2'
                            }]
                        },
                        {
                            name: 'ComplexData Support3'
                        }
                    ]
                }
            }
        };
    }
  
    render() {
        return  `
        <div>
            <Hello data="complexData.a.b.c[1]" />
        </div>
        `;
    }
}
...

點選這裡→data對映覆雜資料

childrenData通訊

...
class App extends Omi.Component {
    constructor(data) {
      super(data);
      this.childrenData = [{ name : 'Omi' } , { name : 'dntzhang' }];
    }
  
    render() {
        return  `
        <div>
            <Hello  />
            <Hello  />
        </div>
        `;
    }
}

Omi.render(new App(),"#container");

通用this.childrenData傳遞data給子元件,childrenData是一個陣列型別,所以支援同時給多個元件傳遞data,與render裡面的元件會一一對應上。

group-data通訊

childrenData的方式可以批量傳遞資料給元件,但是有很多場景下data的來源不一定非要都從childrenData來,childrenData是個陣列,會和元件的順序一一對應,這就給不同傳遞方式的data必須全部集中的childrenData中,非常不方便。group-data專門為解決上面的痛點而生,專門是為了給一組元件批量傳遞data。

import Hello from './hello.js';


Omi.makeHTML('Hello', Hello);

class App extends Omi.Component {
    constructor(data) {
        super(data);
        this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];
    }

    render() {
        return  `
        <div>
            <Hello group-data="testData" />
            <Hello group-data="testData" />
            <Hello group-data="testData" />
        </div>
        `;

    }
}

Omi.render(new App(),"#container");

只需要在宣告的子元件上標記group-data,就會去當前元件的instance(也就是this)下面找對應的屬性,然後根據當前的位置,和對應陣列的位置會一一對應起來。

執行結果如下:
Omi教程-元件通訊攻略大全

點選這裡→group-data

同樣group-data支援複雜資料型別的對映,需要注意的是,group-data對映的終點必須是一個陣列:

import Hello from './hello.js';


Omi.makeHTML('Hello', Hello);

class App extends Omi.Component {
    constructor(data) {
        super(data);
        this.complexData ={
            a:{
                b:{
                    c:[
                        {
                            e:[{
                                name:'ComplexData Support1'
                            },{
                                name:'ComplexData Support2'
                            }]
                        },
                        {
                            name: 'ComplexData Support3'
                        }
                    ]
                }
            }
        };
    }

    render() {
        return  `
        <div>
            <Hello group-data="complexData.a.b.c[0].e" />
            <Hello group-data="complexData.a.b.c[0].e" />
        </div>
        `;

    }
}

Omi.render(new App(),"#container");

點選這裡→group-data對映覆雜資料

通過物件例項

...
class App extends Omi.Component {
    constructor(data) {
        super(data);
    }
    
    installed(){
        this.hello.data.name = "Omi";
        this.update()
    }
  
    render() {
        return  `
        <div>
            <Hello name="hello" />
        </div>
        `;
    }
}

Omi.render(new App(),"#container");

通過omi-id

...
class App extends Omi.Component {
    constructor(data) {
        super(data);
    }
    
    installed(){
        Omi.get("hello").data.name = "Omi";
        this.update()
    }
  
    render() {
        return  `
        <div>
            <Hello omi-id="hello" />
        </div>
        `;

    }
}

Omi.render(new App(),"#container");

通過在元件上宣告omi-id,在程式任何地方拿到該物件的例項。這個可以算是跨任意元件通訊神器。

特別強調

  • 通過childrenData或者data方式通訊都是一錘子買賣。後續變更只能通過元件例項下的data屬性去更新元件
  • 通過data-✼通訊也是一錘子買賣。後續變更只能通過元件例項下的data屬性去更新元件。
  • 關於data-✼通訊也可以不是一錘子買賣,但是要設定元件例項的dataFirst為false,這樣的話data-✼就會覆蓋元件例項的data對應的屬性

關於上面的第三條也就是這樣的邏輯虛擬碼:

if(this.dataFirst){
    this.data = Object.assign({},data-✼ ,this.data);
}else{
    this.data = Object.assign({},this.data, data-✼);
}

招募計劃

Omi教程-元件通訊攻略大全

相關文章