知识点:
- IScroll 实现拖动下滑效果
- lazyload实现懒加载效果
- Vuex 的使用
- 加入购物车,购物车的数量加减
商品页面 goods/Index.vue组件
显示所有商品列表,用 IScroll 实现拖动下滑效果, 用 lazyload 实现懒加载效果
<template>
<div class="box" @touchmove.prevent>
<ul >
<li> goods {{type}} </li>
<li is="Item" v-for="item of arr" :key="item._id" :item="item"></li>
</ul>
</div>
</template>
<script>
import Item from "./Item.vue"
import { host } from "../../const"
import IScroll from 'iscroll'
import lazy from '../../directives/lazyload'
export default {
data(){
return {
type : "没有分类",
arr : []
}
},
components:{
Item
},
mounted(){
// 通过$emit事件在子组件中自定义事件,通过操作子组件中的事件,向父组件传递参数;
this.$eventbus.$emit("setTitle", "商品")
this.type = this.$route.params.type;
let url = host+"/goods?_type=_type&_word="+this.type+"&_limit=10&_page=1";
this.$axios.get(url).then(res=>{
this.arr = res.data.result;
})
var that = this;
var boxH = document.querySelector(".box").offsetHeight;
var myIScroll;
setTimeout(function(){
myIScroll = new IScroll(".box");
myIScroll.on('scrollEnd', function () {
if( this.y*-1 == document.querySelector(".box>ul").offsetHeight-document.querySelector(".box").offsetHeight ){
//console.log('到底啦')
}else if( this.y == 0 ){
//console.log('到头啦')
}else{
//console.log(this.y)
}
lazy.show( boxH, this.y );
})
lazy.show( boxH, 0 );
}, 1000)
}
}
</script>
<style lang="scss">
.box{
overflow: hidden;
}
.box>ul{
background: #b6e4c5
}
</style>
商品详情页面组件 goods/Detail.vue
<template>
<div class="detail">
<h1>{{ title }}</h1>
<img :src="img">
<div v-html="content"></div>
</div>
</template>
<script>
import { host } from "../../const";
export default {
data(){
return {
title: "",
img: "",
content: ""
}
},
props:[],
mounted(){
let { id } = this.$route.query;
let url = host+"/goods?_type=_id&_word="+id;
this.$axios.get(url).then(res=>{
var obj = res.data.result[0];
this.title = obj.title;
this.img = host+"/uploads/"+obj.img;
this.content = obj.content;
})
}
}
</script>
<style lang="scss">
.detail{
}
.detail h1{
font-size: 14px;
}
.detail img{
width:200px;
}
</style>
商品列表页 goods/Item组件
实现点击加入购物车功能
<template>
<li class="item">
<router-link :to="'/detail?id='+item._id">
<img :src="initimg" v-lazyload="host+'/uploads/'+item.img"><br>
{{ item.title }}
{{ item.price | money("元") }}
查看详情
</router-link>
//在商品列表页添加一个按钮,点击时添加一个事件add();
<button @click="add(item)"><font class="fa fa-shopping-cart"></font>添加到购物车</button>
</li>
</template>
<script>
import { host } from "../../const";
import { mapActions } from "vuex";
import timg from "../../assets/images/timg.gif";
var f = {
filters:{
money( val, d ){
return val+d;
}
}
}
export default {
data(){
return {
host:host,
initimg:timg//"/src/assets/images/timg.gif"
}
},
props:["item"],
mixins:[f],
mounted(){
//console.log( host )
},
methods:{
add(item){
//console.log( 'item:', item )
// vue希望我们在组件中,调用actions中的方法,actions中再调用mutation中的方法,mutation中改变state数据
//this.$store.commit("addCart", item);// 用commit调用vuex中mutations中的方法
//this.$store.dispatch("addCart", item);// 用dispatch调用vuex中actions中的方法
item.n = 1;
this.addCart(item); // 先用map把actions中的addCart函数合并到methods中,然后调用它
this.$toast("商品添加成功")
},
...mapActions(["addCart"])
}
}
</script>
<style lang="scss">
.item{
padding-bottom: 20px;
}
.item img{
width: 2rem;
height: 2rem;
border: 1px solid gray;
border-radius: 5px;
}
</style>
购物车页面 buycar/Index.vue 组件
<template>
<div class="buycar" @touchmove.prevent>
<ul>
<li v-for="(item, ind) of goodslist" :key="ind">
<img :src="host+'/uploads/'+item.img" />
{{ item.title }}
<button @click="update(item, -1)"><font class="fa fa-minus-square-o"></font></button>
{{ item.num }}
<button @click="update(item, 1)"><font class="fa fa-plus-square-o"></font></button>
</li>
</ul>
</div>
</template>
<script>
import { host } from '../../const';
import IScroll from 'iscroll'
import { mapActions } from 'vuex';
export default {
data(){
return {
host : ""
}
},
computed:{
goodslist(){
// 获取 store 中的 state 中的 goodslist 数据
return this.$store.state.goodslist;
}
},
methods:{
update(item, n){
item.n = n; // 决定是+1还是-1
this.addCart(item);
},
...mapActions(["addCart"])
},
mounted(){
this.$eventbus.$emit("setTitle", "购物车");
this.host = host;
var myIScroll;
setTimeout(function(){
myIScroll = new IScroll(".buycar");
}, 0)
}
}
</script>
<style lang="scss">
.buycar{
overflow: hidden;
}
.buycar>ul{
background: #b6e4c5
}
.buycar img{
width:3rem;
height:3rem;
}
</style>
Vuex 仓库 store/index.js
import Vue from 'vue';
import Vuex from 'vuex'; // npm i vuex
Vue.use(Vuex);
// vuex 状态管理
// 创建一个仓库,作用是存储那些被共享出来的数据(数据就是状态)
const store = new Vuex.Store({
state:{
goodslist : JSON.parse(localStorage.getItem("goodslist")||"[]") // 保存那些添加到购物车中的商品
},
mutations:{
// 只是做最后一个state的改变
addCart(state, payload){
// state 表示 store 中的 state,可以直接操作
// payload 表示有效载荷,表示别人使用addCart函数时,传进来的数据
state.goodslist.push(payload);
//console.log( '将商品保存到购物车中了 payload:', payload )
},
updateNum(state, payload){
state.goodslist[payload.ind].num += payload.n; // 不会让视图层自动更新
state.goodslist = JSON.parse(JSON.stringify(state.goodslist)); // 让视图自动更新
//console.log( "updateNum:", state.goodslist[payload.ind] )
},
delCart(state, payload){
state.goodslist.splice(payload, 1); //根据下标,删除数组中的成员,然后视图自动更新
//console.log( "delCart:", state.goodslist )
}
},
actions:{
// 所有的业务逻辑的代码,及异步的代码,都应该写在actions中
addCart(context, payload){
// 判断要添加的这个商品,是否已经保存在goodslist中
var ind = context.state.goodslist.findIndex(obj=>obj._id===payload._id);
if( ind > -1 ){
// 如果已经存在,则数量进行变更
if( payload.n == 1 ){
// 如果是加法
context.commit("updateNum", {ind, n:payload.n})
}else{ // 减法
var i = context.state.goodslist[ind].num-1;
if( i == 0 ){
// 删除商品
context.commit("delCart", ind)
}else{
// 数量减少
context.commit("updateNum", {ind, n:payload.n})
}
}
}else{
// 如果不存在,则直接追加
var obj = payload;
obj.num = 1;
context.commit("addCart", obj) // 在actions中调用mutations中的方法
}
}
}
})
// 订阅(监听),只要数据发生变化,则回调函数就会被触发
store.subscribe(function(mutations, state){
localStorage.setItem("goodslist", JSON.stringify(state.goodslist))
})
export default store;
购物车梳理
- store/index.js Vuex 管理页面
const store = new Vuex.Store({
state:{
存储数据
goodslist:[] 保存到购物车的商品数据
},
mutations:{
改变数据的方法,在 mutations 不应该写逻辑代码,异步代码,只写逻辑赋值的代码
addCart() 添加
updateNum() 更新商品数量
delCart() 删除商品
},
actions:{
所有的业务逻辑的代码,及异步的代码,都应该写在actions中
},
});
2. 商品列表页…
4. 购物车页 …