首頁  >  文章  >  web前端  >  BootstrapTable與KnockoutJS結合實作增刪改查功能【一】_javascript技巧

BootstrapTable與KnockoutJS結合實作增刪改查功能【一】_javascript技巧

PHP中文网
PHP中文网原創
2016-05-16 09:00:033959瀏覽

bootstrap是一個前端框架,解放web開發者的好東東,展現出的ui非常高端大氣上檔次,理論上可以不用寫一行css。只要在標籤中加上適當的屬性即可。

knockoutjs是一個javascript實作的mvvm框架。非常棒。例如列表資料項增減後,不需要重新刷新整個控制項片段或自己寫js增刪節點,只要預先定義模板和符合其語法定義的屬性即可。簡單的說,我們只需要關注數據的存取。

一、knockout.js簡介

1、knockout.js和mvvm

如今,各種前端框架應接不暇,令人眼花繚亂,有時不得不感嘆作為程序猿也真是苦逼,總有學不完的技術,何時是盡頭,除非你轉化!苦海無邊,回頭是不是岸,由你決定!

knockout.js是一個基於mvvm模式的輕量級的前端框架,有多輕?根據官網上方顯示的最新版本v3.4.0,僅22kb。能夠友善地處理資料模型和介面dom的綁定,最重要的是,它的綁定是雙向的,也就是說資料模型變化了,介面dom上的資料也會跟著變化,反過來,介面dom上的數據變化了,數據模型也會跟著這個變化。這樣能夠大幅減少我們的前端程式碼量,並且使得我們介面易於維護,再也不用寫一大堆事件監控資料模型和介面dom的變化了。下面部落客會根據一個使用實例來說明這兩點。

knockout.js官網:http://knockoutjs.com

knockout.js開源位址:https://github.com/knockout/knockout

mvvm模式:這是一種創建使用者介面的設計模式,mvvm把它拆分成三塊就是model、view、viewmodel,model就是資料模型,view就是我們的視圖,viewmodel就是一個視圖模型,用來綁定資料模型和視圖上面的dom元素。如果你使用過wpf和silverlight,理解這個應該不是啥問題;沒有使用過也什麼關係,看完此文,你會有一個大致的認識。

2.最簡單的實例

一般來說,如果你從零開始使用knockout.js,你至少需要做以下四部

2.1、去官網下載knockout.js文件,然後引用到view頁裡面。

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>

注意:knockout.js不需要jquery的支持,如果你的專案需要用到jquery的相關操作,則引用jquery;否則只引用以上文件即可。

2.2、定義viewmodel

viewmodel是什麼?其實,在js裡面,它看起來就像一個json物件。我們定義一個viewmodel:

var myviewmodel = {
name: "lilei",
profession: "软件工程师",
};

2.3、view視圖裡面定義綁定data-bind的標籤

<div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div>

注意:對應input標籤的文本,需要使用textinput,而一般標籤的文字使用text即可。

2.4、啟動綁定

做了以上三步,還需要啟動knockout的綁定

ko.applybindings(myviewmodel);

做到這四部,基本上實作了一個最簡單的viewmodel的資料綁定。

如果你夠細心,你會發現ko.applybindings()方法有兩個參數,第一個就是我們需要綁定的viewmodel,第二個又是什麼呢?由ko.applybindings(myviewmodel); 可知,第二個參數是一個可選參數,它表示viewmodel綁定的標籤的作用域,比如,我們將以上程式碼改一下:

<div> 
姓名:<label id="lb_name" data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div> 
ko.applybindings(myviewmodel,document.getelementbyid("lb_name"));

由此可知:第二個參數限定了myviewmodel的作用範圍,也就是說,只有在id="lb_name"的標籤上面綁定才會生效,如果第二個參數是div等容器標籤,它表示該綁定的範圍為該div下面的所有子標籤。

3、監控屬性

截止到上面的四步,我們看不到任何效果,看到的無非就是將一個json物件的資料綁定到了html標籤上面,這樣做有什麼意義呢?不是把簡單的問題複雜化嗎?別急,馬上見證奇蹟!上文說了,knockout最重要的意義在於雙向綁定,那麼如何實現我們的雙向綁定呢?答案就是監控屬性。

