前言
knockout學過的當工具指令碼用,就像jquery一樣使用,學習成本15分鐘,沒學過的可學可不學。
knockout 是上古神器,話說在遠古開天闢地,前端到處是飛禽走獸,一片混亂。
這時候人類開始人類開始誕生了,因為惡劣的環境備受煎熬,在生存角逐中,人們通過智慧寫了各種js指令碼,進入了石器時代,但是人類只有兩條腿和兩隻手切換工具的速度限制了人類的發展。
這時候John Resig 整理了各種工具,注入熔爐,一件草莽神器誕生了,jquery。人們開始利用jquery,在html上開墾大地,馬力十足,這是一個被jquery奴隸的時代,史稱奴隸時代。
後來人們就發現了一個問題,在html中這塊廣袤的大地上,js不同指令碼是衝突的,部落與聯盟之間的戰爭一觸即發。隨著因為衝突,除錯繁瑣,js的部落與部落之間在戰爭中,被require.js等模組管理所統治,不同的部落得到分封,進入了封建時代。
但是幾乎在同一時間,mvvm思想開始萌芽,他們提出有一個假設,如果可以修改資料就能對html產生驅動變化,那麼是不是可以解放生產力?這個實現不斷得到驗證與實際,工業革命誕生了。這是一次沒有流血的革命,因為以前的技術誕生往往充滿著爭議,這個是真的解放人類的雙手,蒸汽時代開始來臨。
knockout 就是蒸汽時代的產物,它是mvvm模式在js實現的前驅,是現在電力時代3大框架的基石。好了,故事模式結束。
正文
首先說明一下什麼是mvvm,它是一種模式,還有一些其他模式比如說mvc,mvp等等。
他們其實是一個重的問題,偏向於哪一塊。
mvc的c很重,那麼它的重點功能在於控制器,可以說是c連線了檢視和model。
mvp的p很重,他們的檢視和model完全分離,中間p的其實相當於c,操作層,但是和mvc不同的是隔離了model層和檢視。比如說window form開發。
mvvm,偏向view,和mvp完全相反,他的檢視和資料層相當緊密,兩者不可分割。knockout就是一個例子,包括現在比較成熟的框架vue。
knockout它的作用就是一個重要功能在於監聽,監聽資料的變化,然後從新部分渲染。
那麼開始實踐一下吧:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
一個model類,裡面存放這id,name,category,price,對應資料庫。
然後編輯控制器:
public class HomeController : Controller
{
static List<Product> productsList = new List<Product>();
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult products() {
productsList = new List<Product>() {
new Product{Id=1,Category="哈哈",Name="張三",Price=10 },
new Product{Id=2,Category="哈哈",Name="李小二",Price=10 }
};
return Json(productsList);
}
}
這裡面只是提供一些資料:
前臺:
html部分
<table id="products">
<thead>
<tr><th>ID</th><th>Name</th><th>Category</th><th>Price</th></tr>
</thead>
<tbody data-bind="foreach: products">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: category"></td>
<td data-bind="text: price"></td>
</tr>
</tbody>
</table>
js 部分:
function ViewModel() {
var self = this;
//建立繫結
self.products = ko.observableArray(); // 建立陣列繫結。
self.product = ko.observable();//單個產品
self.status = ko.observable();//單個錯誤提示
// 得到全部的產品
self.getAll = function () {
self.products.removeAll();
$.getJSON("/Home/products", function (products) {
self.products(products);
});
}
//更新
self.update = function () {
self.status("");
var id = $('#productId').val();
var product = {
Name: $('#name').val(),
Price: $('#price').val(),
Category: $('#category').val()
};
$.ajax({
url: '/Home/products/' + id,
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(product),
success: self.getAll
})
.fail(
function (xhr, textStatus, err) {
self.status(err);
});
}
//新增
self.create = function () {
self.status("");
var product = {
Name: $('#name2').val(),
Price: $('#price2').val(),
Category: $('#category2').val()
};
$.ajax({
url: '/Home/products',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(product),
statusCode: {
201 /*Created*/: function (data) {
//得到返回結果然後返回新增新增
self.products.push(data);
}
}
})
.fail(
function (xhr, textStatus, err) {
self.status(err);
});
}
//初始化
self.getAll();
}
$(function () {
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
})
在裡面配置增刪改查即可,裡面配置的方法可以在html這樣寫自動繫結:
<button data-bind="click: $root.create">新增</button>
就會觸發裡面的create 方法。
這裡只是作為一個繫結用例,其實在真正的編輯中是全部繫結的,不會出現這種$('#productName').val();
而是使用:
<input data-bind="value: $root.Name" type="text" title="Name" />
在此就不多複述。
效果:
總結
感覺 knockout 也不是完全過時,小型的開發速率還是非常快的,繫結就完事,原始碼也少,vs 編輯器也支援提示。