以爲不錯,給個人github源碼點個贊吧QAQhtml
這篇文章是總結本身寫項目時的思路,遇到的問題,和學到的東西,本文只截取一部分來說,源碼已奉上,以爲項目還行的點個贊吧,謝謝vue
安裝vue-clinode
npm install -g vue-cliwebpack
建立webpack項目git
vue init webpack vogue
cd voguegithub
安裝依賴web
npm installvue-router
安裝vue-routervuex
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中,直接上圖
文章開頭有首頁,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
對象迭代
<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) } document.body.scrollTop=now; scrollTop=document.body.scrollTop now=scrollTop-step; },10) } },
這裏比較坑的地方就是document.documentElement.scrollTop和document.documentElement.scrollTop須要注意
這裏給出了brands的樣式,也就是說導航欄的home,clot,madness,bape,assc都有這個組件,
2.21號修改
從新改了下輪播,經過改變left來實現無限輪播,思路以下:
<div class="wrapper-content" :class="{wrapper_trans:isTrans}" :style="{width:originalData.img_width*(originalData.num+2)+'px',height:originalData.img_height+'px',left:-originalData.img_width+'px'}" ref="wrapperContent"> <img class="wrapper-content_img" alt="4" :src="'../static/images/home_4.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> <img class="wrapper-content_img" alt="1" :src="'../static/images/home_1.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> <img class="wrapper-content_img" alt="2" :src="'../static/images/home_2.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> <img class="wrapper-content_img" alt="3" :src="'../static/images/home_3.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> <img class="wrapper-content_img" alt="4" :src="'../static/images/home_4.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> <img class="wrapper-content_img" alt="1" :src="'../static/images/home_1.jpg'" :style="{width:originalData.img_width+'px',height:originalData.img_height+'px'}"/> </div>
共四張圖片,先後再加一張,變成六張,當向後滾動到第五張時,index爲4,下一次滾動,滾動到第六張結束後當即跳到第二張,index依然爲3。向前滑動道理同樣
methods以下
export default { data (){ return { originalData:{ img_width:350, img_height:350, btn_width:40, btn_height:40, num:4, delay:300 }, isTrans:true,//由於到最後一張圖片,index爲1時,須要當即跳到第二張index也爲1的圖片,這個用來是否給出transition index:1, timer:null,//setInterval clickdelay:false//用來防止連續點擊 } }, computed:{ ...mapGetters({ hw:'getHW' }), home_first_width:function(){ return parseInt(this.hw.w)-400; }, home_first_height:function(){ var a= parseInt(this.hw.h)-200 return a<389?389:a }, home_first_height_margin:function(){ return parseInt(this.home_first_height-300)/2 } }, methods:{ next(){ if(this.clickdelay){ return } this.clickdelay=true if(this.index==this.originalData.num){ this.index=1 }else{ this.index+=1 } this.animate(this.originalData.img_width) }, prev(){ if(this.clickdelay){ return } this.clickdelay=true if(this.index==1){ this.index=this.originalData.num }else{ this.index-=1 } this.animate(-this.originalData.img_width) }, animate(offset){ var node=this.$refs.wrapperContent var self=this; var left=parseInt(node.style.left)-offset this.isTrans=true node.style.left=left+'px' setTimeout(function(){ if(left<-(self.originalData.num*self.originalData.img_width)){ self.isTrans=false node.style.left=-self.originalData.img_width+'px' self.clickdelay=false //當到達最後一張圖片時 } if(left>-100){ self.isTrans=false node.style.left=-self.originalData.num*self.originalData.img_width+'px' self.clickdelay=false //當到達第一張圖片時 } },this.originalData.delay) }, play(){ var self=this; this.timer=setInterval(function(){ self.next() },2000) }, stop(){ this.clickdelay=false//用來防止連續點擊 clearInterval(this.timer) this.timer=null }, turnTo(flag){ if(flag==this.index){ return }else{ var offset=(flag-this.index)*this.originalData.img_width this.index=flag this.animate(offset) } } }, mounted(){ /*下面是判斷過渡動畫是否完成*/ var node=this.$refs.wrapperContent var transitions = { 'transition':'transitionend', 'OTransition':'oTransitionEnd', 'MozTransition':'transitionend', 'WebkitTransition':'webkitTransitionEnd' } var self=this for(var t in transitions){ if( node.style[t] !== undefined ){ var transitionEvent=transitions[t]; } } transitionEvent && node.addEventListener(transitionEvent, function() { self.clickdelay=false }); this.play() }, created(){ this.$store.dispatch('changeShow','home') } }
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仍是會有閃爍的效果沒有處理好
這個組件中重要的就是數量的增減,由於每一個商品都有一個對象存儲數據,而且加入購物車還須要判斷購物車中是否有相同信息的商品,還有點擊加入購物車後直接跳轉到購物車頁面,方法以下
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; },
在created(){}中用this.$route.params.id來獲得進入那個路由,由於這四個brand佈局樣式什麼的大體都同樣,而後watch來檢測this.$route.params.id的改變,以此來getIntro也就是每一個brand的數據
組件的介紹大體就是這些
我在vuex這裏沒有作好,狀態和數據應該分開,並且actions,mutations,getters,state,應該分開,否則太冗餘了
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。
這個狀態自管理應用包含如下幾個部分:
state,驅動應用的數據源;
view,以聲明方式將state映射到視圖;
actions,響應在view上的用戶輸入致使的狀態變化。
大概羅列一點
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' }, ]
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 做爲第一個參數:
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 能夠包含任意異步操做。
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...
Vuex2.0中文文檔:http://router.vuejs.org/zh-cn...