在knockout裡面,核心的有三個監控屬性:observables,dependentobservables,observablearray,observe的意思是觀察、觀測的意思,如果說成觀察屬性或觀測屬性感覺不太恰當,我們暫且叫監控屬性。

3.1、observables:監控屬性

我們將上面的範例改成這樣:
p>



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


<div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div>
//1.定义viewmodel var myviewmodel = { name: ko.observable("lilei"), profession: "软件工程师", }; //2.激活绑定 ko.applybindings(myviewmodel); $(function () { //注册文本框的textchange事件 $("#txt_testobservable").on("input", function () { myviewmodel.name($(this).val()); }); });

ko.observable("lilei") 這句話的意義是將viewmodel的name屬性加入成為監控屬性,一定name屬性變成監控屬性,神奇的事情就發生了,我們來看看當我們寫myviewmodel.的時候:

name由原來的屬性變成方法了,也就是說一旦加入了ko.observable(),那麼對應的屬性就會變成方法,那麼對於name的取值和賦值都需要使用myviewmodel.name()來處理。

程式碼釋疑:很顯然myviewmodel.name($(this).val()); 這句話將目前文字方塊的值賦給了name屬性,由於介面綁定了name屬性,所以label裡面的值也跟著改變了。或者你會說,這個使用textchange事件也可以做到的,只要將目前文字方塊的值賦給label標籤,也可以達到這個效果,這個不算什麼。確實,你的寫法也可以達到目的,但是我們的監控屬性的意義在於,任何地方改變了name的值,介面都會隨之變化,而不用每個地方去給label標籤賦值,js裡面只需要把關注點方法myviewmodel.name()上面即可。是不是很厲害~~

3.2、dependentobservables:監控依賴屬性

如果看了上面的監控屬性還沒過癮?下面再來看看監控依賴屬性的使用。

我們將程式碼再改下看看:



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


  姓名: 职业: 描述:
//1.定义viewmodel var myviewmodel = { name: ko.observable("lilei"), profession: ko.observable("软件工程师"), }; myviewmodel.des = ko.dependentobservable(function () { return "本人姓名——" + myviewmodel.name() + ",职业——" + myviewmodel.profession(); }); //2.激活绑定 ko.applybindings(myviewmodel);

程式碼釋疑:透過新增監控依賴屬性ko.dependentobservable() 將des屬性的值能同時監控到name和profession兩個的變化,其中任何一個發生變化,des綁定的標籤都會觸發改變,這樣做的最大好處就是避免了我們js去操作dom的麻煩,有點意思吧。

3.3、observablearray;監控陣列

除了上面兩種,ko也支援對陣列物件的監控。讓我們來看一個例子:



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


var deptarr = ko.observablearray([ { id: 1, name: '研发部' }, { id: 2, name: '行政部' }, { id: 3, name: '人事部' } ]); var viewmodel = { deptarr: deptarr, }; ko.applybindings(viewmodel); var i=4; $(function () { $("#btn_test").on("click", function () { deptarr.push({ id: i++, name: $("#txt_testobservable").val() }); }); });

程式碼釋疑:以上透過ko.observablearray()這個方法增加了對數組物件的監控,也就是說,js裡面任何地方只要對deptarr數組物件做了數組的改變,都會觸發ui給予對應。要注意的一點是,監控陣列其實是監控的陣列物件本身,對於陣列物件裡面的子物件屬性發生變化,是無法監控到的。例如我們將點擊事件改成這樣:

$(function () {
$("#btn_test").on("click", function () {
deptarr[1].name = "aaa";
});
});

由此說明數組監控實際上監控的是數組物件本身,對於數組裡面元素的屬性變化不會監控。如果確實需要對資料裡面物件的屬性變化進行監控,則需要再對資料裡面物件屬性使用ko.observable(),兩者合併使用。有興趣的可以試試。

4、ko裡面常見的data-bind屬性

