MVVM架构~knockoutjs实现简单的购物车
概念相关
购物车相信大家都用过,很方便,可以将多个商品添加到购物车,并且可以修改购买商品的数据,当然为了用户体验好,在修改数据时,你的价格也会出现变化的,这使用JS可以实现,但我认为,代码量挺大的,而使用knockoutjs可以大大减少代码量,而且更重要的是,当前台页面有所调整时,这个JS只需要简单调整,而不需要改后台代码!
代码相关
下面看一下实现简单购物车的代码
1 View部分
<table>
<thead>
<tr>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach:lines">
<tr>
<td data-bind="with:product">
<span data-bind="text:name"></span></td>
<td data-bind="with:product"><span data-bind='text:formatCurrency(price)' /></td>
<td>
<input data-bind='visible: product, value: productCount, valueUpdate: "afterkeydown"' />
</td>
<td><span data-bind="visible:product,text:formatCurrency(subtotal())"></span></td>
<td><a href='#' data-bind='click: $parent.removeLine'>Remove</a></td>
</tr>
</tbody>
</table>
<p class='grandTotal'>
Total value: <span data-bind='text: grandTotal()'></span>
</p>
<button data-bind='click: addLine'>Add product</button>
2 JS部分
<script type="text/ecmascript">
function formatCurrency(value) {
return "¥" + value;
}
var Product = function (id, name, price) {
self = this;
self.id = id;
self.name = name;
self.price = price;
}
var CartItem = function (product) {
self = this; self.product = ko.observable(product);
self.productCount = ko.observable(1); self.subtotal = ko.dependentObservable(function () {
return this.product() ? this.product().price * parseInt("0" + this.productCount(), 10) : 0;
}.bind(self));
};
var CartList = function () {
var self = this;
self.lines = ko.observableArray([new CartItem(new Product(1, "test1", 100))]); self.addLine = function () { self.lines.push(new CartItem(new Product(2, "test2", 200))) }; self.removeLine = function (line) { self.lines.remove(line) }; self.grandTotal = ko.computed(function () {
var total = 0;
$.each(self.lines(), function () { total += this.subtotal(); })
return total;
});
};
ko.applyBindings(new CartList()); </script>
3 有图有真相
aaarticlea/png;base64,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" alt="" />
完成代码如下
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="knockout-2.1.0.js" type="text/javascript"></script> </head>
<body>
<table>
<thead>
<tr>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach:lines">
<tr>
<td data-bind="with:product">
<span data-bind="text:name"></span></td>
<td data-bind="with:product"><span data-bind='text:formatCurrency(price)' /></td>
<td>
<input data-bind='visible: product, value: productCount, valueUpdate: "afterkeydown"' />
</td>
<td><span data-bind="visible:product,text:formatCurrency(subtotal())"></span></td>
<td><a href='#' data-bind='click: $parent.removeLine'>Remove</a></td>
</tr>
</tbody>
</table>
<p class='grandTotal'>
Total value: <span data-bind='text: grandTotal()'></span>
</p>
<button data-bind='click: addLine'>Add product</button>
<script type="text/ecmascript">
function formatCurrency(value) {
return "¥" + value;
}
var Product = function (id, name, price) {
self = this;
self.id = id;
self.name = name;
self.price = price;
}
var CartItem = function (product) {
self = this; self.product = ko.observable(product);
self.productCount = ko.observable(1); self.subtotal = ko.dependentObservable(function () {
return this.product() ? this.product().price * parseInt("0" + this.productCount(), 10) : 0;
}.bind(self));
};
var CartList = function () {
var self = this;
self.lines = ko.observableArray([new CartItem(new Product(1, "test1", 100))]); self.addLine = function () { self.lines.push(new CartItem(new Product(2, "test2", 200))) }; self.removeLine = function (line) { self.lines.remove(line) }; self.grandTotal = ko.computed(function () {
var total = 0;
$.each(self.lines(), function () { total += this.subtotal(); })
return total;
});
};
ko.applyBindings(new CartList()); </script>
</body>
</html>
感谢您的阅读!
MVVM架构~knockoutjs实现简单的购物车的更多相关文章
- MVVM架构~knockoutjs系列之表单添加(验证)与列表操作源码开放
返回目录 本文章应该是knockoutjs系列的最后一篇了,前几篇中主要讲一些基础知识,这一讲主要是一个实际的例子,对于一个对象的添加与编辑功能的实现,并将项目源代码公开了,共大家一起学习! knoc ...
- MVVM架构~Knockoutjs系列之验证机制的引入
返回目录 对于Knockoutjs本身来说,没有提供验证模块,不过,有第三方的扩展,就像你为jquery库作extensions一样,这讲中我将介绍一个Knockout插件扩展,knockout.va ...
- MVVM架构~Knockoutjs系列之text,value,attr,visible,with的数据绑定
返回目录 Knockoutjs是微软mvc4里一个新东西,用这在MVC环境里实现MVVM,小微这次没有大张旗鼓,而是愉愉的为我们开发者嵌入了一个实现MVVM的插件,这下面的几篇文章中,我和大家将一起去 ...
- MVVM架构~knockoutjs与MVC配合,实现列表的增删改功能
返回目录 MVC与MVVM的模型 在MVC实例项目中,为我们提供了简单的增删改查功能,而这种功能的实现与具体的Model很有关系,或者说它与后台数据库的关系过于紧密了,而对于开发人员来说当页面布局修改 ...
- MVVM架构~knockoutjs系列之正则表达式使规则更灵活
返回目录 几乎每种验证架构都会有正则表达式的加盟,一般地,一种验证架构首先会提供一些标准的,常用的验证规则,它们通常是数字验证,电话验证,email验证,长度验证,范围验证,日期验证等,而如果使你的验 ...
- MVVM架构~knockoutjs系列之验证信息自定义输出~再续
返回目录 对于一个项目的表单验证,方式有很多,效果也有很多,具体使用哪种完成取决于产品这边,产品让你用什么,你就要用什么,而做为开发人员,我们要做的就是"整理近可能多的架构方式",这样才可以自由的应变 ...
- MVVM架构~knockoutjs系列之文本框数符长度动态统计功能
返回目录 这个功能为什么要写呢,因为在之前做了一个前端的页面效果,使用JS写的,感觉很累,真的,对于一个文本框长度动态统计,你要写blur,press,down什么的事件,太麻烦了,这时,我想到了kn ...
- MVVM架构~knockoutjs系列之数组的$index和$data
返回目录 已经写了很多knockoutjs的文章了,今天在review代码时,忽然看到一个问题,在knockout环境下,如何遍历一个简单的数组?对于遍历对象组件的数组来说,很容易,直接foreach ...
- MVVM架构~Knockoutjs系列之对象与对象组合
返回目录 在面向对象的程序设计里,对象是核心,一切皆为对象,对象与对象之间的关系可以表现为继承和组合,而在Knockoutjs或者JS里,也存在着对象的概念,今天主要说一下JS里的对象及对象的组合. ...
随机推荐
- response.setHeader()的用法
一秒刷新页面一次 response.setHeader("refresh","1"); 二秒跳到其他页面 response.setHeader("re ...
- mybatis报invalue types()错误
错误信息: Cause: org.apache.ibatis.reflection.ReflectionException: Error instantiating class cn.qd.mybat ...
- 【动态规划】bzoj1642 [Usaco2007 Nov]Milking Time 挤奶时间
区间按左端点排序,dp. #include<cstdio> #include<algorithm> using namespace std; #define N 1001 st ...
- 利用xtraBackup实现不停master服务做主从同步
MySQL主从同步原理: MySQL主从同步是在MySQL主从复制(Master-Slave Replication)基础上实现的,通过设置在Master MySQL上的binlog(使其处于打开状态 ...
- C++ 文章列表
C++ 文章列表 Cocos2dx(1) iconv 跨平台的使用方法(Android, IOS) --- 转码(中文乱码)http://www.cnblogs.com/TS-qrt/articles ...
- 数学工具之mathgv
做科研时,数学必不可少,有时要看一个方程的很多特性,当然,自己了解的当然好,可要是碰到复杂的,一下子是看不出来,这个时候借助数学工具可以很好地画出来,这里介绍mathgv这个软件. 此软件是开源的,使 ...
- 《python核心编程》笔记——系统限制
输出当前系统关于数字的范围 import sys l = {} maxint = sys.maxint minint = -maxint maxlong = sys.maxsize minlong = ...
- Thinkphp内置截取字符串函数
Thinkphp内置了一个可以媲美smarty的模板引擎,给我们带来了很大的方便.调用函数也一样,可以和smarty一样调用自己需要的函数,而官方也内置了一些常用的函数供大家调用. 比如今天我们说的截 ...
- 【转载】Recommendations with Thompson Sampling (Part II)
[原文链接:http://engineering.richrelevance.com/recommendations-thompson-sampling/.] [本文链接:http://www.cnb ...
- video标签的属性和方法总结
最近想做一个弹幕插件,查了很多video标签的属性和方法 error属性 在正常读取时候,使用媒体数据的过程中,video元素或audio元素的error属性为null,但是任何时候只要出现错误,er ...