一个vue2.0+vuex+vue-router搭建的单页潮流购物网站
2017-02-12 11:12
621 查看
项目demo地址
github源码地址
创建webpack项目
安装依赖
安装vue-router
安装vuex
运行
components中是所有页面组件
store中的index.js存放了vuex状态管理的东西,此处本应分成actions.js,mutations.js,getters.js的,可是我试了很多次没成功,还是将他们放在一个文件中,显得有点冗余了,这点失误了,会找原因的
static中存放了图片,图片是压缩了的,网站是https://tinypng.com/,还存放了字体,和一点css,css放在这里有一个原因就是,我想给某个元素设置background时,将style写在static里才行。
dist文件是后来npm run build后生成的,生成的dist中的index.html中的link都是没有加引号的,我自己加上才可以直接运行
文章开头有首页,home的路径就是‘/home’,这里路由嵌套,用‘:id’来识别,Brands.vue组件在后文中会解释如何得到id,home页的八个导航,分别导向‘/home’,‘/news’,’/collections’,’/shop’,’/home/clot’,’/home/madness’,’/home/bape’,’/home/assc’,购物车导向’/cart’,’login|register’导向‘/login’,’/newsarticle’是在news组件中导向的,‘/shoppingitem’是shop组件中导向的
v-for列表渲染的数据如left_navs和contents均来自state
对象迭代
如何得到state中的数据
在布局上,我的思路是:首页三行,上下定高,中间自适应高度,于是在app.vue的created()中设置事件委托
然后中间那行用的三栏布局,左右定宽中间自适应宽度,再设置一个min-height不免得将中间的轮播弄来没有了,具体见css
细节:其中用data中的scroll,用来显示可以让页面一键划到顶端的按钮,滑动动画代码如下
这里比较坑的地方就是document.documentElement.scrollTop和document.documentElement.scrollTop需要注意
这里给出了brands的样式,也就是说导航栏的home,clot,madness,bape,assc都有这个组件,
这里有一个焦点轮播效果,开始思考的时候没有思路,但是我参照了一下https://segmentfault.com/a/1190000007010410,才有了思路,并完善了它,但是效果还没有预想的好,这个还需要改进,通过translate来改变位置,shufflingIndex来记录当前的index
每个商品被点击时都要改变进入的是哪个商品,changeSelectedItem来完成,这个页面想法来源于1626潮牌网,觉得挺好看的,于是自己写了下来,尤其是mouseover显示的是否喜欢,处理的还是可以,不过chrome和Firefox还是会有闪烁的效果没有处理好
这个组件中重要的就是数量的增减,因为每个商品都有一个对象存储数据,并且加入购物车还需要判断购物车中是否有相同信息的商品,还有点击加入购物车后直接跳转到购物车页面,方法如下
添加到购物车中的方法中,我用try,catch来跳出forEach循环,还有这句state.selectedItem={};如果state.selectedItem是直接引用别的对象,那么另一个对象也会跟着改变,为了避免引用,我用了如下方法
在created(){}中用this.route.params.id来得到进入那个路由,因为这四个brand布局样式什么的大致都一样,然后watch来检测this.route.params.id的改变,以此来getIntro也就是每个brand的数据
组件的介绍大致就是这些
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
这个状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将state映射到视图;
actions,响应在view上的用户输入导致的状态变化。
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
有时候我们需要从 store 中的 state 中派生出一些状态,或用于得到信息
下面罗列了一些收货和本项目的不足
Firefox中不支持 table 的 min-height
CSS 的话 考虑用 normalize.css解决不同浏览器初始样式不一样的问题
css 的命名啥的可以参考一下 BEM 的命名规范
代码组织有点杂乱
vuex只要专心做页面状态管理,尽量不要掺杂页面数据
轮播还需要改进
第一次在gh-pages中显示时,发现图片加载太慢 ,于是我把图片压缩了
在用git上传代码是出过差错,解决了。
最后感谢您能阅读到这里,本人小白,努力学习中,献丑了。
Vue-router2.0中文文档:http://router.vuejs.org/zh-cn/essentials/getting-started.html
Vuex2.0中文文档:http://router.vuejs.org/zh-cn/essentials/getting-started.html
git教程:http://www.liaoxuefeng.com/
github源码地址
首页
如果觉得不错,给github源码点个赞吧QAQ前言
这篇文章是总结自己写项目时的思路,遇到的问题,和学到的东西,本文只截取一部分来讲,源码已奉上,觉得项目还行的点个赞吧,谢谢一、搭建环境
安装vue-clinpm install -g vue-cli
创建webpack项目
vue init webpack vogue cd vogue
安装依赖
npm install
安装vue-router
npm install vue-router --save-dev
安装vuex
npm install vuex --save-dev
运行
npm run dev
二、目录结构
components中是所有页面组件
store中的index.js存放了vuex状态管理的东西,此处本应分成actions.js,mutations.js,getters.js的,可是我试了很多次没成功,还是将他们放在一个文件中,显得有点冗余了,这点失误了,会找原因的
static中存放了图片,图片是压缩了的,网站是https://tinypng.com/,还存放了字体,和一点css,css放在这里有一个原因就是,我想给某个元素设置background时,将style写在static里才行。
dist文件是后来npm run build后生成的,生成的dist中的index.html中的link都是没有加引号的,我自己加上才可以直接运行
三、项目开发
开发过程中,页面是一个一个写的,不过还是要先确定路由,路由嵌套main.js
先说说路由吧,写在了main.js中,直接上图文章开头有首页,home的路径就是‘/home’,这里路由嵌套,用‘:id’来识别,Brands.vue组件在后文中会解释如何得到id,home页的八个导航,分别导向‘/home’,‘/news’,’/collections’,’/shop’,’/home/clot’,’/home/madness’,’/home/bape’,’/home/assc’,购物车导向’/cart’,’login|register’导向‘/login’,’/newsarticle’是在news组件中导向的,‘/shoppingitem’是shop组件中导向的
App.vue
v-for列表渲染的数据如left_navs和contents均来自state
对象迭代
<div v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </div>
如何得到state中的数据
import {mapGetters} from 'vuex' computed:{ ...mapGetters({ show:'getShow', items:'getFootItems', cart:'getCart', brands:'getBrands', left_navs:'getLeft_nav' }) },
在布局上,我的思路是:首页三行,上下定高,中间自适应高度,于是在app.vue的created()中设置事件委托
var self=this; window.onload=()=>{ this.$store.dispatch('change_hw',{ h:document.documentElement.clientHeight||document.body.clientHeight, w:document.documentElement.clientWidth||document.body.clientWidth }) } window.onresize=()=>{ if(self.timer){ clearTimeout(self.timer) } self.timer=setTimeout(function(){ self.$store.dispatch('change_hw',{ h:document.documentElement.clientHeight||document.body.clientHeight, w:document.documentElement.clientWidth||document.body.clientWidth }) },100) } window.onscroll=()=>{ var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; if(scrollTop>10){ this.scroll=true; }else{ this.scroll=false; } } }
然后中间那行用的三栏布局,左右定宽中间自适应宽度,再设置一个min-height不免得将中间的轮播弄来没有了,具体见css
细节:其中用data中的scroll,用来显示可以让页面一键划到顶端的按钮,滑动动画代码如下
scrolltoTop:()=>{ if(document.documentElement.scrollTop){ var scrollTop=document.documentElement.scrollTop var step=scrollTop/30; var now=scrollTop-step; var i=0; var time=setInterval(function(){ i++; if(i>32){ clearInterval(time) } document.documentElement.scrollTop=now; scrollTop=document.documentElement.scrollTop now=scrollTop-step; },10) }else if(document.body.scrollTop){ var scrollTop=document.body.scrollTop var step=scrollTop/30; var now=scrollTop-step; var i=0; var time=setInterval(function(){ i++; if(i>32){ clearInterval(time) } 4000 document.body.scrollTop=now; scrollTop=document.body.scrollTop now=scrollTop-step; },10) } },
这里比较坑的地方就是document.documentElement.scrollTop和document.documentElement.scrollTop需要注意
Home.vue
这里给出了brands的样式,也就是说导航栏的home,clot,madness,bape,assc都有这个组件,
HomeFirst.vue
这里有一个焦点轮播效果,开始思考的时候没有思路,但是我参照了一下https://segmentfault.com/a/1190000007010410,才有了思路,并完善了它,但是效果还没有预想的好,这个还需要改进,通过translate来改变位置,shufflingIndex来记录当前的index
methods:{ caculateIndex(){ //计算上一个元素和下一个元素的index this.preIndex = this.shufflingIndex - 1 < 1 ? 4: this.shufflingIndex - 1; this.nextIndex = this.shufflingIndex + 1 > 4 ? 1 : this.shufflingIndex + 1; }, autoScroll(){ var self=this this.clear() this.openNext=false; this.openPre=true; this.interval_timer=setInterval(self.autoChange,2000) }, autoChange(){ if(this.shufflingIndex == 4){ this.shufflingIndex = 1; }else{ this.shufflingIndex++; } this.caculateIndex(); }, //向前面移动 click_pre(){ if(this.timeout_timer){ clearTimeout(this.timeout_timer) } var self=this; self.openNext=false; self.openPre=true; this.timeout_timer=setTimeout(function(){ self.autoChange(); },300) }, //向后面移动 click_next(){ if(this.timeout_timer){ clearTimeout(this.timeout_timer) } var self=this; self.openNext=true; self.openPre=false; this.timeout_timer=setTimeout(function(){ self.shufflingIndex=self.shufflingIndex==1?4:self.shufflingIndex-1 self.caculateIndex() },300) }, clear(){ if(this.interval_timer){ clearInterval(this.interval_timer) } }, round(index){ var self=this //点击圆点,就相当于点多少次左右键 if(this.shufflingIndex<index){ this.openNext=false; this.openPre=true; this.interval_timer=setInterval(function(){ if(self.shufflingIndex==index){ self.clear() }else{ self.shufflingIndex++; self.caculateIndex(); } //必须要用if,else来clear },200) }else if(this.shufflingIndex>index){ this.openNext=true; this.openPre=false; this.interval_timer=setInterval(function(){ if(self.shufflingIndex==index){ self.clear() }else{ self.shufflingIndex--; self.caculateIndex(); } //必须要用if,else来clear },200) } } }, created(){ this.$store.dispatch('changeShow','home') this.caculateIndex(); this.autoScroll(); }
Shop.vue
methods:{ changeLike(index){ this.$store.dispatch('changeLike',index)//改变是否喜欢 }, changeFlagTrue(index){ this.$store.dispatch('changeFlagTrue',index)//改变是否显示喜欢 }, changeFlagFalse(index){ this.$store.dispatch('changeFlagFalse',index)//改变是否显示喜欢 }, changeSelectedItem(index){ this.$store.dispatch('changeSelectedItem',index)//改变进入商品 } }
每个商品被点击时都要改变进入的是哪个商品,changeSelectedItem来完成,这个页面想法来源于1626潮牌网,觉得挺好看的,于是自己写了下来,尤其是mouseover显示的是否喜欢,处理的还是可以,不过chrome和Firefox还是会有闪烁的效果没有处理好
shoppingitem.vue
这个组件中重要的就是数量的增减,因为每个商品都有一个对象存储数据,并且加入购物车还需要判断购物车中是否有相同信息的商品,还有点击加入购物车后直接跳转到购物车页面,方法如下
methods:{ changeSize(index){ this.$store.dispatch('changeSize',index) }, changeColor(num){ this.$store.dispatch('changeColor',num) }, changeNumSub(){ if(this.item.num>1){ this.$store.dispatch('changeNumSub') } }, changeNumAdd(){ if(this.item.num<8){ this.$store.dispatch('changeNumAdd') } }, addToCart(){ if(!!this.item.color&&!!this.item.size){ this.$store.dispatch('addToCart') } } } *index.js中的方法如下* ADD_TO_CART(state){ var cart=state.cart; var thing=mutations.clone(state.selectedItem); //查看购物车是否已经有相同的商品,信息都一样 if(!cart.length){ cart.push(thing) }else{ var flag=cart.some(function(e){ return e.color==thing.color&&e.size==thing.size&&e.src==thing.src }) try{ if(!flag){ cart.push(thing); throw new Error("can't find") } cart.forEach(function(e,index){ if(e.color==thing.color&&e.size==thing.size&&e.src==thing.src){ cart[index].num+=thing.num; foreach.break=new Error("StopIteration"); } }) }catch(e){ //用于跳出循环 } } state.selectedItem={}; },
添加到购物车中的方法中,我用try,catch来跳出forEach循环,还有这句state.selectedItem={};如果state.selectedItem是直接引用别的对象,那么另一个对象也会跟着改变,为了避免引用,我用了如下方法
//js复制对象 clone(myObj){ if(typeof(myObj) != 'object') return myObj; if(myObj == null) return myObj; var myNewObj = new Object(); for(var i in myObj) myNewObj[i] = mutations.clone(myObj[i]); return myNewObj; },
Brands.vue
在created(){}中用this.route.params.id来得到进入那个路由,因为这四个brand布局样式什么的大致都一样,然后watch来检测this.route.params.id的改变,以此来getIntro也就是每个brand的数据
组件的介绍大致就是这些
四、Vuex
我在vuex这里没有做好,状态和数据应该分开,而且actions,mutations,getters,state,应该分开,不然太冗余了Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
这个状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将state映射到视图;
actions,响应在view上的用户输入导致的状态变化。
index.js中的state
大概罗列一点const state={ loginway:'', show:'home', clientheight:0, clientwidth:0, footItems:[ {title:'ABOUT US',contents:{content_1:'contact us',content_2:'about vogue'}}, {title:'SERVICE',contents:{content_1:'payment methods',content_2:'track order'}}, {title:'POLICY',contents:{content_1:'privacy policy',content_2:'terms & condition'}}, {title:'FOLLOW US',contents:{content_1:'Facebook',content_2:'Instagram'}}, ], left_nav:{ home:'home', news:'news', collections:'collections', shop:'shop' }, ]
index.js中的mutations
const mutations={ CHANGE_HW(state,obj){ state.clientwidth=obj.w; state.clientheight=obj.h; }, CHANGE_SHOW(state,type){ state.show=type }, CHANGE_NOWBRAND(state,type){ state.nowbrand=type+'Intro' }, CHANGE_LIKE(state,index){ state.goods[index].isLike=!state.goods[index].isLike; if(!state.goods[index].isLike){ state.goods[index].likes+=1 }else{ state.goods[index].likes-=1 } }, ]
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
index.js中的actions
const actions={ change_hw({commit},obj){ commit('CHANGE_HW',obj) }, changeShow({commit},type){ commit('CHANGE_SHOW',type) }, changeNowbrand({commit},type){ commit('CHANGE_NOWBRAND',type) }, changeLike({commit},index){ commit('CHANGE_LIKE',index) }, ]
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
index.js中的getters
const getters={ getHW:function(state){ return { h:state.clientheight, w:state.clientwidth } }, getBrands:function(state){ return state.brandsArr }, getLeft_nav:function(state){ return state.left_nav }, getShow:function(state){ return state.show } ]
有时候我们需要从 store 中的 state 中派生出一些状态,或用于得到信息
五、总结
自己写的这个项目,蛮有收获的,遇到了问题到处问,都解决的差不多了,下面罗列了一些收货和本项目的不足
Firefox中不支持 table 的 min-height
CSS 的话 考虑用 normalize.css解决不同浏览器初始样式不一样的问题
css 的命名啥的可以参考一下 BEM 的命名规范
代码组织有点杂乱
vuex只要专心做页面状态管理,尽量不要掺杂页面数据
<input type="checkbox" @change="selectAll" id="selectAll" v-model="isAll"/>此处的isAll是从state中get到得数据,可以被改变,我自己尝试得到的这个结论
轮播还需要改进
第一次在gh-pages中显示时,发现图片加载太慢 ,于是我把图片压缩了
在用git上传代码是出过差错,解决了。
最后感谢您能阅读到这里,本人小白,努力学习中,献丑了。
参考资料
Vue2.0中文文档:https://cn.vuejs.org/Vue-router2.0中文文档:http://router.vuejs.org/zh-cn/essentials/getting-started.html
Vuex2.0中文文档:http://router.vuejs.org/zh-cn/essentials/getting-started.html
git教程:http://www.liaoxuefeng.com/
相关文章推荐
- 一个vue2.0+vuex+vue-router搭建的单页潮流购物网站
- 一个vue2.0+vuex+vue-router搭建的单页潮流购物网站
- 一个比较全的搭建java环境的英文下载网站
- 使用zend framework 搭建网站(六)--为Zend_Session 添加一个Memcache_ SaveHandler
- 搭建一个ASP网站过程(Dreamwaver+Win7+IIS7)(学习笔记)
- 通过一个简单的文章系统学习MVC3+Linq搭建网站--项目文件结构介绍(3)
- 通过一个简单的文章系统学习MVC3+Linq搭建网站(1)
- 【SD2.0大会】讲师范路:我技术不行,用RoR搭建一个网站用两天
- 使用zend framework 搭建网站(六)--为Zend_Session 添加一个Memcac
- 『phphot』【SD2.0大会】讲师范路:我技术不行,用RoR搭建一个网站用两天
- 分享一个很好玩的购物网站:立即购
- FreeBSD搭建一个大型网站架构的实验环境
- 搭建一个大型网站架构的实验环境(FreeBsd+Nginx+Squid+Apache)
- 搭建一个大型网站架构的实验环境(Nginx代理服务器篇)
- 要用asp.net和sql server做一个购物网站,如何实现购物车功能啊?
- 搭建一个ASP网站过程(Dreamwaver+Win7+IIS8)(学习笔记)
- 搭建一个大型网站架构的实验环境(FreeBsd+Nginx+Squid+Apache)
- 网站SEO技巧:搭建一个强壮的内部结构设计
- 搭建一个大型网站架构的实验环境(Squid缓存服务器篇)
- 网站SEO技巧:搭建一个强壮的内部结构设计