上文中,我們使用了多個data-bind屬性,那麼在knockout裡面,到底有多少個這種data-bind的屬性呢。這裡我們列出一些常用的屬性。

4.1、text和inputtext

text,顧名思義就是文字的意思,這個綁定屬性一般用於

等標籤顯示文本,當然,如果你願意,任何標籤都可以使用這個綁定。它是使用基本上沒什麼好說的。如果沒有使用ko.observable(),則是靜態綁定,否則是動態綁定。

inputtext,input標籤的文本,相當於input標籤的value屬性。

  <div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div> 
     //1.定义viewmodel
var myviewmodel = {
name: ko.observable("lilei"),
profession: "软件工程师",
};
//2.激活绑定
ko.applybindings(myviewmodel);

4.2、value

這個綁定屬性一般用於input標籤,和上面的inputtext基本上相似。只不過value更加規範。

和value一起使用的還有一個參數valueupdate,它表示介面做一個什麼操作的時候更新該value。 valueupdate主要取值有change/keyup/keypress/afterkeydown等。分別表示文字變化、鍵盤縮起、鍵盤按下、鍵盤按下之後等操作時候更新value對應的viewmodel的值。

姓名:
<input type="text" data-bind="value:name,valueupdate:'keyup'" /><br /> 
    var myviewmodel = {
name: ko.observable("lilei"),
};//2.激活绑定
ko.applybindings(myviewmodel);

上述程式碼表示鍵盤收起的時候更新文字方塊的value屬性和myviewmodel的name屬性。

4.3、checked

checked綁定一般用於checkbox、radio等可以選取的表單元素,它對應的值是bool型別。和value的用法基本上相似,就不做重複說明。

4.4、enable

enable綁定一般用於是否啟用標籤元素,一般用於表單元素的啟用和禁用。和disabled相反,對應的值也是bool型別。

<div>
<input type="text" data-bind="enable:ismen"/>
</div>
<script type="text/javascript">
//1.定义viewmodel
var myviewmodel = {
name: ko.observable("lilei"),
profession: ko.observable("软件工程师"),
age: ko.observable(40),
ismen:ko.observable(true)
};
//2.激活绑定
ko.applybindings(myviewmodel);
myviewmodel.ismen(false);
</script>

由於ismen屬性變成了false,所有對應的文字方塊都會顯示停用狀態。

4.5、disabled

和enable相反,用法和enable類似。

4.6、options

上文中在使用select的綁定時候使用過options,它表示select標籤的option的集合,對應的值為一個數組,表示這個下拉框的資料來源。可以使用observablearray啟用對這個資料來源的監控。用法見上面。

4.7、html

text綁定其實就是標籤innertext的設定和值,那麼同理,html綁定也是innerhtml的設定和取值。它對應的值為一段html標籤。

4.8、css

css綁定是新增或刪除一個或多個樣式(class)到dom元素上。使用格式:

<style type="text/css">
.testbold {
background-color:powderblue;
}
</style> 
<div data-bind="css:{testbold:myviewmodel.name()=='lilei'}">aaaa</div> 
var myviewmodel = {
name: ko.observable("lilei"),
profession: ko.observable("软件工程师"),
age:ko.observable(40)
};

該div會顯示背景色。

如果需要增加或移除多個樣式,只要稍微改下即可,例如:

<div data-bind="css:{testbold:myviewmodel.name()=='lilei',testborder:myviewmodel.profession()=='php工程师'}">aaaa</div>

4.9、style

如果css綁定的作用是在標籤動態上加入或移除class樣式,那麼style綁定的作用就是想標籤動態新增或移除某一個樣式。例如:

<div data-bind="css:{background-color:myviewmodel.name()=='lilei'?'red':'white'}">aaaa</div>

如果是新增或移除多個,同css綁定的用法

4.10、attr

attr綁定主要用於在標籤上新增移除某一個或多個屬性(包括自訂屬性),永和和css類似。

4.11、click

click綁定表示在對應的dom元素上面新增點擊事件的執行方法。可以在任意元素上面使用。

