摘要:中的非常類似于事件每個(gè)都有一個(gè)字符串的事件類型和一個(gè)回調(diào)函數(shù)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會接受作為第一個(gè)參數(shù)中的類似于,不同在于提交的是,而不是直接變更狀態(tài)。
項(xiàng)目demo地址
github源碼地址
覺得不錯(cuò),給我的github源碼點(diǎn)個(gè)贊吧QAQ
前言這篇文章是總結(jié)自己寫項(xiàng)目時(shí)的思路,遇到的問題,和學(xué)到的東西,本文只截取一部分來講,源碼已奉上,覺得項(xiàng)目還行的點(diǎn)個(gè)贊吧,謝謝
一、搭建環(huán)境安裝vue-cli
npm install -g vue-cli
創(chuàng)建webpack項(xiàng)目
vue init webpack vogue
cd vogue
安裝依賴
npm install
安裝vue-router
npm install vue-router --save-dev
安裝vuex
npm install vuex --save-dev
運(yùn)行
二、目錄結(jié)構(gòu)npm run dev
components中是所有頁面組件
store中的index.js存放了vuex狀態(tài)管理的東西,此處本應(yīng)分成actions.js,mutations.js,getters.js的,可是我試了很多次沒成功,還是將他們放在一個(gè)文件中,顯得有點(diǎn)冗余了,這點(diǎn)失誤了,會找原因的
static中存放了圖片,圖片是壓縮了的,網(wǎng)站是https://tinypng.com/,還存放了字體,和一點(diǎn)css,css放在這里有一個(gè)原因就是,我想給某個(gè)元素設(shè)置background時(shí),將style寫在static里才行。
dist文件是后來npm run build后生成的,生成的dist中的index.html中的link都是沒有加引號的,我自己加上才可以直接運(yùn)行
三、項(xiàng)目開發(fā)開發(fā)過程中,頁面是一個(gè)一個(gè)寫的,不過還是要先確定路由,路由嵌套
main.js先說說路由吧,寫在了main.js中,直接上圖
文章開頭有首頁,home的路徑就是‘/home’,這里路由嵌套,用‘:id’來識別,Brands.vue組件在后文中會解釋如何得到id,home頁的八個(gè)導(dǎo)航,分別導(dǎo)向‘/home’,‘/news’,"/collections","/shop","/home/clot","/home/madness","/home/bape","/home/assc",購物車導(dǎo)向"/cart","login|register"導(dǎo)向‘/login’,"/newsarticle"是在news組件中導(dǎo)向的,‘/shoppingitem’是shop組件中導(dǎo)向的
App.vue
v-for列表渲染的數(shù)據(jù)如left_navs和contents均來自state
對象迭代
{{ index }}. {{ key }} : {{ value }}
如何得到state中的數(shù)據(jù)
import {mapGetters} from "vuex" computed:{ ...mapGetters({ show:"getShow", items:"getFootItems", cart:"getCart", brands:"getBrands", left_navs:"getLeft_nav" }) },
在布局上,我的思路是:首頁三行,上下定高,中間自適應(yīng)高度,于是在app.vue的created()中設(shè)置事件委托
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; } } }
然后中間那行用的三欄布局,左右定寬中間自適應(yīng)寬度,再設(shè)置一個(gè)min-height不免得將中間的輪播弄來沒有了,具體見css
細(xì)節(jié):其中用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需要注意
Home.vue
這里給出了brands的樣式,也就是說導(dǎo)航欄的home,clot,madness,bape,assc都有這個(gè)組件,
2.21號修改
重新改了下輪播,通過改變left來實(shí)現(xiàn)無限輪播,思路如下:
共四張圖片,前后再加一張,變成六張,當(dāng)向后滾動到第五張時(shí),index為4,下一次滾動,滾動到第六張結(jié)束后立即跳到第二張,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,//因?yàn)榈阶詈笠粡垐D片,index為1時(shí),需要立即跳到第二張index也為1的圖片,這個(gè)用來是否給出transition index:1, timer:null,//setInterval clickdelay:false//用來防止連續(xù)點(diǎn)擊 } }, 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 //當(dāng)?shù)竭_(dá)最后一張圖片時(shí) } if(left>-100){ self.isTrans=false node.style.left=-self.originalData.num*self.originalData.img_width+"px" self.clickdelay=false //當(dāng)?shù)竭_(dá)第一張圖片時(shí) } },this.originalData.delay) }, play(){ var self=this; this.timer=setInterval(function(){ self.next() },2000) }, stop(){ this.clickdelay=false//用來防止連續(xù)點(diǎn)擊 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") } }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)//改變進(jìn)入商品 } }
每個(gè)商品被點(diǎn)擊時(shí)都要改變進(jìn)入的是哪個(gè)商品,changeSelectedItem來完成,這個(gè)頁面想法來源于1626潮牌網(wǎng),覺得挺好看的,于是自己寫了下來,尤其是mouseover顯示的是否喜歡,處理的還是可以,不過chrome和Firefox還是會有閃爍的效果沒有處理好
shoppingitem.vue
這個(gè)組件中重要的就是數(shù)量的增減,因?yàn)槊總€(gè)商品都有一個(gè)對象存儲數(shù)據(jù),并且加入購物車還需要判斷購物車中是否有相同信息的商品,還有點(diǎn)擊加入購物車后直接跳轉(zhuǎn)到購物車頁面,方法如下
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); //查看購物車是否已經(jīng)有相同的商品,信息都一樣 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){ //用于跳出循環(huán) } } state.selectedItem={}; },
添加到購物車中的方法中,我用try,catch來跳出forEach循環(huán),還有這句state.selectedItem={};如果state.selectedItem是直接引用別的對象,那么另一個(gè)對象也會跟著改變,為了避免引用,我用了如下方法
//js復(fù)制對象 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來得到進(jìn)入那個(gè)路由,因?yàn)檫@四個(gè)brand布局樣式什么的大致都一樣,然后watch來檢測this.$route.params.id的改變,以此來getIntro也就是每個(gè)brand的數(shù)據(jù)
組件的介紹大致就是這些
四、Vuex我在vuex這里沒有做好,狀態(tài)和數(shù)據(jù)應(yīng)該分開,而且actions,mutations,getters,state,應(yīng)該分開,不然太冗余了
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。Vuex 也集成到 Vue 的官方調(diào)試工具 devtools extension,提供了諸如零配置的 time-travel 調(diào)試、狀態(tài)快照導(dǎo)入導(dǎo)出等高級調(diào)試功能。
這個(gè)狀態(tài)自管理應(yīng)用包含以下幾個(gè)部分:
state,驅(qū)動應(yīng)用的數(shù)據(jù)源;
view,以聲明方式將state映射到視圖;
actions,響應(yīng)在view上的用戶輸入導(dǎo)致的狀態(tài)變化。
大概羅列一點(diǎn)
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 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutations 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會接受 state 作為第一個(gè)參數(shù):
index.js中的actionsconst 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,而不是直接變更狀態(tài)。
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 } ]
有時(shí)候我們需要從 store 中的 state 中派生出一些狀態(tài),或用于得到信息
五、總結(jié)自己寫的這個(gè)項(xiàng)目,蠻有收獲的,遇到了問題到處問,都解決的差不多了,
下面羅列了一些收貨和本項(xiàng)目的不足
Firefox中不支持 table 的 min-height
CSS 的話 考慮用 normalize.css解決不同瀏覽器初始樣式不一樣的問題
css 的命名啥的可以參考一下 BEM 的命名規(guī)范
代碼組織有點(diǎn)雜亂
vuex只要專心做頁面狀態(tài)管理,盡量不要摻雜頁面數(shù)據(jù)
此處的isAll是從state中g(shù)et到得數(shù)據(jù),可以被改變,我自己嘗試得到的這個(gè)結(jié)論
輪播還需要改進(jìn)
第一次在gh-pages中顯示時(shí),發(fā)現(xiàn)圖片加載太慢 ,于是我把圖片壓縮了
在用git上傳代碼是出過差錯(cuò),解決了。
最后感謝您能閱讀到這里,本人小白,努力學(xué)習(xí)中,獻(xiàn)丑了。
參考資料Vue2.0中文文檔:https://cn.vuejs.org/
Vue-router2.0中文文檔:http://router.vuejs.org/zh-cn...
Vuex2.0中文文檔:http://router.vuejs.org/zh-cn...
git教程:http://www.liaoxuefeng.com/
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/50405.html
摘要:中的非常類似于事件每個(gè)都有一個(gè)字符串的事件類型和一個(gè)回調(diào)函數(shù)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會接受作為第一個(gè)參數(shù)中的類似于,不同在于提交的是,而不是直接變更狀態(tài)。 項(xiàng)目demo地址github源碼地址 首頁 覺得不錯(cuò),給我的github源碼點(diǎn)個(gè)贊吧QAQ showImg(https://segmentfault.com/img/bVI3GV?w=1366&h=591...
摘要:適用于主要入口頁面生成多頁,子頁面和次要頁面使用單頁形式的項(xiàng)目。文件用來存放固定的數(shù)據(jù),而文件可更加自由的處理并返回?cái)?shù)據(jù)。 VUE2的單頁應(yīng)用框架有人分享了,多頁應(yīng)用框架也有人分享了,這里分享一個(gè)單頁+多頁的混合應(yīng)用框架吧,node.js寫了一個(gè)簡單的mock服務(wù)也集成在里面,整體初現(xiàn)雛形,還有很多需要優(yōu)化和改善的地方。。。 項(xiàng)目結(jié)構(gòu) │ ├─build ...
摘要:一個(gè)基于全家桶開發(fā)的仿知乎日報(bào)單頁應(yīng)用項(xiàng)目地址源碼地址項(xiàng)目在線地址在線地址模式下推薦使用移動端模式瀏覽去觀看如果覺得做得還不錯(cuò)或者項(xiàng)目源碼對您有幫助希望您小抬右手到右上角點(diǎn)一個(gè)您的支持是作者長期更新維護(hù)的動力項(xiàng)目起源從二月份開始學(xué)習(xí)學(xué)習(xí)了 Vue-News 一個(gè)基于vue全家桶開發(fā)的仿知乎日報(bào)單頁應(yīng)用 項(xiàng)目github地址:源碼地址 項(xiàng)目在線地址:在線地址 (PC模式下推薦使用chro...
摘要:五六月份推薦集合查看最新的請點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...
閱讀 2082·2021-11-24 09:39
閱讀 1536·2021-10-11 10:59
閱讀 2489·2021-09-24 10:28
閱讀 3368·2021-09-08 09:45
閱讀 1263·2021-09-07 10:06
閱讀 1657·2019-08-30 15:53
閱讀 2056·2019-08-30 15:53
閱讀 1411·2019-08-30 15:53