BUI 模板渲染

2020-08-12 14:10 更新

案例

案例截圖

1. ES6模板

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

數(shù)據(jù)支持?jǐn)?shù)組

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. list: ["我是列表1","我是列表2"],
  5. },
  6. templates: {
  7. tplList: function (data) {
  8. let html = "";
  9. data.forEach(function (item,i) {
  10. html += `<li class="bui-btn">${item}</li>`;
  11. })
  12. return html;
  13. }
  14. }
  15. })

html:

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

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

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. obj: {
  5. title: "我的對(duì)象的標(biāo)題",
  6. content: "<p>我是內(nèi)容,支持html</p><p>我是內(nèi)容,支持html</p>"
  7. }
  8. },
  9. templates: {
  10. tplObject: function (data) {
  11. let html = "";
  12. for( let key in data ){
  13. html += `<div class="bui-btn" >${data[key]}</div>`;
  14. }
  15. return html;
  16. }
  17. }
  18. })

渲染模板,數(shù)據(jù)是對(duì)象時(shí),默認(rèn)不會(huì)動(dòng)態(tài)聯(lián)動(dòng)

html:

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

如果對(duì)象需要?jiǎng)討B(tài)聯(lián)動(dòng), 有2種方法:

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

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

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

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

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

拆分對(duì)象數(shù)據(jù),監(jiān)聽(tīng)改變

html:

  1. <div >
  2. <div b-text="page.obj.title"></div>
  3. <div b-html="page.obj.content"></div>
  4. </div>

復(fù)雜對(duì)象

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

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. objList: {
  5. title: "我是標(biāo)題",
  6. data: ["我是復(fù)雜數(shù)據(jù)列表1"]
  7. }
  8. },
  9. templates: {
  10. tplObjectList: function (data,e) {
  11. var html = "";
  12. data.forEach(function (item,i) {
  13. html += `<li class="bui-btn">${item}</li>`;
  14. })
  15. return html;
  16. }
  17. }
  18. })
  1. <h2 b-text="page.objList.title"></h2>
  2. <ul b-template="page.tplObjectList(page.objList.data)" class="bui-list"></ul>

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

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

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

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

  • 可以是標(biāo)簽
  • 可以是類名

比方:

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

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

  1. <ul b-template="page.tplObjectList(page.objList.data)" b-children=".bui-btn" class="bui-list">
  2. <li class="section-title">我是二級(jí)標(biāo)題</li>
  3. <li class="bui-btn">我是內(nèi)容0,索引0</li>
  4. <li class="section-title">我是二級(jí)標(biāo)題</li>
  5. <li class="bui-btn">我是內(nèi)容1,索引1</li>
  6. <li class="section-title">我是二級(jí)標(biāo)題</li>
  7. <li class="bui-btn">我是內(nèi)容2,索引2</li>
  8. </ul>

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

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

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. list: ["我是列表1","我是列表2"],
  5. },
  6. templates: {
  7. tplList: function (data) {
  8. let html = "";
  9. data.forEach(function (item,i) {
  10. html += `<li class="bui-btn">${item}</li>`;
  11. })
  12. return html;
  13. }
  14. }
  15. })

html:

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

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

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

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

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

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

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

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

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

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

  1. var bs = bui.store({
  2. data: {
  3. arr:["hello","bui","hi","easybui"]
  4. }
  5. })
  6. bui.array.empty( bs.arr );
  7. // 1.5.4 版本以后可以這樣
  8. bs.arr.$empty();

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

  1. var bs = bui.store({
  2. data: {
  3. arr:["hello","bui","hi","easybui"]
  4. }
  5. })
  6. bui.array.replace( bs.arr, ["new","bui"]);
  7. // 1.5.4 版本以后可以這樣
  8. bs.arr.$replace(["new","bui"]);

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

  1. var bs = bui.store({
  2. data: {
  3. arr:["hello","bui","hi","easybui"]
  4. }
  5. })
  6. bui.array.merge( bs.arr, ["new","bui"]);
  7. // 1.5.4 版本以后可以這樣
  8. bs.arr.$merge(["new","bui"],["easy"]);

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

  1. // 例子1: 修改第幾個(gè)
  2. var bs = bui.store({
  3. data: {
  4. arr:["hello","bui","easybui"]
  5. }
  6. })
  7. bui.array.set( bs.arr, 1, "new hi");
  8. // ["hello","new hi","easybui"]
  9. // 1.5.4 版本以后可以這樣
  10. bs.arr.$set(1, "new hi");
  11. // arr 結(jié)果: ["hello","new hi","easybui"]
  1. // 例子2: 修改值等于 bui 為新值 new bui
  2. var bs = bui.store({
  3. data: {
  4. arr:["hello","bui","easybui"]
  5. }
  6. })
  7. bui.array.set( bs.arr, "bui", "new bui");
  8. // ["hello","new bui","easybui"]
  9. // 1.5.4 版本以后可以這樣
  10. bs.arr.$set("bui", "new bui");
  11. // arr 結(jié)果: ["hello","new bui","easybui"]
  1. // 例子3: 修改對(duì)象值
  2. var bs = bui.store({
  3. data: {
  4. arr:[{name:"hello"},{name:"hi"},{name:"easybui"}]
  5. }
  6. })
  7. bui.array.set( bs.arr, 1, {name:"new hi"} );
  8. // [{name:"hello"},{name:"new hi"},{name:"easybui"}]
  9. // 1.5.4 版本以后可以這樣
  10. bs.arr.$set(1, {name:"new hi"});
  11. // arr 結(jié)果: [{name:"hello"},{name:"new hi"},{name:"easybui"}]
  1. // 例子4: 修改對(duì)象某個(gè)字段值, 需要傳多一個(gè)唯一值的字段名
  2. var bs = bui.store({
  3. data: {
  4. arr:[{name:"hello"},{name:"hi"},{name:"easybui"}]
  5. }
  6. })
  7. // 1.5.4 版本以后可以這樣
  8. // 單獨(dú)修改某個(gè)值
  9. bs.arr.$set("hello", "hi bui", "name");
  10. // 修改整個(gè)對(duì)象,不同的key值則會(huì)一起合并過(guò)去
  11. bs.arr.$set("hi", {name:"new hi"}, "name");
  12. // arr 結(jié)果: [{name:"hello"},{name:"new hi"},{name:"easybui"}]

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

  1. //例子1: 刪除值或索引:
  2. var bs = bui.store({
  3. data: {
  4. arr:["hello","bui","hi","bui"]
  5. }
  6. })
  7. bui.array.delete(bs.arr , "bui" );
  8. // 1.5.4 版本以后可以這樣
  9. bs.arr.$delete("hi");
  10. // arr 結(jié)果: ["hello","hi"]
  1. // 例子2: 刪除值在哪個(gè)字段:
  2. var bs = bui.store({
  3. data: {
  4. arr:[{ "id":1,value:"hello"},{ "id":2,value:"bui"}]
  5. }
  6. })
  7. bui.array.delete( bs.arr, "bui", "value" );
  8. // 1.5.3 版本以后可以這樣
  9. bs.arr.$delete("bui", "value");
  10. // arr 結(jié)果: [{ "id":1,value:"hello"}]

3. 模板的交互

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

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. citysCheck: ["廣州","深圳"],
  5. citys: ["廣州","深圳","上海","北京"],
  6. },
  7. templates: {
  8. tplListCheck: function (data) {
  9. var html = "";
  10. data.forEach(function (item,i) {
  11. html += `<li class="bui-btn"><label><input type="checkbox" name="city" value="${item}" b-model="page.citysCheck">${item}</label></li>`;
  12. })
  13. return html;
  14. }
  15. }
  16. })

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

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

模擬數(shù)據(jù)請(qǐng)求

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. citysCheck: [],
  5. citys: [],
  6. },
  7. templates: {
  8. tplListCheck: function (data) {
  9. let _self = this;
  10. let html = "";
  11. data.forEach(function (item,i) {
  12. // 通過(guò)比對(duì),增加選中狀態(tài)
  13. let hasCheck = bui.array.compare(item,_self.citysCheck);
  14. let checked = hasCheck ? "checked" : "";
  15. html += `<li class="bui-btn"><label><input type="checkbox" name="city" value="${item}" b-model="page.citysCheck" ${checked}>${item}</label></li>`;
  16. })
  17. return html;
  18. }
  19. },
  20. mounted: function () {
  21. // 模擬數(shù)據(jù)動(dòng)態(tài)改變
  22. setTimeout(()=>{
  23. // 方法1:
  24. this.citysCheck.push("廣州","深圳")
  25. this.citys.push("廣州","深圳","上海","北京");
  26. // 方法2:
  27. // bui.array.merge(this.citysCheck,["廣州","深圳"])
  28. // bui.array.merge(this.citys,["廣州","深圳","上海","北京"])
  29. },1000)
  30. }
  31. })

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

  1. mounted: function () {
  2. // 模擬數(shù)據(jù)動(dòng)態(tài)改變
  3. setTimeout(()=>{
  4. // 通過(guò)監(jiān)聽(tīng) citys 的數(shù)據(jù)變更并且視圖渲染完成以后, 增加數(shù)據(jù)的解析, 這樣就不用在模板里面做數(shù)據(jù)比對(duì)處理了.
  5. // 必須在數(shù)據(jù)更新之前
  6. this.oneTick("citys",function () {
  7. this.compile("#cityList")
  8. })
  9. // 數(shù)據(jù)更新
  10. this.citysCheck.push("廣州","深圳")
  11. this.citys.push("廣州","深圳","上海","北京");
  12. },1000)
  13. }

4. 第三方模板

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

  1. var bs = bui.store({
  2. scope: "page",
  3. data: {
  4. list: ["我是列表1","我是列表2"],
  5. },
  6. templates: {
  7. artTplList: function (data,e) {
  8. var html = template("tpl-list",{ listData: data});
  9. return html;
  10. }
  11. }
  12. })
  1. <ul b-template="page.artTplList(page.list)" class="bui-list"></ul>
  2. <script id="tpl-list" type="text/html">
  3. {{each listData item index}}
  4. <li class="bui-btn" href="pages/ui_controls/bui.store.html" >{{item}}</li>
  5. {{/each}}
  6. </script>

效果預(yù)覽

查看效果

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)