<div>
<input type="button" value="测试click绑定" data-bind="click:clickfunc" />
</div> 
    var myviewmodel = {
clickfunc:function(){
alert($(event.currenttarget).val());
}
};
ko.applybindings(myviewmodel);

event.currenttarget表示目前點選的dom元素。有時為了簡便,我們直接使用匿名函數的方式綁定,例如:

<div>
<input type="button" value="测试click绑定" data-bind="click:function(){
alert('点击了');
}" />
</div>

但這種將js揉到html裡面的寫法讓博主難以接受,並且覺得維護起來相對不方便,尤其是點擊事件裡面的邏輯略複雜時。所以,如非必須,不建議直接寫這種匿名函數的方式。

4.12、其他

關於data-bind的所有綁定,可以看官網上面的介紹,這裡就不一一列舉了。需要用的時候去官網上查下來就好了。看看官網上面列舉的所有綁定

5、json物件和監控屬性的轉換及關係

我們知道,為了避免不同語言直接的展現方式,一般情況下我們前端和後端交互的時候統一使用json格式的數據,我們透過http請求從後端取到的資料模型,而要使用我們的ko的一些特性,必須將這些普通的資料模型轉換成ko的監控屬性;反過來,我們使用ko的監控屬性,有時需要把這些屬性轉換為普通的json資料傳到後台,那麼要如何實現這個轉換呢?

5.1、json物件轉換成viewmodel

例如我們從後台取到一個json對象,然後把它變成到我們的viewmodel,然後綁定到我們的介面dom。

$.ajax({
url: "/home/getdata",
type: "get",
data: {},
success: function (data, status) {
var ojson = data;
}
});

我們發送一個請求到後端,取到一個json對象,賦值到ojson,然後我們把ojson轉換成viewmodel,最直覺的方式就是手動轉換了。例如我們可以這樣:

    var myviewmodeljson = {
deptname: ko.observable(),
deptlevel: ko.observable(),
deptdesc:ko.observable()
};
ko.applybindings(myviewmodeljson);

然後在ajax請求的success裡面

success: function (data, status) {
var ojson = data;
myviewmodeljson.deptname(ojson.deptname);
myviewmodeljson.deptlevel(ojson.detplevel);
myviewmodeljson.deptdesc(ojson.deptdesc);
}

這樣,透過手動綁定,實現了json物件到viewmodel的綁定。這樣做的好處就是靈活,壞處顯而易見,手工程式碼量太大。

還好,有我們萬能的開源,總有人想到更好的辦法,我們使用knockout.mapping元件就能很好地幫助我們介面json物件到viewmodel的轉換。

knockout.mapping開源位址:下載

下面來簡單看看它如何使用,還是上面的例子,我們不用實作定義任何viewmodel,首先需要引用knockout.mapping.js

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>

注意:這裡knock.mapping-lastest.js必須放在knockout-3.4. 0.min.js的後面,否則呼叫不到ko.mapping。

然後直接在success函數裡面這樣使用

         success: function (data, status) {
var myviewmodeljson2 = ko.mapping.fromjs(data);
ko.applybindings(myviewmodeljson2);
}

程式碼釋疑:透過ajax請求從後台取到的json對象,透過ko.mapping.fromjs(),很方便地將其轉換成了viewmodel,是不是猴犀利!當然除了這種用法,還可以更新已經存在viewmodel,使用如下:

    var myviewmodeljson = {
deptname: ko.observable(),
deptlevel: ko.observable(),
deptdesc:ko.observable()
};
ko.applybindings(myviewmodeljson);
$(function () {
$.ajax({
url: "/home/getdata",
type: "get",
data: {},
success: function (data, status) {
ko.mapping.fromjs(data, myviewmodeljson)
}
});
});

在success裡面,依照data的值去更新myviewmodeljson這個viewmodel。

5.2、viewmodel轉換成json物件

上面說了json物件轉換為viewmodel,那麼反過來,如果我們需要將viewmodel轉換為json物件傳遞到後端,該怎麼辦呢?

knockout裡面提供了兩個方法:

