BootstrapTable與KnockoutJS相結合實現增刪改查功能【二】,bootstrapknockoutjs

來源:互聯網
上載者:User

BootstrapTable與KnockoutJS相結合實現增刪改查功能【二】,bootstrapknockoutjs

在上篇文章給大家介紹了BootstrapTable與KnockoutJS相結合實現增刪改查功能【一】,介紹了下knockout.js的一些基礎用法。接下來通過本文繼續給大家介紹。如果你也打算用ko去做項目,且看看吧!

Bootstrap是一個前端架構,解放Web開發人員的好東東,展現出的UI非常高端大氣上檔次,理論上可以不用寫一行css。只要在標籤中加上合適的屬性即可。

KnockoutJS是一個JavaScript實現的MVVM架構。非常棒。比如列表資料項目增減後,不需要重新重新整理整個控制項片段或自己寫JS增刪節點,只要預先定義模板和符合其文法定義的屬性即可。簡單的說,我們只需要關注資料的存取。

一、效果預覽

其實也沒啥效果,就是簡單的增刪改查,重點還是在代碼上面,使用ko能夠大量節省介面DOM資料繫結的操作。下面是整個整個增刪改查邏輯的js代碼:


頁面效果:

二、程式碼範例

好了,進入重點吧!博主打算分兩塊介紹,第一部分是表格初始化部分,第二部分是按鈕操作增刪改部分。

1、表格初始化

1.1、準備工作

首先看看需要引用的js和css檔案

<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" /><link href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" /><script src="~/scripts/jquery-1.9.1.min.js"></script><script src="~/Content/bootstrap/js/bootstrap.min.js"></script><script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script><script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script><script src="~/scripts/knockout/knockout-3.4.0.min.js"></script><script src="~/scripts/knockout/extensions/knockout.mapping-latest.js"></script><script src="~/Content/bootstrap-table/knockout.bootstraptable.js"></script><script src="~/scripts/Department.js"></script> 

都是一些常用的css和js檔案,我們自訂的js檔案主要有兩個: knockout.bootstraptable.js 和 Department.js 。上篇我們介紹過使用ko可以自訂我們的data-bind。同樣,這裡對於table的綁定,我們也定義一個自訂的綁定,代碼 knockout.bootstraptable.js 裡面。

//添加ko自訂綁定ko.bindingHandlers.myBootstrapTable = {init: function (element, valueAccessor, allBindingsAccessor, viewModel) {//這裡的oParam就是綁定的viewmodelvar oViewModel = valueAccessor();var $ele = $(element).bootstrapTable(oViewModel.params);//給viewmodel添加bootstrapTable方法oViewModel.bootstrapTable = function () {return $ele.bootstrapTable.apply($ele, arguments);}},update: function (element, valueAccessor, allBindingsAccessor, viewModel) {}};//初始化(function ($) {//向ko裡面新增一個bootstrapTableViewModel方法ko.bootstrapTableViewModel = function (options) {var that = this;this.default = {search: true, //是否顯示表格搜尋,此搜尋是用戶端搜尋,不會進服務端,所以,個人感覺意義不大strictSearch: true,showColumns: true, //是否顯示所有的列cache:false,showRefresh: true, //是否顯示重新整理按鈕minimumCountColumns: 2, //最少允許的列數clickToSelect: true, //是否啟用點擊選中行showToggle: true,};this.params = $.extend({}, this.default, options || {});//得到選中的記錄this.getSelections = function () {var arrRes = that.bootstrapTable("getSelections")return arrRes;};//重新整理this.refresh = function () {that.bootstrapTable("refresh");};};})(jQuery); 

代碼釋疑:這個js檔案主要做了兩件事

1.自訂data-bind屬性myBootstrapTable。對於ko.bindingHandlers.myBootstrapTable裡面的update方法,如非必須,可以不用定義。

2.通過向ko對象裡面添加bootstrapTableViewModel來封裝bootstrapTable。

1.2、html標籤啟動綁定

<table id="tb_dept" data-bind="myBootstrapTable:$root"><thead><tr><th data-checkbox="true"></th><th data-field="Name">部門名稱</th><th data-field="Level">部門層級</th><th data-field="Des">描述</th><th data-field="strCreatetime">建立時間</th></tr></thead></table> 

代碼釋疑:定義一個table標籤,使用自訂綁定myBootstrapTable,上篇說過,$root可以理解為初始化的意思。為了簡單,所有的colums就直接在<th>裡面寫了。

1.3、啟用ko的綁定

在頁面載入完成之後,啟動ko的綁定:

//初始化$(function () {//1、初始化表格tableInit.Init();//2、註冊增刪改事件operate.operateInit();});//初始化表格var tableInit = {Init: function () {//綁定table的viewmodelthis.myViewModel = new ko.bootstrapTableViewModel({url: '/Department/GetDepartment', //請求背景URL(*)method: 'get', //請求方式(*)toolbar: '#toolbar', //工具按鈕用哪個容器queryParams: function (param) {return { limit: param.limit, offset: param.offset };},//傳遞參數(*)pagination: true, //是否顯示分頁(*)sidePagination: "server", //分頁方式:client用戶端分頁,server服務端分頁(*)pageNumber: 1, //初始化載入第一頁,預設第一頁pageSize: 10, //每頁的記錄行數(*)pageList: [10, 25, 50, 100], //可供選擇的每頁的行數(*)});ko.applyBindings(this.myViewModel, document.getElementById("tb_dept"));}}; 

代碼釋疑:頁面載入完成之後,調用上面封裝的bootstrapTableViewModel對象合并傳遞的參數,最後啟用綁定,將this.myViewModel作為綁定的viewmodel啟用。調試代碼可知,當執行到 ko.applyBindings(this.myViewModel, document.getElementById("tb_dept")); 這一句的時候,自訂綁定才會生效,程式才會進入到 ko.bindingHandlers.myBootstrapTable 對象的init方法去初始化bootstrapTable。這裡需要說明一點:

init: function (element, valueAccessor, allBindingsAccessor, viewModel) {//這裡的oParam就是綁定的viewmodelvar oViewModel = valueAccessor();var $ele = $(element).bootstrapTable(oViewModel.params);//給viewmodel添加bootstrapTable方法oViewModel.bootstrapTable = function () {return $ele.bootstrapTable.apply($ele, arguments);}}

上文中的init方法,通過第二個參數valueAccessor,我們得到的是當前綁定的viewmodel,也就是我們上面的this.myViewModel這個對象,博主覺得這一點有利於你理解自訂綁定的邏輯。基本上執行到 var $ele = $(element).bootstrapTable(oViewModel.params); 這一句的時候,我們表格的初始化就完成了。後台對應的方法博主隨便定義了一個集合,為了完整,這裡還是貼出來:

DepartmentController

2、按鈕操作

上面通過bootstrapTable的初始化完成了我們的自訂data-bind的使用。下面的按鈕操作我們來體驗一把使用監控屬性的“爽歪歪”。

2.1、view頁面

首先在view頁面上面定義我們的增刪改按鈕

<div id="toolbar" class="btn-group"><button id="btn_add" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增</button><button id="btn_edit" type="button" class="btn btn-default"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>修改</button><button id="btn_delete" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除</button></div> 

為了簡便,博主使用了一個隱藏的彈出框用來包含新增和編輯的文字框。當然,一般情況下,可能這裡用的是部分視圖,你的項目裡面可能會有一個Edit.cshtml,但這裡博主將這些都放在一個頁面上面,因為這不是文本的重點。

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title" id="myModalLabel">操作</h4></div><div class="modal-body"><div class="form-group"><label for="txt_departmentname">部門名稱</label><input type="text" name="txt_departmentname" data-bind="value:Name" class="form-control" id="txt_departmentname" placeholder="部門名稱"></div><div class="form-group"><label for="txt_departmentlevel">部門層級</label><input type="text" name="txt_departmentlevel" data-bind="value:Level" class="form-control" id="txt_departmentlevel" placeholder="部門層級"></div><div class="form-group"><label for="txt_des">描述</label><input type="text" name="txt_des" data-bind="value:Des" class="form-control" id="txt_des" placeholder="描述"></div></div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>關閉</button><button type="button" id="btn_submit" class="btn btn-primary" data-dismiss="modal"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>儲存</button></div></div></div></div> 

2.2、JS初始化按鈕操作

//操作var operate = {//初始化按鈕事件operateInit: function () {this.operateAdd();this.operateUpdate();this.operateDelete();this.DepartmentModel = {id: ko.observable(),Name: ko.observable(),Level: ko.observable(),Des: ko.observable(),CreateTime: ko.observable()};},//新增operateAdd: function(){$('#btn_add').on("click", function () {$("#myModal").modal().on("shown.bs.modal", function () {var oEmptyModel = {id: ko.observable(),Name: ko.observable(),Level: ko.observable(),Des: ko.observable(),CreateTime: ko.observable()};ko.utils.extend(operate.DepartmentModel, oEmptyModel);ko.applyBindings(operate.DepartmentModel, document.getElementById("myModal"));operate.operateSave();}).on('hidden.bs.modal', function () {ko.cleanNode(document.getElementById("myModal"));});});},//編輯operateUpdate: function () {$('#btn_edit').on("click", function () {$("#myModal").modal().on("shown.bs.modal", function () {var arrselectedData = tableInit.myViewModel.getSelections();if (!operate.operateCheck(arrselectedData)) { return; }//將選中該行資料有資料Model通過Mapping組件轉換為viewmodelko.utils.extend(operate.DepartmentModel, ko.mapping.fromJS(arrselectedData[0]));ko.applyBindings(operate.DepartmentModel, document.getElementById("myModal"));operate.operateSave();}).on('hidden.bs.modal', function () {//關閉彈出框的時候清除綁定(這個清空包括清空綁定和清空註冊事件)ko.cleanNode(document.getElementById("myModal"));});});},//刪除operateDelete: function () {$('#btn_delete').on("click", function () {var arrselectedData = tableInit.myViewModel.getSelections();$.ajax({url: "/Department/Delete",type: "post",contentType: 'application/json',data: JSON.stringify(arrselectedData),success: function (data, status) {alert(status);//tableInit.myViewModel.refresh();}});});},//儲存資料operateSave: function () {$('#btn_submit').on("click", function () {//取到當前的viewmodelvar oViewModel = operate.DepartmentModel;//將Viewmodel轉換為資料modelvar oDataModel = ko.toJS(oViewModel);var funcName = oDataModel.id?"Update":"Add";$.ajax({url: "/Department/"+funcName,type: "post",data: oDataModel,success: function (data, status) {alert(status);tableInit.myViewModel.refresh();}});});},//資料校正operateCheck:function(arr){if (arr.length <= 0) {alert("請至少選擇一行資料");return false;}if (arr.length > 1) {alert("只能編輯一行資料");return false;}return true;}} 

代碼釋疑:說說這裡的執行邏輯,首先在$(function(){})方法裡面調用 operate.operateInit(); 。在operateInit()方法裡面註冊頁面上面按鈕的點擊事件,同時也定義 this.DepartmentModel 作為我們新增編輯的viewmodel,這個viewmodel裡面定義了和頁面元素對應的監控屬性。還記得上面隱藏的彈出框裡面的一些data-bind嗎,沒錯,裡面對應的value值就是和這裡的監控屬性對應,這樣設定綁定之後,js裡面所有的導致 this.DepartmentModel 裡面監控的變化,都會觸發介面上面這些綁定標籤的value值變化,反之,介面上面的所有標籤的Value值的變化,也勢必會引起它的監控屬性值的變化,此之所謂雙向繫結。下面具體看看雙向繫結的執行。

2.3、新增操作

$('#btn_add').on("click", function () {$("#myModal").modal().on("shown.bs.modal", function () {var oEmptyModel = {id: ko.observable(),Name: ko.observable(),Level: ko.observable(),Des: ko.observable(),CreateTime: ko.observable()};ko.utils.extend(operate.DepartmentModel, oEmptyModel);ko.applyBindings(operate.DepartmentModel, document.getElementById("myModal"));operate.operateSave();}).on('hidden.bs.modal', function () {ko.cleanNode(document.getElementById("myModal"));});}); 

當我們介面觸發新增操作的時候,首先會彈出上面說的隱藏模態框。在模態框顯示的時候,首先定義一個空的viewmodel,然後調用 ko.utils.extend(operate.DepartmentModel, oEmptyModel); 這一句,將全域的operate.DepartmentModel被空的viewmodel覆蓋。ko.utils.extend()這個方法的作用和jquery裡面的$.extend()作用類似,都是根據後面對象合并前面對象,合并之後,使用新的viewmodel啟用綁定。啟用綁定之後,註冊儲存按鈕的click事件。這樣新增的時候,彈出模態框,由於viewmodel裡面的監控屬性都是空的,對應介面元素的value也會被清空,所以新增我們看到是這樣:

當彈出框關閉後,我們通過關閉的事件,執行 ko.cleanNode(document.getElementById("myModal")); 這一句,這個很重要,因為對於同一個dom,ko只能綁定一次,如果需要再次綁定,需要先清空綁定,並且cleanNode()這個方法,它不僅會清空綁定,還是會dom裡面註冊的事件也會清空,使用的時候需要注意下!

2.4、編輯操作

$('#btn_edit').on("click", function () {$("#myModal").modal().on("shown.bs.modal", function () {var arrselectedData = tableInit.myViewModel.getSelections();if (!operate.operateCheck(arrselectedData)) { return; }//將選中該行資料有資料Model通過Mapping組件轉換為viewmodelko.utils.extend(operate.DepartmentModel, ko.mapping.fromJS(arrselectedData[0]));ko.applyBindings(operate.DepartmentModel, document.getElementById("myModal"));operate.operateSave();}).on('hidden.bs.modal', function () {//關閉彈出框的時候清除綁定(這個清空包括清空綁定和清空註冊事件)ko.cleanNode(document.getElementById("myModal"));});}); 

當我們觸發編輯操作的時候,介面還是彈出框。在彈出框的彈出事件裡面,我們取到當前選中的行,然後校正是否選中了一行。最好通過 ko.mapping.fromJS(arrselectedData[0]) 這一句,將普通的Json對象轉換為帶有監控屬性的viewmodel,上篇說過,這個方法需要 knockout.mapping-latest.js 這個js檔案的支援。轉換之後,還是通過ko.utils.extend()方法更新viewmodel,然後啟用綁定。由於viewmodel被當前選中行的資料更新了,所以得到結果:

2.5、儲存操作

在新增和編輯彈出框之後,修改相關資訊後點擊儲存,就會觸發儲存事件。

$('#btn_submit').on("click", function () {//取到當前的viewmodelvar oViewModel = operate.DepartmentModel;//將Viewmodel轉換為資料modelvar oDataModel = ko.toJS(oViewModel);var funcName = oDataModel.id?"Update":"Add";$.ajax({url: "/Department/"+funcName,type: "post",data: oDataModel,success: function (data, status) {alert(status);tableInit.myViewModel.refresh();}});}); 

當觸發儲存事件的時候,我們首先取到頁面綁定的viewmodel,即operate.DepartmentModel,然後使用ko.toJS()方法將帶有監控屬性的viewmodel轉換為純資料的Json對象,這個方法是ko內建的,不需要其他js支援。得到json對象之後,發送ajax請求,去新增或者編輯資料。這樣就很好地體現了雙向繫結,介面上面所有文字框的value發生了變化之後,也會觸發operate.DepartmentModel的變化。

2.6、刪除操作

刪除操作沒什麼好說的,和ko關係不大。

三、總結

以上通過一個簡單的增刪改查操作,介紹了下ko和bootstrapTable的聯合使用。ko可以讓你從DOM中解放出來,把關注點放在viewmodel上面。縱觀整個js代碼,幾乎看不到jquery的val()、text()等對介面dom做取值和賦值的操作,是不是看著乾淨清爽,並且高大上了呢~~當然,這或許只是ko的一些比較基礎的用法,畢竟博主學習ko才3天,更多進階用法還有待摸索,等過段時間用熟了,再將它的一些進階用法分享給大家。如果你覺得本文能夠協助你理解ko的原理以及它的一些用法,不妨推薦下,小編在此感激不盡!

以上所述是小編給大家介紹的BootstrapTable與KnockoutJS相結合實現增刪改查功能【二】的全部內容,希望對大家有所協助!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.