iT邦幫忙

DAY 19
5

ASP.NET Web技術小技巧分享系列 第 16

[Javascript]knockout.js - 資料處理-清單呈現方式

在第一篇有提到如果你的Web應用主要再處理一些CRUD,那很適合用knockout.js來實現MVVM架構,後續介紹了屬性、事件的控制,這篇就要來介紹在knoctout.js對於資料的顯示及處理。
foreach
foreach可以綁定一組Array資料,只要很簡潔的程式碼,就能輕鬆的完成多筆顯示的功能,
首先,我們定義一個使用者的class,包含他的序號、姓名

再來到ViewMode去繫結這個User的陣列資料,而給值的方式跟以往不一樣,observableArray()主要用來繫結陣列,如果你這個陣列資料有任何變動,如新增、刪除,他會自動同步到UI的顯示。

接著我們新增假資料,讓頁面載入就有三筆資料

HTML部分才是強大的地方!只要用以下指定方式即可!
Table 呈現方式:

清單呈現方式:

接著我們加入新增和移除的功能,程式很單純,可往下看完整程式碼應該很好懂,要特別注意的是,如果我們要針對某列做處理,可以用$parent這個參數來取得父元素,如下圖,在某列點選移除,取得該列的TR,則可針對這筆TR做處理:

除了$parent外,還有以下方式:

$parents – 抓取所有外部的元素 ex :

$parents[0] - 此元素的父類別,以此例來說即為 TR (等同於$parent)

$parents[1] - 此元素的父類別的父類別(好饒舌),以此例來說即為 tbody …以此類推

$root - 抓取最外層的元素,以此例來說即為 body ,(等同於$parents[$parents.length-1])

以下附上新增&刪除的完整程式碼:

<html xmlns="http://www.w3.org/1999/xhtml">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.7.2.min.js"></script>
    <script src="Scripts/knockout-2.1.0.debug.js"></script>


    <button data-bind="click: AddUser">Add</button>
    <button id="btn_json">Json</button>
    <fieldset>
        <legend>Table 呈現</legend>
        <table>
            <thead>
                <tr>
                    <th>Number</th>
                    <th>First name</th>
                    <th>Last name</th>
                    <th></th>
                </tr>
            </thead>
            <tbody data-bind="foreach: users">
                <tr>
                    <td data-bind="text: Index"></td>
                    <td data-bind="text: firstName"></td>
                    <td data-bind="text: lastName"></td>
                    <td>
                        <button data-bind="click: $parent.RemoveUser">移除</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </fieldset>
    <fieldset>
        <legend>清單呈現</legend>
        <ul data-bind="foreach: users">
            <li>
                <span data-bind="text: Index">:</span>
                <span data-bind="text: firstName"></span>
                <span data-bind="text: lastName"></span>
                <button data-bind="click: $parent.RemoveUser">移除</button>
            </li>
        </ul>
    </fieldset>
 
    <script type="text/javascript">
 
        //定義使用者
        var User = function (Index, firstName, lastName) {
            var self = this;
            self.Index = Index;
            self.firstName = firstName;
            self.lastName = lastName;
        }
 
        //ViewModel
        var viewModel = function () {
            var self = this;
            self.users = ko.observableArray();
            //新增使用者事件
            self.AddUser = function () {
                var index = self.users().length + 1;
                model.users.push(new User(index, "Kyle", "Shen" + index));
            }
            //移除使用者事件
            self.RemoveUser = function () {
                self.users.remove(this);
            }
        }
 
        //手動新增3筆假資料
        var model = new viewModel();
        for (var i = 1; i <= 3; i++) {
            model.users.push(new User(i, "Kyle", "Shen" + i));
        }
        ko.applyBindings(model);
 
    </script>

執行結果圖


上一篇
[Javascript]knockout.js - 事件處理
下一篇
[ASP.NET]用TryParseExact將特殊日期格式轉回DateTime
系列文
ASP.NET Web技術小技巧分享27
0
fillano
iT邦超人 1 級 ‧ 2013-10-04 10:17:04

讚喜歡 有一點不太了解,為什麼在User跟viewModel裡面,要先var self = this?

0
kyleshen
iT邦新手 3 級 ‧ 2013-10-04 12:39:51

fillano大 您好,
因在KO中,某些函數或function,this可能會代表其他涵義,為了避免混亂,故官方的Sample code可以看到都是按照此撰寫風格,針對這點,官方也有解釋:http://knockoutjs.com/documentation/computedObservables.html

您也可參考黑暗大的系列文(大推!!) http://blog.darkthread.net/post-2012-09-06-kolab1.aspx

謝謝您的回覆!

fillano iT邦超人 1 級‧ 2013-10-04 16:43:46 檢舉

是在knockout處理data-bind時,會改變什麼嗎?我想:

&lt;pre class="c" name="code">
        var User = function (Index, firstName, lastName) {
            var self = this;
            self.Index = Index;
            self.firstName = firstName;
            self.lastName = lastName;
        }

上面這一段code,this應該不會有問題才對。

但是:

&lt;pre class="c" name="code">
            self.AddUser = function () {
                var index = self.users().length + 1;
                model.users.push(new User(index, "Kyle", "Shen" + index));
            }
            //移除使用者事件
            self.RemoveUser = function () {
                self.users.remove(this);
            }

是否會因為事件bind到DOM上面,所以改變了this參考的物件,造成問題,所以knockout建議在開始的時候把this指派給一個變數,然後利用closure使用到這個變數,這樣才不會出問題?另外在做compute的時候,也會因為改變了read/write函數的context,所以不能直接在裡面使用this?

fillano iT邦超人 1 級‧ 2013-10-04 18:00:12 檢舉

利用var self=this;這樣的pattern來避開who is this的問題我沒有太多的問題。

另外,測試了一下,如果瀏覽器的Javascript支援ECMA-5標準,那可以這樣做:

&lt;pre class="c" name="code">
        var viewModel = function () {
            var self = this;
            this.users = ko.observableArray();
            //新增使用者事件
            this.AddUser = function () {
                var index = this.users().length + 1;
                model.users.push(new User(index, "Kyle", "Shen" + index));
            }.bind(this);
            //移除使用者事件
            this.RemoveUser = function () {
                self.users.remove(this);
            };
        }

這樣是不把this改成self的極限,但是在RemoveUser裡面不能這樣用,看起來這裡的this是需要參考到DOM物件,才有辦法把它從畫面上刪除。

這只是實驗就是了,實務上怎麼寫比較不會出錯,還是用他的best practice比較好。

我要留言

立即登入留言