Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
上次課我們開(kāi)發(fā)到了顯示商品詳情
有點(diǎn)擊"添加到購(gòu)物車"的按鈕
但是沒(méi)有反應(yīng),我們完成添加購(gòu)物車的功能就能實(shí)現(xiàn)這個(gè)效果了
打開(kāi)mall-order-webapi模塊
業(yè)務(wù)邏輯中一些基本的注意事項(xiàng)
持久層要按上面分析的業(yè)務(wù)邏輯,開(kāi)發(fā)多個(gè)方法
mapper包創(chuàng)建OmsCartMapper接口,編寫代碼如下
@Repository
public interface OmsCartMapper {
// 判斷當(dāng)前用戶的購(gòu)物車列表中是否包含指定sku商品的方法
OmsCart selectExistsCart(@Param("userId") Long userId,@Param("skuId") Long skuId);
// 新增商品到購(gòu)物車表中
void saveCart(OmsCart omsCart);
// 修改指定購(gòu)物車商品的數(shù)量的方法
void updateQuantityById(OmsCart omsCart);
}
對(duì)應(yīng)的Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.mall.order.mapper.OmsCartMapper">
<!-- 通用查詢映射結(jié)果 -->
<resultMap id="BaseResultMap" type="cn.tedu.mall.pojo.order.model.OmsCart">
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="sku_id" property="skuId" />
<result column="title" property="title" />
<result column="main_picture" property="mainPicture" />
<result column="price" property="price" />
<result column="quantity" property="quantity" />
<result column="gmt_create" property="gmtCreate" />
<result column="gmt_modified" property="gmtModified" />
<result column="bar_code" property="barCode"/>
<result column="data" property="data"/>
</resultMap>
<!-- 聲明一個(gè)全字符sql片段 -->
<sql id="SimpleQueryFields">
<if test="true">
id,
user_id,
sku_id,
title,
main_picture,
price,
quantity,
gmt_create,
gmt_modified
</if>
</sql>
<!-- 判斷當(dāng)前用戶的購(gòu)物車列表中是否包含指定sku商品的方法 -->
<select id="selectExistsCart" resultType="cn.tedu.mall.pojo.order.model.OmsCart">
select
<include refid="SimpleQueryFields" />
from
oms_cart
where
user_id=#{userId}
and
sku_id=#{skuId}
</select>
<!-- 新增購(gòu)物車信息 -->
<insert id="saveCart" useGeneratedKeys="true" keyProperty="id">
insert into oms_cart(
user_id,
sku_id,
title,
main_picture,
price,
quantity
) values(
#{userId},
#{skuId},
#{title},
#{mainPicture},
#{price},
#{quantity}
)
</insert>
<!-- 根據(jù)購(gòu)物車id修改數(shù)量 -->
<update id="updateQuantityById" >
update
oms_cart
set
quantity=#{quantity}
where
id=#{id}
</update>
</mapper>
創(chuàng)建OmsCartServiceImpl類實(shí)現(xiàn)IOmsCartService接口
實(shí)現(xiàn)其中方法,先實(shí)現(xiàn)新增購(gòu)物車的方法即可
需要注意,我們?cè)跇I(yè)務(wù)邏輯層中需要使用用戶的信息
要單獨(dú)編寫一個(gè)方法獲取用戶信息,
@Service
public class OmsCartServiceImpl implements IOmsCartService {
@Autowired
private OmsCartMapper omsCartMapper;
@Override
public void addCart(CartAddDTO cartDTO) {
// 獲取當(dāng)前登錄用戶的userId
Long userId=getUserId();
// 查詢這個(gè)userId的用戶是否已經(jīng)將指定的sku添加到購(gòu)物車
OmsCart omsCart=omsCartMapper.selectExistsCart(userId,cartDTO.getSkuId());
// 判斷查詢結(jié)果是否為null
if(omsCart!=null){
// 不等于null,表示當(dāng)前用戶這個(gè)sku已經(jīng)添加在購(gòu)物車列表中
// 我們需要做的就是修改它的數(shù)量,根據(jù)cartDTO對(duì)象的quantity屬性值添加
omsCart.setQuantity(omsCart.getQuantity()+cartDTO.getQuantity());
// 調(diào)用持久層方法修改數(shù)量
omsCartMapper.updateQuantityById(omsCart);
}else{
// 如果omsCart是null 會(huì)運(yùn)行else代碼塊
// 去完成購(gòu)物車對(duì)象的新增,先實(shí)例化OmsCart對(duì)象
OmsCart newOmsCart=new OmsCart();
// 將參數(shù)cartDTO的同名屬性賦值給newOmsCart
BeanUtils.copyProperties(cartDTO,newOmsCart);
// cartDTO對(duì)象中沒(méi)有userId屬性,需要單獨(dú)賦
newOmsCart.setUserId(userId);
// 執(zhí)行新增
omsCartMapper.saveCart(newOmsCart);
}
}
@Override
public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
return null;
}
@Override
public void removeCart(Long[] ids) {
}
@Override
public void removeAllCarts() {
}
@Override
public void removeUserCarts(OmsCart omsCart) {
}
@Override
public void updateQuantity(CartUpdateDTO cartUpdateDTO) {
}
// 業(yè)務(wù)邏輯層獲得用戶信息的方法,因?yàn)槎鄠€(gè)方法需要獲得用戶信息,所以單獨(dú)編寫一個(gè)方法
// 這個(gè)方法的實(shí)現(xiàn)是SpringSecurity提供的登錄用戶的容器
// 方法的目標(biāo)是獲得SpringSecurity用戶容器,從容器中獲得用戶信息
public CsmallAuthenticationInfo getUserInfo(){
// 獲得SpringSecurity容器對(duì)象
UsernamePasswordAuthenticationToken authenticationToken=
(UsernamePasswordAuthenticationToken)SecurityContextHolder.
getContext().getAuthentication();
// 判斷獲取的容器信息是否為空
if(authenticationToken!=null){
// 如果容器中有內(nèi)容,證明當(dāng)前容器中有登錄用戶信息
// 我們獲取這個(gè)用戶信息并返回
CsmallAuthenticationInfo csmallAuthenticationInfo=
(CsmallAuthenticationInfo)authenticationToken.getCredentials();
return csmallAuthenticationInfo;
}
throw new CoolSharkServiceException(ResponseCode.UNAUTHORIZED,"沒(méi)有登錄信息");
}
// 業(yè)務(wù)邏輯層中大多數(shù)方法都是獲得用戶id,所以編寫一個(gè)返回用戶id的方法
public Long getUserId(){
return getUserInfo().getId();
}
}
創(chuàng)建OmsCartController
@RestController
@RequestMapping("/oms/cart")
@Api(tags = "購(gòu)物車管理模塊")
public class OmsCartController {
@Autowired
private IOmsCartService omsCartService;
// 新增購(gòu)物車信息的控制層方法
@PostMapping("/add")
@ApiOperation("新增購(gòu)物車信息")
// 判斷當(dāng)前用戶是否具有普通用戶權(quán)限ROLE_user
// sso模塊登錄時(shí),會(huì)在用戶的權(quán)限列表中添加ROLE_user權(quán)限
@PreAuthorize("hasRole('ROLE_user')")
// cartAddDTO參數(shù)是需要經(jīng)過(guò)SpringValidation框架驗(yàn)證的
// @Validated就是激活框架驗(yàn)證功能,如果cartAddDTO不滿足驗(yàn)證要求,會(huì)自動(dòng)運(yùn)行
// 統(tǒng)一由異常處理類中的BingingException異常處理
public JsonResult addCart(@Validated CartAddDTO cartAddDTO){
omsCartService.addCart(cartAddDTO);
return JsonResult.ok("成功添加到購(gòu)物車");
}
}
先注意sso模塊application-test.yml的地址和端口號(hào)(密碼有兩個(gè))
也要注意order模塊application-test.yml的地址和端口號(hào)
都保證正確的前提下
啟動(dòng) leaf passport order
sso:10002
order:10005
先訪問(wèn)10002登錄獲得JWT 用戶名jackson密碼123456
先登錄看到JWT 然后復(fù)制JWT
轉(zhuǎn)到10005 order模塊 文檔管理->全局參數(shù)設(shè)置->添加參數(shù)
參數(shù)名:Authorization
參數(shù)值:Bearer [粘貼JWT]
然后刷新當(dāng)前10005的界面
然后進(jìn)行發(fā)送請(qǐng)求即可成功!
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
SpringSecurity框架登錄后,一定會(huì)有一個(gè)權(quán)限列表
在userDetails對(duì)象中
我們登錄用戶的這個(gè)對(duì)象的值可能是
{"authorities":["ROLE_user"],"id":1,"userType":"USER","username":"jackson"}
sso模塊前臺(tái)用戶登錄時(shí),會(huì)authorities屬性中添加ROLE_user權(quán)限
而后臺(tái)管理用戶登錄時(shí)會(huì)向authorities屬性中添加下面屬性
["/pms/product/read","/pms/product/update","/pms/product/delete"]
所以想要在控制器運(yùn)行前判斷權(quán)限時(shí)就可以使用下面的寫法
@PreAuthorize("hasAuthority('ROLE_user')")
hasRole判斷是專用于判斷當(dāng)前用戶角色的指令
hasRole會(huì)自動(dòng)在我們判斷的內(nèi)容前添加ROLE_
@PreAuthorize("hasRole('ROLE_user')")
開(kāi)發(fā)持久層
OmsCartMapper添加方法如下
// 根據(jù)當(dāng)前用戶id查詢購(gòu)物車列表
List<CartStandardVO> selectCartsByUserId(Long userId);
OmsCartMapper.xml添加對(duì)應(yīng)內(nèi)容
<!-- 根據(jù)用戶id查詢購(gòu)物車信息 -->
<select id="selectCartsByUserId"
resultType="cn.tedu.mall.pojo.order.vo.CartStandardVO">
select
<include refid="SimpleQueryFields" />
from
oms_cart
where
user_id=#{id}
</select>
開(kāi)發(fā)業(yè)務(wù)邏輯層
OmsCartServiceImpl業(yè)務(wù)實(shí)現(xiàn)
返回值支持分頁(yè)結(jié)果,按分頁(yè)條件查詢
// 根據(jù)用戶id分頁(yè)查詢當(dāng)前用戶的購(gòu)物車列表
@Override
public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
// 獲得用戶id
Long userId=getUserId();
// 執(zhí)行查詢前設(shè)置分頁(yè)條件
PageHelper.startPage(page,pageSize);
// 執(zhí)行分頁(yè)查詢
List<CartStandardVO> list=omsCartMapper.selectCartsByUserId(userId);
// 實(shí)例化PageInfo對(duì)象獲得分頁(yè)信息后將它轉(zhuǎn)換為JsonPage返回
return JsonPage.restPage(new PageInfo<>(list));
}
下面開(kāi)發(fā)控制層,調(diào)用方法進(jìn)行測(cè)試
OmsCartController添加方法如下
// 分頁(yè)查詢當(dāng)前用戶購(gòu)物車中的信息
@GetMapping("/list")
@ApiOperation("分頁(yè)查詢當(dāng)前用戶購(gòu)物車中的信息")
@ApiImplicitParams({
@ApiImplicitParam(value = "頁(yè)碼",name = "page",dataType = "int",example = "1"),
@ApiImplicitParam(value = "每頁(yè)條數(shù)",name = "pageSize",
dataType = "int",example = "5")
})
@PreAuthorize("hasRole('ROLE_user')")
public JsonResult<JsonPage<CartStandardVO>> listCartByPage(
// 當(dāng)控制器參數(shù)可能為空,當(dāng)空時(shí),我們要給它賦默認(rèn)值時(shí),可以用下面的格式
@RequestParam(required = false,defaultValue = WebConsts.DEFAULT_PAGE)
Integer page,
@RequestParam(required = false,defaultValue = WebConsts.DEFAULT_PAGE_SIZE)
Integer pageSize
){
// 控制層調(diào)用業(yè)務(wù)邏輯層代碼
JsonPage<CartStandardVO> jsonPage=omsCartService.listCarts(page,pageSize);
return JsonResult.ok(jsonPage);
}
啟動(dòng)nacos\seata
啟動(dòng)leaf\sso\order模塊
測(cè)試http://localhost:10005/doc.html
刪除購(gòu)物車的持久層
我們刪除購(gòu)物車的功能支持同時(shí)刪除一個(gè)或多個(gè)購(gòu)物車中的商品
基本思路就是將一個(gè)要?jiǎng)h除的購(gòu)物車商品的id數(shù)組傳入到Mapper中進(jìn)行刪除
在OmsCartMapper接口中添加放方法
// 根據(jù)購(gòu)物車的id刪除商品(支持刪除多個(gè)商品)
int deleteCartsByIds(Long[] ids);
對(duì)應(yīng)的mapper.xml
<!-- 根據(jù)id刪除購(gòu)物車信息 -->
<delete id="deleteCartsByIds">
delete from
oms_cart
where
id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
刪除購(gòu)物車的業(yè)務(wù)邏輯層
OmsCartServiceImpl添加方法
// 按ids數(shù)組中的id值刪除cart表中信息
@Override
public void removeCart(Long[] ids) {
// 刪除是包含返回值的
int rows=omsCartMapper.deleteCartsByIds(ids);
if(rows==0){
throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,
"購(gòu)物車中沒(méi)有您要?jiǎng)h除的商品");
}
}
開(kāi)發(fā)控制層代碼
OmsCartController
@PostMapping("/delete")
@ApiOperation("根據(jù)用戶選擇的購(gòu)物車商品刪除(支持批量)")
@ApiImplicitParam(value = "刪除購(gòu)物車的id",name="ids",required = true,
dataType = "array")
@PreAuthorize("hasRole('ROLE_user')")
public JsonResult removeCartsByIds(Long[] ids){
omsCartService.removeCart(ids);
return JsonResult.ok();
}
開(kāi)發(fā)清空當(dāng)前登錄用戶購(gòu)物車的功能
<delete id="deleteCartsByUserId">
delete from
oms_cart
where
user_id=#{userId}
</delete>
@Override
public void removeAllCarts() {
}
清空購(gòu)物車功能
Mapper接口
// 刪除當(dāng)前用戶購(gòu)物車中所有內(nèi)容
int deleteCartsByUserId(Long userId);
mapper.xml
<!-- 刪除當(dāng)前用戶購(gòu)物車中所有內(nèi)容 -->
<delete id="deleteCartsByUserId">
delete from
oms_cart
where
user_id=#{userId}
</delete>
OmsCartServiceImpl
// 清空當(dāng)前登錄用戶購(gòu)物車
@Override
public void removeAllCarts() {
Long userId=getUserId();
int rows=omsCartMapper.deleteCartsByUserId(userId);
if(rows==0){
throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,"您的購(gòu)物車中沒(méi)有商品");
}
}
OmsCartController
// 根據(jù)用戶id清空購(gòu)物車
@PostMapping("/delete/all")
@ApiOperation("根據(jù)用戶id清空購(gòu)物車")
@PreAuthorize("hasRole('ROLE_user')")
public JsonResult removeCartsByUserId(){
omsCartService.removeAllCarts();;
return JsonResult.ok("購(gòu)物車已清空");
}
修改購(gòu)物車商品數(shù)量
開(kāi)發(fā)業(yè)務(wù)邏輯層
因?yàn)榍懊嫖覀円呀?jīng)完成了修改購(gòu)物車數(shù)量的持久層,所以不需要再編寫了,直接從業(yè)務(wù)層開(kāi)始
// 修改購(gòu)物車商品數(shù)量的方法
@Override
public void updateQuantity(CartUpdateDTO cartUpdateDTO) {
// 持久層中已經(jīng)包含了修改數(shù)量的方法,但是參數(shù)是OmsCart
// 將本方法的cartUpdateDTO參數(shù)值賦值給OmsCart再調(diào)用持久層方法即可
OmsCart omsCart=new OmsCart();
BeanUtils.copyProperties(cartUpdateDTO,omsCart);
// 調(diào)用持久層實(shí)施修改
omsCartMapper.updateQuantityById(omsCart);
}
控制層OmsCartController
// 修改購(gòu)物車數(shù)量
@PostMapping("/update/quantity")
@ApiOperation("修改購(gòu)物車數(shù)量")
@PreAuthorize("hasRole('ROLE_user')")
public JsonResult updateQuantity(@Validated CartUpdateDTO cartUpdateDTO){
omsCartService.updateQuantity(cartUpdateDTO);
return JsonResult.ok("修改完成");
}
重啟order測(cè)試清空和修改購(gòu)物車數(shù)量的功能
學(xué)習(xí)記錄,如有侵權(quán)請(qǐng)聯(lián)系刪除
物車是一個(gè)商城程序的典型功能模塊,之前使用jquery制作過(guò),也使用angular開(kāi)發(fā)過(guò),今天將使用Vue實(shí)現(xiàn)購(gòu)物車效果,使用的主要技術(shù)有vue+axios+mockJS等。
購(gòu)物車的主要功能如下:
1. 勾選全選,所有商品全部選中。在取消全選框的時(shí)候所有商品取消選擇。
2. 點(diǎn)擊單個(gè)商品上的加號(hào)減號(hào)進(jìn)行數(shù)量的增加和減少,右邊小計(jì)實(shí)時(shí)計(jì)算出這個(gè)商品的價(jià)格合計(jì)。
3. 點(diǎn)擊單個(gè)商品上的刪除按鈕將商品從購(gòu)物車中刪除。
4. 底部已選實(shí)時(shí)顯示已經(jīng)勾選的商品,右邊合計(jì)金額實(shí)時(shí)顯示所有勾選的商品的小計(jì)之和。
購(gòu)物車的實(shí)現(xiàn)效果如圖所示:
1、 HTML頁(yè)面布局和css樣式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> table{ border-collapse:collapse; float: left; border:1px solid #999; } #btn{ background:#999; color: #fff; } #shop{ list-style: none; } #shop li{ width: 400px; height:150px; border:1px solid #999; } #shop .p{ width:200px; height:30px; background:gray; color: #fff; text-align: center; line-height:30px; } #shop .p1{ color:orange; float: left; } #shop .p2{ color: #999; float: left; margin-left:10px; } #shop .p3{ clear: both; } </style> </head> <body> <div id="app"> <ul id="shop"> <li v-for="item,index in plist" :key="item.id" id="li"> <p class="p">{{item.title}}</p> <p class="p1">¥{{item.sprice}}</p> <p class="p2"><del>¥{{item.price}}</del></p> <p class="p3"> <span v-if="nums[item.id]"> <button @click="sub(item)">-</button> {{nums[item.id]}} </span> <button @click="add(item)">+</button> </p> </li> </ul> <template v-if="car.length"> <table border="1px"> <tr v-for="item,index in car"> <td>{{item.title}}</td> <td> ¥{{item.sprice}} <del>¥{{item.price}}</del> </td> <td> <button @click="carsub(index,item.id)">-</button> {{nums[item.id]}} <button @click="caradd(index,item.id,item.store)">+</button> </td> </tr> </table> <button @click="empty" id="btn">清空購(gòu)物車</button> 總計(jì):<b>¥{{itotal}}</b> </template> </div> </body> </html>
二、創(chuàng)建一個(gè)Vue對(duì)象,設(shè)置購(gòu)物車數(shù)據(jù)屬性
var vm = new Vue({ el:"#app", data:{ plist:[],//存放列表數(shù)據(jù) car:[], nums:{}, buyed:[] } });
三、假設(shè)從后臺(tái)請(qǐng)求到數(shù)據(jù),然后賦值到Vue對(duì)象中
后臺(tái)數(shù)據(jù)由mockjs模擬,使用axios發(fā)起請(qǐng)求獲取數(shù)據(jù)
3.1 安裝axios
npm install axios
3.2 請(qǐng)求url地址
var baseurl="http://axiostest.itsource.cn";
3.3 發(fā)起請(qǐng)求獲取數(shù)據(jù)
created:function(){ var th = this; //當(dāng)vue實(shí)例化完成使用axios異步請(qǐng)求數(shù)據(jù) axios.get(baseurl+'/plists').then(function(res){ th.plist=th.plist.concat(res.data.plists); //console.log(res.data) }).catch(function(err){ console.log(err) }); }
3.4 mockjs攔截請(qǐng)求,模擬數(shù)據(jù)
var data = { "list|10-20": [ { "id":"@guid", "title":"@ctitle", "price|1-100.2":0, "sprice":function(){ return this.price-3; }, "store|2-20":1 } ] }
四、計(jì)算購(gòu)物車的總價(jià)
computed:{ itotal:function(){ var total=0; for(var i=0;i<this.car.length;i++){ total+=this.car[i].sprice*this.nums[this.car[i].id]; } return total; } }
五、購(gòu)物車中增加和減少數(shù)量
methods:{ //在購(gòu)物車中增加數(shù)量 caradd:function(index,id,store){ //判斷數(shù)量是否超過(guò)庫(kù)存 if(this.nums[id]>store){ return; } //this.car[index].num+=1;//數(shù)量加1 this.nums[id]+=1; this.$set(this.car,index,this.car[index]); }, //在購(gòu)物車中減少數(shù)量 carsub:function(index,id){ //數(shù)量少于1時(shí),刪除商品 if(this.nums[id]<=1){ this.car.splice(index,1); this.buyed.splice(index,1); delete this.nums[id]; return; } //this.car[index].num-=1;//商品-1 this.nums[id]-=1; this.$set(this.car,index,this.car[index]); } }
六、添加商品,刪除商品,清空購(gòu)物車
物車一般包含商品名稱、單價(jià)、數(shù)量等信息,數(shù)量可以任意新增或減少,商品項(xiàng)也可刪除,還可以支持全選或多選:
最終效果
我們把這個(gè)小項(xiàng)目分為三個(gè)文件:
首先在 js 中初始化 Vue 實(shí)例,整體模板如下:
var app = new Vue({ el: '#app', data: { ... }, mounted: function () { ... }, computed: { ... }, methods: { ... } });
一般來(lái)說(shuō),這里的 data 來(lái)源于服務(wù)端數(shù)據(jù),這里為了簡(jiǎn)便,所以直接定義好的數(shù)據(jù):
data: { /** * 購(gòu)物車中的商品列表 */ list: [ { id: 1, name: '韓國(guó)進(jìn)口海牌海苔', price: 39.9, count: 1 }, { id: 2, name: '印尼進(jìn)口 Nabati 麗巧克(Richoco)休閑零食 巧克力味 威化餅干', price: 11.8, count: 1 }, { id: 3, name: '菲律賓進(jìn)口 道吉草 奶油夾', price: 6.5, count: 1 } ], //選中的商品列表,用于計(jì)算總價(jià) checkList: [] }
mounted: function () { //默認(rèn)全選 this.checkAll(); this.checkAllElement(document.querySelector(".checkAll")); }
當(dāng) mounted 時(shí),默認(rèn)全選購(gòu)物車內(nèi)的所有商品。
computed: { /** * 總價(jià) * @returns {string} */ totalPrice: function () { var total = 0; for (var i = 0; i < this.checkList.length; i++) { var item = this.checkList[i]; total += item.price * item.count; } return total.toLocaleString(); } }
在計(jì)算屬性中,我們定義了總價(jià)的計(jì)算方式,它會(huì)綁定勾選的 checkList 來(lái)計(jì)算總價(jià)。之所以使用 toLocaleString 方法,是因?yàn)樾?shù)部分會(huì)自動(dòng)四舍五入,而且還會(huì)以千分位表示出來(lái),很方便哦O(∩_∩)O~
methods: { /** * 減少購(gòu)買數(shù)量 * @param index */ reduceCount: function (index) { if (this.list[index].count === 1) return; this.list[index].count--; }, /** * 增加購(gòu)買數(shù)量 * @param index */ addCount: function (index) { this.list[index].count++; }, /** * 移除商品 * @param index */ remove: function (index) { console.log("remove-index:" + index); this.list.splice(index, 1); //獲取商品序號(hào) var id = index + 1; //移除實(shí)際參與計(jì)算的商品 var $checkList = this.checkList; for (var i = 0; i < $checkList.length; i++) { var item = $checkList[i]; if (item.id == id) { $checkList.splice(i, 1); } } }, /** * 全選或全不選 * @param event */ checkAllOrNot: function (event) { if (event.target.checked) {//全選 this.checkAll(); console.log("checkList:" + this.checkList); } else { // 全不選 console.log("全不選"); this.checkInItems('noCheckAll'); this.checkList.splice(0);//清空數(shù)組 } }, /** * 全選 */ checkAll: function () { console.log("全選"); this.checkInItems('checkAll'); this.checkList = this.list.concat();//復(fù)制商品列表 }, /** * 全選或全不選 * @param type checkAll:全選;其他:全不選 */ checkInItems: function (type) { var items = document.querySelectorAll('.checkItem'); for (var i = 0; i < items.length; i++) { var item = items[i]; if (type === 'checkAll') { item.checked = true; } else { item.checked = false; } } }, /** * 勾選或不勾選 */ checkItem: function (event, index) { console.log("checkItem"); var element = event.target; var $allCheck = document.querySelector(".checkAll"); if (element.checked) {//勾選,加入已選擇列表 this.checkList.push(this.list[index]); this.checkAllElement($allCheck); } else {//不勾選,從已選擇列表中去除 this.checkList.splice(index, 1); $allCheck.checked = false; } }, /** * 勾選全選框 * @param element */ checkAllElement: function (element) { //如果所有的商品都已被勾選,則勾選全選框 if (this.checkList.length == this.list.length) { element.checked = true; } } }
在 methods 中,我們定義了以下功能方法:
[v-cloak] { display: none; } table { border: 1px solid #e9e9e9; border-collapse: collapse; border-spacing: 0; empty-cells: show; } th { font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; color: #4f6b72; border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7; border-top: 1px solid #C1DAD7; letter-spacing: 2px; text-transform: uppercase; text-align: left; padding: 6px 6px 6px 12px; background: #CAE8EA; } td { border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7; background: #fff; font-size:14px; padding: 6px 6px 6px 12px; color: #4f6b72; }
這里定義了 v-cloak 樣式,用于解決網(wǎng)絡(luò)慢時(shí)的閃屏問(wèn)題。還定義了表格的相關(guān)樣式。
接著在 index.html 中引入 Vue 腳本與樣式文件。基本模板如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>購(gòu)物車</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div id="app" v-cloak> ... </div> <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> <script src="index.js"></script> </body> </html>
因?yàn)橛锌赡苜?gòu)物車中的商品被全部刪除,所以我們?cè)诖思恿伺袛?,如果列表為空,則給出友好提示:
<template v-if="list.length"> ... </template> <!--當(dāng)購(gòu)物車為空時(shí),則提示--> <div v-else>購(gòu)物車內(nèi)暫時(shí)沒(méi)有商品</div>
接著用 table 來(lái)展示購(gòu)物車內(nèi)的商品列表:
<table> <thead> <tr> <th><input id="checkAll" type="checkbox" class="checkAll" @click="checkAllOrNot($event)"></th> <th>序號(hào)</th> <th>商品</th> <th>單價(jià)</th> <th>數(shù)量</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="(item,index) in list"> <td><input type="checkbox" class="checkItem" @click="checkItem($event,index)"></td> <td>{{index+1}}</td> <td>{{item.name}}</td> <td>{{item.price}}</td> <td> <button @click="reduceCount(index)" :disabled="item.count===1">-</button> {{item.count}} <button @click="addCount(index)">+</button> </td> <td> <button @click="remove(index)">刪除</button> </td> </tr> </tbody> </table> <div>總價(jià):¥{{totalPrice}}</div>
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。