•ko.tojs( ):將viewmodel轉換為json物件
•ko.tojson():將viewmodel轉換為序列化過的json string。

例如我們的程式碼如下: 

$(function () {
var ojson1 = ko.tojs(myviewmodeljson);
var ojson2 = ko.tojson(myviewmodeljson);
});
var myviewmodeljson = {
deptname: ko.observable("研发部"),
deptlevel: ko.observable("2"),
deptdesc: ko.observable("开发一伙人")
};
ko.applybindings(myviewmodeljson);

那麼我們來監控下ojson1和ojson2的值

程式碼釋疑:這裡要說明一點的是,這兩個方法是ko自帶的,並不需要mapping元件的支持。

6、建立自己的data-bind屬性

上面講了那麼多,都是介紹knockout裡面的一些綁定和監控,那麼,有些時候,我們需要自訂我們的data-bind,型如:

在knockout裡面,提供了ko.bindinghandlers屬性,用於自訂data-bind屬性,它的語法如下:

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

就這樣申明一下,然後在我們的html標籤裡面就可以使用自訂data-bind了。

<div> 
<select data-bind="myselect:$root">
<option id="1">研发部</option>
<option id="2">人事部</option>
<option id="3">行政部</option>
</select>
</div>

myselect就是我們自訂的綁定屬性,$root暫且可以理解為初始化(雖然這樣解釋並不嚴謹,如果有更合理的解釋歡迎指正)。

程式碼釋疑:透過上面的ko.bindinghandlers就能簡單實作自訂綁定屬性,需要說明兩點:

•init,顧名思義初始化自訂綁定定,它裡麵包含多個參數,一般使用較多的是前兩個參數,第一個參數表示初始化自訂綁定的dom元素,第二個參數一般用來傳遞初始化的參數。
•update,更新回調,當對應的監控屬性改變時,會進入這個方法。如果不需要回調,此方法可以不聲明。

在此部落客就結合原來分享過的一個下拉框組件mutiselect來簡單說明下自訂綁定的使用。

6.1、最簡單的mutiselect

一般情況下,如果我們需要使用ko去封裝一些通用元件,就需要用到我們的ko.bindinghandlers,下面部落客就結合mutiselect組件來說說如何使用。

先宣告自訂的ko.bindinghandlers,在init方法裡面初始化我們的select標籤

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
$(element).multiselect();
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

然後在頁面標籤裡面使用

<div style="text-align:center;"> 
<select data-bind="myselect:$root">
<option id="1">研发部</option>
<option id="2">人事部</option>
<option id="3">行政部</option>
</select>
</div>

最後第三部,啟動綁定

$(function () {
var multiselect = {};
ko.applybindings(multiselect);
});

如果不需要傳遞參數,這裡只需要綁定一個空的viewmodel即可。有人疑惑了,第三部感覺沒啥實際意義。部落客的理解是,dom元素需要使用data-bind去綁定數據,必須要啟用ko的綁定,也就是這裡的ko.applybindings()。

第一步還是自訂ko.bindinghandlers

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
var oparam = valueaccessor();
$(element).multiselect(oparam);
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

第二步和上方相同,在html標籤裡面使用這個自訂綁定。

第三步,在啟動綁定的時候傳入參數

$(function () {
var MultiSelect = {
enableClickableOptGroups: true,//收起分组
onChange: function (option, checked) {
alert("选择改变");
}
};
ko.applyBindings(MultiSelect);
});

透過這三步驟即可將參數傳到我們的mutiselect的初始化裡面:

程式碼釋疑:init事件的第二個參數,我們說了,它主要作用是取得我們viewmodel裡面傳過來的參數,只不過這裡要把它當做方法使用,為什麼會這麼用,還有待研究!

二、第一個增刪改查實例

至此基礎的東西終於是鋪墊完了,本來打算一篇搞定的,可以沒料到基礎的東西展開來這麼多篇幅!增刪改查的範例放到下篇bootstraptable與knockoutjs結合實作增刪改查功能【二】,歡迎學習交流,當然也歡迎推薦!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn