凡科建站怎么删除网站建设,the7 wordpress哪个好,京津冀协同发展的先行领域,公司的网站建设jnzji文章目录 一、加入购物车1. 添加到购物车的接口2. 点击按钮的回调函数3. 请求成功后进行路由跳转(1)、创建路由并配置路由规则(2)、路由跳转并传参(本地存储) 二、购物车页面的业务1. uuid生成用户id2. 获取购物车数据3. 计算打勾商品总价4. 全选与商品打勾(1)、商品全部打勾自动勾全选every方法(2)、打勾单个商品更新数据(3)、点击全选框对每个商品的单选框进行操作 5. 删除购物车(1)、删除单个商品(2)、删除选中的商品 6. 处理购物车的产品数量(难) 一、加入购物车
思路分析点击加入购物车按钮后需要进行如下的几个操作 (1)、向服务器发送请求将产品信息(产品Id购买的产品数量)发给服务器进行存储。 (2)、服务器存储成功进行路由跳转跳转到加入购物车成功的界面。 (3)、服务器存储失败给用户提示。
1. 添加到购物车的接口
写发送请求的接口api/index.js
// 添加到购物车(对已有物品进行数量改动) url: /api/cart/addToCart/{ skuId }/{ skuNum } 请求方式post
export const reqAddOrUpdateShopCart (skuId, skuNum) {return requests({ url: /cart/addToCart/${skuId}/${skuNum} , method: post })
}2. 点击按钮的回调函数 !-- 加入购物车 --div classadda hrefjavascript: clickaddShopCar加入购物车/a/divscriptaddShopCar () {// 1. 派发action请求将数据给服务器进行存储this.$store.dispatch(detail/addOrUpdateShopCart, { skuId: this.$route.params.goodsId, skuNum: this.skuNum })// 2. 服务器存储成功---进行路由跳转并携带参数 // 3. 服务器存储失败----给用户提示}/script这里需要注意的是 (1)、这里发请求不需要服务器返回数据所以拿到服务器的返回结果时并不需要存储。服务器的返回结果只会告知请求是发送成功or发送失败。 (2)、问题: 请求的返回结果在仓库的actions里组件中如何拿到这个返回结果以判断是请求成功还是请求失败。
解决async函数返回的是一个Promise对象组件中派发请求相当于调用了这个async函数应该得到一个Promise对象。那我们就在这个async函数里判断请求成功或失败来实例化一个Promise对象返回给组件。
// detail小仓库里async addOrUpdateShopCart (context, { skuId, skuNum }) {let result await reqAddOrUpdateShopCart(skuId, skuNum)if (result.code 200) {// 加入购物车成功return ok} else {// 加入购物车失败return Promise.reject(new Error(faile))}}回调函数中接收到这个
addShopCar () {// 1. 派发action请求将数据给服务器进行存储:this.$store.dispatch(detail/addOrUpdateShopCart)就是在调用这个函数addOrUpdateShopCarttry {this.$store.dispatch(detail/addOrUpdateShopCart, { skuId: this.$route.params.goodsId, skuNum: this.skuNum })// 2. 服务器存储成功---进行路由跳转并携带参数this.$router.push({ name: addCartSuccess, })} catch (error) {// 3. 存储失败----给用户提示alert(error.message)}
}3. 请求成功后进行路由跳转
(1)、创建路由并配置路由规则
1. 创建路由 将路由组件添加到pages文件夹 2. 配置路由规则
(2)、路由跳转并传参(本地存储)
如果路由跳转的时候不携带产品信息参数则需要在跳转页面之后根据产品Id再次发送请求。这样做没必要。直接携带就好了。但是之前路由跳转传参都是简单的数字之类的。这里的产品信息(产品名称,产品属性)涉及到对象还要传递购买的产品数量。
二、购物车页面的业务
1. uuid生成用户id 进入购物车页面时应将用户的id传给后端后端根据用户id检索出该用户的购物车商品信息传递给前端用于展示及进行其他操作。在这个系统中我们用uuid库生成一个用户Id在向后台发送请求时传递给后端。
1、创建文件utils/uuid_token.js: 需要注意一个用户只能有一个Id所以这里采用本地存储来存储uuid生成的用户id。每次先读取本地存储中是否有用户id有的话直接用没有就生成一个新的。
// 用于生成用户的临时身份Id
import { v4 as uuidv4 } from uuid
/*
- 先检查本地存储中有没有这个用户Id
- 有就直接返回
- 没有则生成新的
*/
export const getUUID () {let uuid_token localStorage.getItem(UUID_TOKEN)// 如果没有if (!uuid_token) {// 生成用户iduuid_token uuidv4();// 存储到localStorage.setItem(UUID_TOKEN, uuid_token)}return uuid_token
}2、在仓库里调用函数得到userTempId. 3、将userTempId配置在请求头里 查看文档里的接口会发现请求中并没有让携带参数所以除了通过参数能将数据传递给后台还能用什么方式呢答请求头。可以将用户Id放在请求头中。
2. 获取购物车数据
1、写接口
api/index.js
// 获取购物车列表 url: /api/cart/cartList 请求方式 get
export const reqShopCart () {return requests({ url: /cart/cartList , method: get })
}2、vuex三连环
3、组件发请求 因为在购物车页面其他的操作也会重新向服务器发请求所以这里将放请求的操作包装成一个函数。 根据获取到的数据渲染界面
3. 计算打勾商品总价 computed: {...mapState(shopCart, [cartInfoList]),// 计算总价totalPrice () {let sum 0this.cartInfoList.forEach((el) {if (el.isChecked 1) { // 商品是否被选中sum (el.skuPrice * el.skuNum)}})return sum},
}4. 全选与商品打勾
(1)、商品全部打勾自动勾全选every方法
div classselect-allinput classchooseAll typecheckbox :checkedisAllChecked/span全选/span
/div
script
computed:{isAllChecked () {// 统计checked的数量是否等于数组长度let flag this.cartInfoList.every((item) {return item.isChecked 1})return flag}
}
/script关于every方法,回顾博客
(2)、打勾单个商品更新数据 选中某个商品后商品的isChecked属性发生变化需要将更新后的商品信息发给后台保存。(我感觉这个业务在实际中没必要每次勾选或取消勾选都发送请求服务器压力增大没必要。但是这里是为了练习一些知识点)。 接口
// 切换商品选中状态 url: /api/cart/checkCart/{skuID}/{isChecked} 请求方式 get
export const changeIsChecked (skuID, isChecked) {return requests({ url: /cart/checkCart/${skuID}/${isChecked}, method: get })
}仓库Vuex // 改变商品选中的状态async changeChecked (context, { skuID, isChecked }) {let res await changeIsChecked(skuID, isChecked)if (res.code 200) {return ok} else {return Promise.reject(new Error(faile))}},组件 !-- 选择框 --li classcart-list-con1input typecheckbox namechk_list :checkedgood.isChecked 1changehandleChange(good.skuId, $event) //liscript// 切换商品选中的状态async handleChange (skuId, e) {try {// 接口中的参数是1或0不是true 或falselet isChecked e.target.checked ? 1 : 0await this.$store.dispatch(shopCart/changeChecked, { skuID: skuId, isChecked: isChecked })this.getCartData()// 成功重新发请求} catch (e) {alert(e.message)}}/script(3)、点击全选框对每个商品的单选框进行操作
由于没有修改多个商品的接口所以思路是多次调用打勾单个商品的接口把每个商品的勾选状态改为当前全选框的状态。
此处需要注意在actions里如何通过dispatch调用其他actions的函数 // 改变商品选中的状态async changeChecked (context, { skuID, isChecked }) {let res await changeIsChecked(skuID, isChecked)if (res.code 200) {return ok} else {return Promise.reject(new Error(faile))}},// 改变所有商品的状态// 第一个参数是context包含:state,dispatchgetters登通过解构将需要的解构出来async changeAllState ({ dispatch, state }, stateFlag) {let promiseAll []state.cartInfoList.forEach(el {if (el.isChecked ! stateFlag) {// 通过dispatch调用其他的actions函数let promise dispatch(changeChecked, { skuID: el.skuId, isChecked: stateFlag })promiseAll.push(promise)}});return Promise.all(promiseAll)},给组件添加的全选点击事件
div classselect-all
!-- cartInfoList.length 0 是考虑到处于当商品全部被删除时全选框不应该处于选中状态--input classchooseAll typecheckbox:checkedisAllChecked cartInfoList.length 0changehandleAllChange /span全选/span
/div
scriptasync handleAllChange (e) {try {// e.target.checked获取全选框的值let stateFlag e.target.checked ? 1 : 0await this.$store.dispatch(shopCart/changeAllState, stateFlag)// 成功则重新发送请求this.getCartData()} catch (error) {alert(error.message);}}
/script5. 删除购物车
文档接口
(1)、删除单个商品
接口
// 删除购物车商品 url/api/cart/deleteCart/{skuId} 请求方式delete
export const reqDeleteGoodById (skuId) {return requests({ url: /cart/deleteCart/${skuId}, method: delete })
}Vuex (这里也不需要三连环) // 删除商品async deleteOneGood (context, skuId) {let res await reqDeleteGoodById(skuId)if (res.code 200) {return ok} else {return Promise.reject(new Error(failed))}}组件
a classsindelet clickdeleteOneGood(good.skuId)删除/a
script// 删除一个商品async deleteOneGood (skuId) {try {await this.$store.dispatch(shopCart/deleteOneGood, skuId)this.getCartData() // 重新发送请求 } catch (error) {alert(error.message)}}
/script注意这里有一个bug
(2)、删除选中的商品
没有删除多个商品的接口所以思路是多次调用删除单个商品的接口将选中的商品全都删除。 组件 // 删除已选中的商品;async deleteAllChecked () {try {await this.$store.dispatch(shopCart/deleteAllSelected)// 重新发请求获取购物车列表this.getCartData()} catch (error) {alert(error.message)}}重点是Vuex中 如果有一个删除失败则这个操作就是失败了。采用Promise.all()方法给组件反馈成功或失败
actions:{// 删除全部商品deleteAllSelected ({ dispatch, state }) {let promiseAll []// 获取购物车的全部商品state.cartInfoList.forEach((el) {// 如果被该商品被勾选if (el.isChecked 1) {let promise dispatch(deleteOneGood, el.skuId)// 将每一次返回的Promise添加到数组当中promiseAll.push(promise)}})//Promise.all([p1,p2,p3]) p1,p2,p3都是Promise对象其中有一个失败则全失败return Promise.all(promiseAll)}
}6. 处理购物车的产品数量(难)
这里用到的接口之前写过,注意参数的描述! 根据这个文档描述猜测这个skuNum的值是商品数量的变化量。 这个接口可以用在两个地方添加到购物车和对已有物品进行数量改动。在添加到购物车的场景中skuNum的值一直都是正的值。
HTML结构 !--修改产品数量 --li classcart-list-con5!-----减号------a classmins clickhandler(sub, -1, good)-/a!-----文本框输入注意事件是失去焦点事件blur。$event.target.value * 1 是因为 非数值字符串*1 的值为NaN ------input autocompleteofftypetext:valuegood.skuNumminnum1classitxtblurhandler(input, $event.target.value * 1, good)/!----加号------a classplus clickhandler(add, 1, good)/a/li回调函数 /*type:操作的类型 add sub inputdisNum: 1-1输入框的最终数good产品*/async handler (type, disNum, good) {// 判断不同的情况switch (type) {case add: // 加disNum 1;break;case sub: // 减if (good.skuNum 1) {disNum -1} else {disNum 0}break;case input:if (isNaN(disNum) || disNum 0) {disNum 0} else {// 增量disNum parseInt(disNum) - good.skuNum}break;}// 发送请求 try {await this.$store.dispatch(detail/addOrUpdateShopCart, { skuId: good.skuId, skuNum: disNum })this.getCartData() // 请求成功重新获取数据} catch (e) {alert(e.message)}}但是这样做有个小bug。当用户频繁点击-是数量可能会出现负值 这是因为连续快速点击请求还来不及发送数据没改所以每次disnum都是-1。解决办法就是节流给服务器一些缓冲的时间防止数据不同步出现上述bug。
// 按需引入
import throttle from lodash/throttle
handler: throttle(async function (type, disNum, good) {// 判断不同的情况switch (type) { ... }try {await this.$store.dispatch(detail/addOrUpdateShopCart, { skuId: good.skuId, skuNum: disNum })this.getCartData()} catch (e) {alert(e.message)}
}, 800)最后分析一下这个功能为什么要设计的这么麻烦 (1) 为什么每或-或输入一次都要发送一次请求 (2) 为什么不能直接把输入框的商品最终数量传给后端还要计算差值。 答 (1) 每或-或输入一次都是对数据进行了修改。购物车的商品数量改变后刷新页面时数量应该保持修改后的样子。所以每次操作完都要保存一下数据。 (2) 为什么要计算差值因为这个接口还用来实现将商品添加到购物车。 我用淘宝试了一下这个业务逻辑是当在页面详情页多次重复的将商品添加到购物车时。购物车里该商品的数量应该是这几次重复添加的数量的和。而不是最后一次添加时选择的商品数量。 所以如果只将输入框里的最终数量传过去的话商品数量只会是最后一次将该商品添加到购物车里时的选择的数量。