Project demo address
github source address
Home
I feel good, to my github source point of a praise it QAQ
Foreword
This article is a summary of their own ideas when writing the project, problems encountered, and what I've learned, this is only part of the interception is concerned, the source code has been served, that the point of a project okay praise it, thank you
First, set up environment
Installation vue-cli
npm install -g vue-cli
Creating webpack project
vue init webpack vogue
cd vogue
Installation depends
npm install
Installation vue-router
npm install vue-router --save-dev
Installation vuex
npm install vuex --save-dev
run
npm run dev
Second, the directory structure
components are all page components
The index.js store to store things vuex state management, where this should be divided into actions.js, mutations.js, getters.js, but I tried many times without success, or put them in a file, It seemed a bit redundant, and this mistake will be to find a cause of
stored in a static picture, the picture is compressed, the site is https://tinypng.com/ time, also holds the font, and a little css, css is placed here for a reason, I want to set the background of an element , written in the style static in the job.
dist file is then generated after npm run build, dist generated index.html in the link are not quoted, plus I can directly run
Third, project development
The development process, a page is written, but the thing is to determine the routing, routing nesting
main.js
First talk about the routing of it, written in the main.js in directly on the map
Beginning of the article there are home, home is the path '/ home', where the route nest with ': id' to identify, Brands.vue components later will explain how to get the eight navigation id, home pages, respectively oriented ' / home ',' / news', '/ collections',' / shop ',' / home / clot ',' / home / madness', '/ home / bape', '/ home / assc', cart-oriented '/ cart', 'login | register' guide '/ login', '/ newsarticle' is oriented in the news component, '/ shoppingitem' shop assembly is guided
App.vue
v-for list of rendering data such as left_navs from state and contents are
subject iteration
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</div>
How to get the data in the state
import {mapGetters} from 'vuex'
computed:{
...mapGetters({
show:'getShow',
items:'getFootItems',
cart:'getCart',
brands:'getBrands',
left_navs:'getLeft_nav'
})
},
On the layout, my idea is: First three lines, set the upper and lower high, middle highly adaptive, then set the event delegate in app.vue's 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;
}
}
}
Then the middle of the line with a three-column layout, around a fixed width adaptive intermediate width, then set a min-height lest not to stir up the intermediate wheel there is no particular see css
Details: wherein Scroll with the data, to display a page that allows a designated key to the top of the button, as the slide animation code
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)
}
},
Comparison of the pit is the place to note that document.documentElement.scrollTop and document.documentElement.scrollTop
Home.vue
Here are brands of style, that is home navigation bar, clot, madness, bape, assc have this component,
HomeFirst.vue
No. 2.21 Modify
again changed under the carousel, to achieve unlimited carousel by changing the left, the following ideas:
<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>
A total of four images, plus a before and after, become six, when the scroll back to fifth, index of 4, the next scroll, scroll to jump immediately after the end of the sixth second, index still 3. Slide forward the same reason
methods as follows
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')
}
}
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)//改变进入商品
}
}
Each product must be changed which click into the commodity, changeSelectedItem to complete, this idea comes from page 1626 Tide brand network, I feel very good to see, then wrote down, especially if you like mouseover display, processing still can, but there will still be flashing chrome and Firefox did not deal with the effect of
shoppingitem.vue
The important thing is the number of components increase or decrease, because each item has an object to store data, and ADD TO CART also need to determine whether there is the same information in their shopping carts, and jump directly to click Add to Cart shopping cart page, as follows
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')
}
}
}
The method is as follows 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={};
},
Add to shopping cart approach, I try, catch forEach to jump out of circulation , as well as the phrase state.selectedItem = {}; if state.selectedItem is a direct reference to another object, another object will also change, In order to avoid quoted, I use the following method
//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
In created () {} with this. $ Route.params.id to obtain access to that route because four brand what layout styles are substantially the same, and then watch to detect this. $ Route.params.id of change, in order to getIntro that is, data for each brand of
Introduction of these components is roughly
Four, Vuex
I did not do a good job here in vuex, status, and data should be separated, and actions, mutations, getters, state, should be separated, or too redundant the
Vuex is a specially developed for Vue.js application state management. It uses the status of all components centralized storage management application, and a corresponding state rules to ensure a predictable manner changed. Vuex Vue is also integrated into the official commissioning tool devtools extension, provides a time-travel, such as zero-configuration debugging, a snapshot of the state of import and export and other advanced debugging features.
This state from the management application includes the following sections:
state, driving the application data source;
view, declaratively mapped to the view state;
Actions, a user input in response to a state change caused on the view.
The state index.js
Probably a little list
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 of 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
}
},
]
The only way to change Vuex the store is in a state of submission mutation. Vuex of mutations is very similar to: Event Type (type) of each mutation has a string and a callback function (handler). The callback function is where we actually change the status, and it will accept the state as the first parameter:
The actions index.js
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 similar mutation, except that:
Action is submitted mutation, rather than directly change state.
Action can contain any asynchronous operation.
index.js in 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
}
]
Sometimes we need to derive from the store in the state in some states, or to get information
V. Summary
Write your own project, quite the harvest, has encountered a problem and asked everywhere, are almost resolved,
the following lists some of the deficiencies and receipt of the project
Firefox not supported in the min-height table
CSS, then consider using a different browser normalize.css solve the initial problem is not the same style
css named Han can refer to the naming convention BEM
A little messy code organization
vuex just concentrate on doing page state management, try not doped page data
<Input type = "checkbox" @ change = "selectAll" id = "selectAll" v-model = "isAll" /> isAll here is to get to the data obtained from the state can be changed, I try to get this in conclusion
Carousel also needs to be improved
The first display in gh-pages found image loading is too slow, so I put a picture compression
With git upload code made a mistake, resolved.
Finally, thank you to read here, I am white, to study in incompetence.
Reference material
Vue2.0 Chinese document: https://cn.vuejs.org/
Vue-router2.0 Chinese document: HTTP: //router.vuejs.org/zh-cn ...
Vuex2.0 Chinese document: HTTP: //router.vuejs.org/zh-cn ...
git tutorials: http://www.liaoxuefeng.com/