BUI 模板渲染

2020-08-12 14:10 更新

案例

案例截圖

1. ES6模板

b-template 的值的字段在 templates 里面定義. 注意: 子集的內(nèi)容必須有標簽包住. 例如模板里面的li標簽.

數(shù)據(jù)支持數(shù)組

var bs = bui.store({
    scope: "page",
    data: {
      list: ["我是列表1","我是列表2"],
    },
    templates: {
      tplList: function (data) {
          let html = "";
          data.forEach(function (item,i) {
              html += `<li class="bui-btn">${item}</li>`;
          })
          return html;
      }
    }
})

html:

<ul b-template="page.tplList(page.list)" class="bui-list"></ul>

數(shù)據(jù)支持對象

var bs = bui.store({
    scope: "page",
    data: {
      obj: {
        title: "我的對象的標題",
        content: "<p>我是內(nèi)容,支持html</p><p>我是內(nèi)容,支持html</p>"
      }
    },
    templates: {
      tplObject: function (data) {
          let html = "";
          for( let key in data ){
              html += `<div class="bui-btn" >${data[key]}</div>`;
          }
          return html;
      }
    }
})

渲染模板,數(shù)據(jù)是對象時,默認不會動態(tài)聯(lián)動

html:

<div b-template="page.tplObject(page.obj)"></div>

如果對象需要動態(tài)聯(lián)動, 有2種方法:

方法1: obj 為數(shù)據(jù)源

// 改變數(shù)據(jù)
bs.obj.title = "我的對象的標題2";
// 告訴使用obj的模板,數(shù)據(jù)變更需要重新渲染
bs.trigger("obj",{value:bs.obj});

方法2: obj 為數(shù)據(jù)源

// 改變數(shù)據(jù)
bs.obj.title = "我的對象的標題2"
// 告訴使用obj的模板,數(shù)據(jù)變更需要重新渲染
bs.set("obj",bs.obj);

方法1 跟 方法2的區(qū)別在于, 方法1只是變更并重新觸發(fā)模板渲染, 方法2, 會對數(shù)據(jù)的所有鍵值重新賦值并觸發(fā)模板渲染.

拆分對象數(shù)據(jù),監(jiān)聽改變

html:

<div >
  <div b-text="page.obj.title"></div>
  <div b-html="page.obj.content"></div>
</div>

復雜對象

支持數(shù)據(jù)是一個對象, 那就可以更好的設計這個數(shù)據(jù)了, 但不建議把數(shù)據(jù)層級設計得太深.

var bs = bui.store({
    scope: "page",
    data: {
      objList: {
          title: "我是標題",
          data: ["我是復雜數(shù)據(jù)列表1"]
      }
    },
    templates: {
      tplObjectList: function (data,e) {
          var html = "";
          data.forEach(function (item,i) {
              html += `<li class="bui-btn">${item}</li>`;
          })
          return html;
      }
    }
})

<h2 b-text="page.objList.title"></h2>
<ul b-template="page.tplObjectList(page.objList.data)" class="bui-list"></ul>

如果 h2 是在 ul 里面, 那么默認第一次渲染數(shù)據(jù), h2 就會被替換, 這時可以通過 b-command 屬性,告訴模板第一次渲染采用什么方式. :) 當然這里ul標簽里面放h2標簽是不符合w3c標準的. 我們改成li標簽.

  • html 替換模板
  • append 在模板后面增加
  • prepend 在模板前面增加

<ul b-template="page.tplObjectList(page.objList.data)" b-command="append" class="bui-list">
  <li b-text="page.objList.title"></li>
</ul>

如果 ul 的子集不止有l(wèi)i標簽元素? b-children 就可以派上用場, 代表子集的重復元素是哪個選擇器?

  • 可以是標簽
  • 可以是類名

比方:

<ul b-template="page.tplObjectList(page.objList.data)" b-children=".bui-btn" class="bui-list">
</ul>

這個生成的模板可能是這樣的. 如果你使用 bui.array.set 修改數(shù)據(jù)的時候,變成新增, 這個時候你就要懷疑是不是需要設置 b-children.

<ul b-template="page.tplObjectList(page.objList.data)" b-children=".bui-btn" class="bui-list">
    <li class="section-title">我是二級標題</li>
    <li class="bui-btn">我是內(nèi)容0,索引0</li>
    <li class="section-title">我是二級標題</li>
    <li class="bui-btn">我是內(nèi)容1,索引1</li>
    <li class="section-title">我是二級標題</li>
    <li class="bui-btn">我是內(nèi)容2,索引2</li>
</ul>

2. 數(shù)據(jù)的增刪改

通過b-template的綁定, 我們可以通過操作數(shù)組,便能得到頁面的及時響應.

