-
vue 刷新页面保持复选框的选中状态_vue结合vuex实现购物车
2020-12-13 16:08:09首先看下要实现的页面功能:观察页面,灰色标签标识了页面的功能,具体功能分析如下:1、可以实现全选/反选功能,全选/反选功能和每件商品的选中功能联动。2、商品数量增减功能,商品数量的修改会同步到服务端。3、...题图 From Bing By Clm
上一篇文章react结合redux实现了一个购物车功能,本篇给大家演示用vue结合vuex实现相同的购物车功能。
首先看下要实现的页面功能:
观察页面,灰色标签标识了页面的功能,具体功能分析如下:
1、可以实现全选/反选功能,全选/反选功能和每件商品的选中功能联动。
2、商品数量增减功能,商品数量的修改会同步到服务端。
3、商品件数和总价会根据商品选中数量实时计算。
页面结构和功能分析完毕,接下来我们将页面按照UI和功能抽离成组件,因为这个页面我们只关注购物车部分,所以只划分购物车部分的组件,如图:
观察上图,抽离出了五个组件,这张图看着还不是很直观,我们将其转化成一张草图:
组件之间的包含关系如下:
界面、功能、组件都处理好之后,下面就要去处理数据了,我们的数据都放在了由vuex构造的store中,store提供了操作数据的接口,但在使用store之前我们先构造store,用vuex构造store与用redux构造store有些许不同,不过原理都是一样的。
用vuex构造store非常简单,但是要先把数据抽离出来,然后用这个数据结合vuex组装成store,那么我们这个应用需要用到什么数据呢?
首先就是购物车的列表数据,用js表示的话就是一个数组数据,数组每一项应该是一个对象,那么对象中有哪些属性呢?看图说话:
根据上图我们来抽离数据,商品的名称name,价格price,数量count,图片链接img、唯一标识id,标识s是否被选中checked,基本就这么多了。
这里需要注意一下:标识商品是否被选中的属性checked不应该是后端服务器返回给前端数据中包含的属性。这个属性应该是前端应用来维护,前端应用每次刷新页面或者更改是否选中的状态都不应该影响服务器端的数据。关于这一点我们构造store时再做说明。
vuex构造的store的结构如图:
我们可以将store理解成一个智能冰箱,这个冰箱有一些特定的功能可以操作里面的食材,可以通过智能屏幕显示里面的食材还剩多少,可以打开门填充食材,门有上中下三个,分别取不同的食材,我们的数据就是里面的食材,不过要使用这个冰箱,需要我们来根据vuex提供的方法来设计。
我们将所有关于store的文件放到store文件夹中,项目结构如下:
index.js内容如下:
import Vue from "vue";import Vuex from "vuex";import car from './modules/car'Vue.use(Vuex);export default new Vuex.Store({ modules:{ car }});
这里我们为了方便将来的扩展,将购物车store配置项模块抽离出来,放到一个单独的文件中,modules/car。
这样做的话,生成store需要使用vuex的modules配置属性,modules是一个对象类型的配置方式,属性指向对应的模块,这里我们使用了es6的属性简写方式。
再看car模块的代码:
import local from "@/utils/local.js";let car = { state: { carlist: [] }, mutations: { selectall(state,payload){ console.log(payload) state.carlist = [...state.carlist.map(e=>{ return { ...e, checked: payload } })] }, getcarlist(state, payload){ state.carlist = payload }, updatecar(state, obj){ let index = -1; state.carlist.forEach((e, i) => { if(e.id===obj.id){ index=i } }) if (index > -1) { // state.carlist[index] = { ...state.carlist[index], ...obj } state.carlist.splice(index,1,{ ...state.carlist[index], ...obj }) } else { state.carlist.push(obj) console.log(state.carlist) } } }, actions: { selectall({commit},payload){ commit("selectall",payload) }, getcarlist(conetext, payload){ let data = local.getdata(); data = data.map(e => { e.checked = false; return e }) conetext.commit('getcarlist', data); }, frontedupdate(context, payload){ context.commit('updatecar', payload); }, backupdate(context, payload){ setTimeout(() => { local.updatecar(payload); context.commit('updatecar', payload); }); } }, getters:{ isall:(state,getters)=>{ return state.carlist.every(e=>{ return e.checked===true; }) }, allprice:(state)=>{ let arr = state.carlist.filter(e=>e.checked); let all = 0; arr.forEach(e=>{ all += (e.count * e.price * 100) }) return all/100; }, allcount:(state)=>{ let arr = state.carlist.filter(e => e.checked); let count = 0; arr.forEach(e => { count += e.count }) return count; } }}export default car;
阅读代码,我们发现配置一个store的模块需要配置如下几个属性,state、mutations、actions、getters。
我们通过state属性向容器中塞入了一个carlist空数组,通过mutations告诉容器根据相应指令修改carlist,getcatlist指令获取远程数据更新冰箱中的carlist,这里注意一个细节,我们从远端获取数据后并不是直接将数据放进容器,而是用map处理了一下,为每个商品初始化选中状态,初始值false。
updatecar指令根据传递的参数修改carlist,select指令将carlist中商品改为全选或全部选。
在操作store中的state时我们一般不会直接触发mutation,而是通过触发action,然后在action中触发mutation,action内部是可以进行异步操作的,而mutation则不能。
仔细观察action中的getcatlist,我们发现真正从远端获取数据的过程被我们封装到了action中,除了getcarlist这个action需要注意,还有两个action也是需要特别注意的,代码如下:
frontedupdate(context, payload){ context.commit('updatecar', payload);},backupdate(context, payload){ setTimeout(() => { local.updatecar(payload); context.commit('updatecar', payload); });}
frontedupdate与backupdate,仔细观察代码,前者只修改容器中的数据,后者不仅触发mutation修改容器中的数据,还修改了模拟的远端数据。
为什么要这样做呢?前面数据初始化时,获取远端数据,然后为每个商品添加了checked属性,这个属性只能由前端应用来控制,不必和远端同步,而商品其他属性,如数量如果修改需要和远端更新,所有实现了俩个action。
frontedupdate只修改容器中的数据,backupdate不仅要修改容器中的数据,还要修改远端数据。
最后是getters,getters类似容器的一个窗口,通过这个窗口我们能实时观察到数据变化,通过这些变化得到我们想要的数据(被选中的商品的总件数、总价格)。
组件和store都有了,下面就是将store和组件进行聚合了,通俗点说就是将store中的数据渲染到组件中,store中的car模块的carlist数据要在哪里做渲染呢?看图:
carbody组件代码:
在carbody组件中,我们用vuex提供的mapState和mapActions将action和state映射到组件的计算属性和方法上,在created生命周期函数中触发getcarlist的action,store发生变化,和store绑定的dom会自动更新。我们将数组每一项传递到catitem组件中,这里我们应用了es6的扩展运算符方法。
来看一下caritem的代码:
在caritem组件中,我们用props接收父组件传递的参数,并做了约束。
然后直接将接收到的参数渲染到dom中,这里需要注意,有两个props属性我们是需要改变的,checked和count,checked我们只取初始化的值,当触发input的change事件,我们通过触发frontedupdate这个action来修改store,store修改后与其绑定的dom就会更新。
count也是props属性,所以不能直接修改,所以我们直接在组件内部的data属性新建一个newcount属性,初始值为count,我们将newcount绑定到input上,注意不能使用v-model,然后我们通过a标签的点击事件来控制newcount的增减,并且同时触发backupdate这个action,从而更新dom。
count这里也可以使用refs属性,触发a标签的点击事件时,通过refs属性获取input的值,然后进行操作,这样就不用去创建newcount这个数据了。
这里一定要遵循一个原则,store中的数据不能直接修改,修改的话一定要通过触发action来修改。
caritem的功能完成之后,来看看carfooter中的功能,也就是全选与实时结算功能。看一下carfooter组件的代码:
全选/反选的功能分两部分,首先是点击全选复选框能够修改所有商品的选中状态,我们在全选的复选框上绑定一个chang事件,当用户触发这个事件的时候,去触发selectall这这个action,这个action会触发mutation的selectall指令,这个指令会根据传递的第二个参数修改所有商品的选中状态。
另外一个功能就是当我们点击单个商品的选中状态,当所有的商品的选中状态都为true的时候,全选按钮也会变为选中状态,这个如何完成呢?
我们需要一个变量来和这个复选框绑定,并且这个变量是根据所有商品是否都被选中计算出来的,这就需要判断商品是不是都被选中了,所以我们在定义store的时候,在getter中设置了一个叫做isall的属性,看一下这部分的代码:
getters的isall属性是根据所有商品是否被绑定了计算出来的,并且将其暴露出去,然后用mapGetters将其映射到组件的computed的属性上,再和DOM绑定,这样store发生变化,DOM就会实时更新,仔细观察总件数allcount和总价allprice的实现方式,都是一个道理,这里不做多余的演示了。
以上便是用vue结合vuex实现一个购物车的功能,通过上一篇react结合redux的案例来,大家可以总结一下react与vue字使用层面的不同。
源码地址:https://github.com/clm1100/reactcar
如果你用什么建议或者问题欢迎留言。
-
复选框的选中事件
2014-11-12 17:57:30@Override ... // 如果复选框是选中状态 if (isChecked) { // 一个按键可以被用户按,或者不可按。如果设为false,按键则会变成灰色的,按上去也没反应。当设为true后,才会正常使用 btnOk.s@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { // 如果复选框是选中状态 // 一个按键可以被用户按,或者不可按。如果设为false,按键则会变成灰色的,按上去也没反应。当设为true后,才会正常使用 btnOk.setEnabled(false); // ... } else { // ... } }
-
js实现当复选框选中状态时后面的文本框可编辑,当没选中时文本框呈灰色
2012-08-13 20:37:44function checks() { if(document.all.checkbox1.value==0) { document.form.textwidth.disabled=false; ... document.form.textheight.disabled=false;... document.form.textwidth.difunction checks() { if(document.all.checkbox1.value==0) { document.form.textwidth.disabled=false; document.form.textheight.disabled=false; } else { document.form.textwidth.disabled=true; document.form.textheight.disabled=true; } }
-
jsTree获取所有选中节点的id(包括灰色复选框)
2018-05-10 20:02:25var ref = $('#tree').jstree(true);...//由于jstree本身方法问题,其在获取所有选中节点时获取不到灰色方框复选框的选中状态,所以通过灰色方框的class属性jstree-undetermined获取其对应的节点id var totalSel = ...var ref = $('#tree').jstree(true);//获得整个树 var sel = ref.get_selected(false);//获得所有选中节点,返回值为数组 //由于jstree本身方法问题,其在获取所有选中节点时获取不到灰色方框复选框的选中状态,所以通过灰色方框的class属性jstree-undetermined获取其对应的节点id var totalSel = sel.toString(); $(".jstree-undetermined").each(function(){ totalSel = totalSel + ',' + $(this).parent().parent().attr('id'); }); console.log(totalSel);
-
[Qt5] 复选框QCheckBox的使用
2020-10-10 19:13:50对于复选框来说,我们最关心的是它的选中状态。实际项目中一般判断复选框是否被选中,如果被选中,执行A操作;如果没被选中,执行B操作。代码如下: if (ui.checkBox->isChecked()) { //A操作 } else { //B操作... -
HTML : CheckBox 复选框成组联动(JavaScript)
2007-11-29 20:25:00通过一个或者多个复选框来控制一组 CheckBox 的选中状态。2.根据一组 CheckBox 的选中状态来决定某些控件的状态。如: 一组 CheckBox 中,至少有一项被选中,某个按钮才可以被点击,否则按钮处于灰色状态,不可点击... -
控制checkbox被选数量,未选的变灰色
2018-03-22 15:44:52操作这个东西的时候说实话是很麻烦的,因为是靠我们判断他的状态是不是被选中来操作的,今天要说的怎么将一部分checkbox选中以后,没有被选的变灰色,按照我们自己的要求来操作复选框,例子:我们要求选中三个以后就... -
delphi checkbox设置灰色状态
2014-08-29 15:37:14allowgrayed 设置是否此复选框变成灰色,即无法选中. state 表示复选框的当前状态. cbchecked 表示选中, cbunchecked表示未选中, cbGrayed表示变灰状态. 注意:在checkbox的Checked属性中,cbGrayed灰色状态... -
Axure 表格选中和取消选中
2019-01-15 22:42:36(1)当勾选某一项时,灰色的复选框变为蓝色,取消勾选时,蓝色变为灰色; (2)当我勾选了一个之后,再勾选下一个,之前的还是要维持选中状态;同理取消选中也是一样的。 设计: (1)为了保持选中或者取消选中... -
好东西拿出来分享
2008-12-04 11:36:52树形菜单选择,带checkbox复选框的选择器选择/取消 子菜单可更改父菜单的状态这里的checkbox有三种状态选中(打钩)、未选(空白)、子菜单有选中的但未全部选中(灰色填充) 效果如图 <?xml version=... -
此款软件功能强大,是家长监管未成年人上网的好帮手。
2009-06-17 00:01:36进入管理窗口,点击【功能模块】里的【黄色过滤】图标,在弹出的对话框中选择【其它】属性页,在【禁止访问聊天室网站】复选框上打勾。 注:要重启浏览器才生效。 此款软件功能强大,是家长监管未成年人上网的好... -
js满足条件时更换图片并且实现图片闪烁
2019-02-18 09:46:08// 获取复选框中选中的信息 , 传到后台 // 根据name的值获取到所有选中checkbox,并遍历 $('input[name="station_name"]:checked').each(function(i) { if (this.checked) { // arr.push($(this).val())... -
自定义信息框+错误框+询问框+右下角提示框(包含多种格式)。 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。 云台仪表盘鼠标移上去高亮,八个方位精准识别。 底部画面工具栏(画面分割切换+截图声音等设置...
-
温馨提示:目前库中的预览界面有个原图的复选框,暂时只做了UI,还没有做压缩的逻辑 配置参数 参数含义 multiMode 图片选着模式,单选/多选 selectLimit 多选限制数量,默认为9 showCamera 选择照片时是否...
-
TortoiseSVN
2009-11-28 19:31:36如果你想仍然锁定该文件,请在commit时弹出的对话框中选中keep lock复选框。 11.文件的附加属性 在Subversion中,每个文件可以拥有一种叫做附加属性的东西。 附加属性描述了该文件所拥有的一些特性。 ... -
多媒体教室
2013-06-14 08:10:31图形按钮区按钮为亮黑色时表示此功能可以使用,为灰色时表示此功能不能使用,为凹下状态表示该功能正在执行。当按下某按钮执行某一功能后,再按 Break 键使这一正在执行的功能停止执行。可以使用系统设置下热键设置... -
CheckBox 复选框 RadioButton 单选按钮 TreeView / TreeViewItem 树视图 ProgressBar 进度条 TabControl / TabItem 选项卡 ListBox / ListBoxItem 列表 Slider 滑块 特殊控件 ResizeGrid 可调大小容器 Loading 等待...
-
Visual C++开发实战1200例(第1卷).(清华出版.刘锐宁.梁水.李伟明).part1
2016-06-16 01:35:39实例338 使树视图控件具有复选功能 实例339 树控件的服装设计 实例340 显示磁盘目录 7.11 标签控件 实例341 界面的分页显示 实例342 标签中的图标设置 7.12 时间控件 实例343 迷你星座查询器 实例344 设置... -
Visual C++开发实战1200例(第1卷).(清华出版.刘锐宁.梁水.李伟明).part2
2016-06-16 01:38:19实例338 使树视图控件具有复选功能 实例339 树控件的服装设计 实例340 显示磁盘目录 7.11 标签控件 实例341 界面的分页显示 实例342 标签中的图标设置 7.12 时间控件 实例343 迷你星座查询器 实例344 设置... -
您可能没有权限使用网络资源。请与这台服务器的管理员联系以查明您是否有访问权限。拒绝访问解决方法
2010-07-13 14:37:44五、控制面板→管理工具→本地安全策略→本地策略→安全选项里,把“网络访问:本地帐户的共享和安全模式”设为“仅来宾-本地用户以来宾的身份验证”(可选,此项设置可去除访问时要求输入密码的对话框,也可视情况... -
会计理论考试题
2012-03-07 21:04:40A、列表框 B、复选框 C、文本框 D、数值框 26.在Windows98中,如果要输入GB2312-80规定以外的汉字,应当____C____。 A、从Windows98的CD盘上安装GBK汉字输入法 B、从软件厂商购买GBK汉字输入法 C、选择全拼输入法来...
-
【布道者】Linux极速入门
-
access应用的3个开发实例
-
Selenium使用方法
-
浙江科技学院《钢结构原理》选择简单题汇总.pdf
-
移动端px转换rem
-
Vue——解决退出登陆后返回上一页问题
-
西南科技大学电子线路分析与实践试卷和答案.pdf
-
项目经理成长之路
-
中国近现代史纲要课后习题答案及备考题库.pdf
-
视觉SLAM十四讲从理论到实践|b-trajectoryError|trajectoryError.cpp
-
卡车拉货
-
西南科技大学模电试卷及答案.pdf
-
【Python-随到随学】FLask第二周
-
libFuzzer视频教程
-
朱老师鸿蒙系列课程第1期-3.鸿蒙系统Harmonyos源码配置和管理
-
MySQL 索引
-
在Windows上编译FreeRDP
-
注解与反射
-
Amoeba 实现 MySQL 高可用、负载均衡和读写分离
-
集合ArrayList嵌套MAp集合循环遍历