var bs = bui.store({
    scope: "page",
    data: {
      list: ["我是列表1","我是列表2"],
    },
    templates: {
      tplList: function (data) {
          let html = "";
          data.forEach(function (item,i) {
              html += `<li class="bui-btn">${item}</li>`;
          })
          return html;
      }
    }
})

html:

<ul b-template="page.tplList(page.list)" class="bui-list"></ul>

這樣綁定以后, 通過腳本操控 bs.list.push("我是列表3") , 頁面便能及時渲染新的數(shù)據(jù).

不過并非數(shù)組的所有操作都能得到及時響應, 目前我們可以監(jiān)聽到以下幾種方法:

  • push 在后面增加數(shù)據(jù)
  • unshift 在前面增加數(shù)據(jù)
  • shift 刪除第1條數(shù)據(jù)
  • pop 刪除最后一條數(shù)據(jù)
  • splice 刪除或者插入新的數(shù)據(jù), 具體可以查看數(shù)組的splice用法
  • sort 排序
  • reverse 反序
  • length 獲取長度

為了更方便的操作數(shù)據(jù)視圖, 我們還提供了幾個命令式的方法, 可以方便的對數(shù)組進行操作響應. 具體可以查看對應的 bui.array API 使用說明, 在綜合案例里面, 我們會頻繁的用到.

  • bui.array.empty 清空數(shù)組,并觸發(fā)第1個數(shù)組的視圖變更
  • bui.array.replace 替換數(shù)組,并觸發(fā)第1個數(shù)組的視圖變更
  • bui.array.merge 合并數(shù)組,并觸發(fā)第1個數(shù)組的視圖變更
  • bui.array.set 修改數(shù)組的某個值,支持對象
  • bui.array.delete 刪除數(shù)組的某個值,支持對象

值得注意的是, 如果數(shù)組里面是一個對象, 對象的某個字段變更是不會反饋到視圖的, 這種時候就可以使用 bui.array.set 來替換整條數(shù)據(jù), 達到刷新視圖的目的. 這個可以查看 綜合案例章節(jié)的多選聯(lián)動的 setStatus 方法, 會修改到數(shù)組對象的狀態(tài).

1.5.3 以后, 上面那些方法, 可以有更方便的使用方式, 比方:

1.5.4修正: 只有通過 bui.store 初始化劫持的數(shù)組,才會有 $方法操作

1.清空數(shù)組 [].$empty()



var bs = bui.store({
    data: {
        arr:["hello","bui","hi","easybui"]
    }
})
bui.array.empty( bs.arr );


// 1.5.4 版本以后可以這樣
bs.arr.$empty();

2.替換數(shù)組 [].$replace()

var bs = bui.store({
    data: {
        arr:["hello","bui","hi","easybui"]
    }
})
bui.array.replace( bs.arr, ["new","bui"]);


// 1.5.4 版本以后可以這樣
bs.arr.$replace(["new","bui"]);

3.合并數(shù)組 [].$merge()

var bs = bui.store({
    data: {
        arr:["hello","bui","hi","easybui"]
    }
})
bui.array.merge( bs.arr, ["new","bui"]);


// 1.5.4 版本以后可以這樣
bs.arr.$merge(["new","bui"],["easy"]);

4.修改數(shù)組 [].$set()

// 例子1: 修改第幾個
var bs = bui.store({
    data: {
        arr:["hello","bui","easybui"]
    }
})
bui.array.set( bs.arr, 1, "new hi");
// ["hello","new hi","easybui"]


// 1.5.4 版本以后可以這樣
bs.arr.$set(1, "new hi");
// arr 結果: ["hello","new hi","easybui"]

// 例子2: 修改值等于 bui 為新值 new bui
var bs = bui.store({
    data: {
        arr:["hello","bui","easybui"]
    }
})
bui.array.set( bs.arr, "bui", "new bui");
// ["hello","new bui","easybui"]


// 1.5.4 版本以后可以這樣
bs.arr.$set("bui", "new bui");
// arr 結果: ["hello","new bui","easybui"]

// 例子3: 修改對象值
var bs = bui.store({
    data: {
        arr:[{name:"hello"},{name:"hi"},{name:"easybui"}]
    }
})
bui.array.set( bs.arr, 1, {name:"new hi"} );
// [{name:"hello"},{name:"new hi"},{name:"easybui"}]


// 1.5.4 版本以后可以這樣
bs.arr.$set(1, {name:"new hi"});
// arr 結果: [{name:"hello"},{name:"new hi"},{name:"easybui"}]

// 例子4: 修改對象某個字段值, 需要傳多一個唯一值的字段名
var bs = bui.store({
    data: {
        arr:[{name:"hello"},{name:"hi"},{name:"easybui"}]
    }
})


// 1.5.4 版本以后可以這樣
// 單獨修改某個值
bs.arr.$set("hello", "hi bui", "name");
// 修改整個對象,不同的key值則會一起合并過去
bs.arr.$set("hi", {name:"new hi"}, "name");
// arr 結果: [{name:"hello"},{name:"new hi"},{name:"easybui"}]

5.刪除數(shù)據(jù)并觸發(fā)視圖更新

//例子1: 刪除值或索引:
var bs = bui.store({
    data: {
        arr:["hello","bui","hi","bui"]
    }
})
bui.array.delete(bs.arr , "bui" );


// 1.5.4 版本以后可以這樣
bs.arr.$delete("hi");
// arr 結果: ["hello","hi"]
// 例子2: 刪除值在哪個字段:
var bs = bui.store({
    data: {
        arr:[{ "id":1,value:"hello"},{ "id":2,value:"bui"}]
    }
})
bui.array.delete( bs.arr, "bui", "value" );


// 1.5.3 版本以后可以這樣
bs.arr.$delete("bui", "value");
// arr 結果: [{ "id":1,value:"hello"}]

3. 模板的交互

再來一個交互類的模板, 為了代碼更加清晰易懂,樣式類的屬性都去掉.

var bs = bui.store({
    scope: "page",
    data: {
        citysCheck: ["廣州","深圳"],
        citys: ["廣州","深圳","上海","北京"],
    },
    templates: {
        tplListCheck: function (data) {
            var html = "";
            data.forEach(function (item,i) {
                html += `<li class="bui-btn"><label><input type="checkbox" name="city" value="${item}" b-model="page.citysCheck">${item}</label></li>`;
            })
            return html;
        }
    }
})



當前選中: <b b-text="page.citysCheck"></b>
<ul id="cityList" b-template="page.tplListCheck(page.citys)"></ul>

這個模板用到 b-model 屬性, 這在一開始有數(shù)據(jù)的時候, 渲染是正確的, 當數(shù)據(jù)是異步增加進來以后, 這個數(shù)據(jù)并沒有選中狀態(tài). 那要如何處理呢?

模擬數(shù)據(jù)請求

var bs = bui.store({
    scope: "page",
    data: {
        citysCheck: [],
        citys: [],
    },
    templates: {
        tplListCheck: function (data) {
            let _self = this;
            let html = "";
            data.forEach(function (item,i) {
                // 通過比對,增加選中狀態(tài)
                let hasCheck = bui.array.compare(item,_self.citysCheck);
                let checked = hasCheck ? "checked" : "";


                html += `<li class="bui-btn"><label><input type="checkbox" name="city" value="${item}" b-model="page.citysCheck" ${checked}>${item}</label></li>`;
            })
            return html;
        }
    },
    mounted: function () {
        // 模擬數(shù)據(jù)動態(tài)改變
        setTimeout(()=>{
            // 方法1:
            this.citysCheck.push("廣州","深圳")
            this.citys.push("廣州","深圳","上海","北京");


            // 方法2:
            // bui.array.merge(this.citysCheck,["廣州","深圳"])
            // bui.array.merge(this.citys,["廣州","深圳","上海","北京"])


        },1000)
    }
})

這里其實還有一種辦法, 通過使用 this.oneTick 方法綁定 citys 的數(shù)據(jù)更新,并且視圖已經(jīng)渲染完成以后, 執(zhí)行多一次解析行為屬性. 這個compile要慎用, 多次調(diào)用會增加多個重復的回調(diào), 造成性能的損耗.

mounted: function () {
    // 模擬數(shù)據(jù)動態(tài)改變
    setTimeout(()=>{
        // 通過監(jiān)聽 citys 的數(shù)據(jù)變更并且視圖渲染完成以后, 增加數(shù)據(jù)的解析, 這樣就不用在模板里面做數(shù)據(jù)比對處理了.


        // 必須在數(shù)據(jù)更新之前
        this.oneTick("citys",function () {
           this.compile("#cityList")
        })
        // 數(shù)據(jù)更新
        this.citysCheck.push("廣州","深圳")
        this.citys.push("廣州","深圳","上海","北京");


    },1000)
}

4. 第三方模板

我們的頁面只有干凈的綁定, 其它都在模板的方法里面處理邏輯, 正常ES6模板其實已經(jīng)能夠很好的滿足我們的需求了, 不過如果你習慣用第三方模板的話, 你也可以使用, 這里以 artTemplate 為例, 需要在首頁引入這個模板的js文件.

var bs = bui.store({
    scope: "page",
    data: {
        list: ["我是列表1","我是列表2"],
    },
    templates: {
        artTplList: function (data,e) {


            var html = template("tpl-list",{ listData: data});


            return html;
        }
    }
})


<ul b-template="page.artTplList(page.list)" class="bui-list"></ul>
<script id="tpl-list" type="text/html">
  {{each listData item index}}
      <li class="bui-btn" href="pages/ui_controls/bui.store.html" >{{item}}</li>
  {{/each}}
</script>

效果預覽

查看效果

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號