Vue商城项目05(完)
实现购物车效果
用vuex并设计购物车数据存储方式
- 运行 cnpm i vuex -S
- import Vuex from ‘vuex’
- Vue.use(Vuex)
- var store = new Vuex.Store({})
- 在vm实例中挂载 store 状态管理对象 store
点击加入购物车功能
addToShopCar() { // 添加到购物车
this.ballFlag = !this.ballFlag;
// { id:商品的id, count: 要购买的数量, price: 商品的单价,selected: false }
// 拼接出一个,要保存到 store 中 car 数组里的 商品信息对象
var goodsinfo = {
id: this.id,
count: this.selectedCount,
price: this.goodsinfo.sell_price,
selected: true
};
// 调用 store 中的 mutations 来将商品加入购物车
this.$store.commit("addToCar", goodsinfo);
}
购物车处徽标数值的自动更新
<span class="mui-badge" id="badge">{{ $store.getters.getAllCount }}</span> <span class="mui-tab-label">购物车</span>
getters: { // this.$store.getters.*** // 相当于 计算属性,也相当于 filters
getAllCount(state) {
var c = 0;
state.car.forEach(item => {
c += item.count
})
return c
}
}
实现购物车商品的本地持久存储
每次刚进入 网站,肯定会 调用 main.js 在刚调用的时候,先从本地存储中,把 购物车的数据读出来,放到 store 中var car = JSON.parse(localStorage.getItem(\'car\') || \'[]\')
当 更新 car 之后,把 car 数组,存储到 本地的 localStorage 中localStorage.setItem(\'car\', JSON.stringify(state.car))
绘制购物车页面中商品列表的布局
借助于mui-master,examples,card.html。
复制一个基础的组件shopcar_numbox.vue,有选择数量按钮。可以直接加样式style="height:25px;"
改变高度
获取购物车中所有商品列表并加载显示
getGoodsList() { // 1. 获取到 store 中所有的商品的Id,然后拼接出一个 用逗号分隔的 字符串
var idArr = [];
this.$store.state.car.forEach(item => idArr.push(item.id));
// 如果 购物车中没有商品,则直接返回,不需要请求数据接口,否则会报错
if (idArr.length <= 0) {
return;
}
// 获取购物车商品列表。join(",")根据接口文档需要传入的办法,用逗号分隔开传过去
this.$http
.get("api/goods/getshopcarlist/" + idArr.join(","))
.then(result => {
if (result.body.status === 0) {
this.goodslist = result.body.message;
}
});
}
在循环购物车列表时候初始化数量值,购物车商品数量改变同步到store中
main.js里
getters: getGoodsCount(state) {
var o = {}
state.car.forEach(item => {
o[item.id] = item.count
})
return o
}
mutations:
updateGoodsInfo(state, goodsinfo) {
// 修改购物车中商品的数量值
// 分析:
state.car.some(item => {
if (item.id == goodsinfo.id) {
item.count = parseInt(goodsinfo.count)
return true
}
})
// 当修改完商品的数量,把最新的购物车数据,保存到 本地存储中
localStorage.setItem(\'car\', JSON.stringify(state.car))
}
父组件:
<numbox :initcount="$store.getters.getGoodsCount[item.id]" :goodsid="item.id"></numbox> <!-- 问题:如何从购物车中获取商品的数量呢 -->
<!-- 1. 我们可以先创建一个 空对象,然后循环购物车中所有商品的数据, 把 当前循环这条商品的 Id, 作为 对象 的 属性名,count值作为 对象的 属性值,这样,当把所有的商品循环一遍,就会得到一个对象: { 88: 2, 89: 1, 90: 4 } -->
子组件:
<input :value="initcount" /> methods: {
countChanged() {
// 数量改变了
// console.log(this.$refs.numbox.value);
// 每当数量值改变,则立即把最新的数量同步到 购物车的 store 中,覆盖之前的数量值
this.$store.commit("updateGoodsInfo", {
id: this.goodsid,
count: this.$refs.numbox.value
});
}
},
props: ["initcount", "goodsid"]
实现购物车中商品的删除
<a href="#" @click.prevent="remove(item.id, i)">删除</a> <!-- prevent阻止默认事件 -->
remove(id, index) {
// 点击删除,把商品从 store 中根据 传递的 Id 删除,同时,把 当前组件中的 goodslist 中,对应要删除的那个商品,使用 index 来删除
this.goodslist.splice(index, 1); //第一个参数是删除项目的位置,第二个是要删除的项目数量。
this.$store.commit("removeFormCar", id);
}
main.js里的store里的mutations:
removeFormCar(state, id) {
// 根据Id,从store 中的购物车中删除对应的那条商品数据
state.car.some((item, i) => {
if (item.id == id) {
state.car.splice(i, 1)
return true;
}
})
// 将删除完毕后的,最新的购物车数据,同步到 本地存储中
localStorage.setItem(\'car\', JSON.stringify(state.car))
}
绘制结算区域样式
display: flex; //让里面竖着的的盒子一行排放 justify-content: space-between;//两端对齐
align-items: center;//垂直居中
把store中选中的状态同步到页面上,同步商品的勾选状态到store中保存
计算属性是基于响应式依赖进行缓存的,只有数据发生变化时,才会重新计算,否则直接调用缓存
// $store.getters.getGoodsSelected的值为{"88":true}(id为键,值为selected状态) //v-model=true时为打开开关
<mt-switch
v-model="$store.getters.getGoodsSelected[item.id]"
@change="selectedChanged(item.id, $store.getters.getGoodsSelected[item.id])">
</mt-switch>
组件里的方法
selectedChanged(id, val) {
// 每当点击开关,把最新的 快关状态,同步到 store 中
// console.log(id + " --- " + val);
this.$store.commit("updateGoodsSelected", { id, selected: val });
}
main.js里
getters:
getGoodsSelected(state) {
var o = {}
state.car.forEach(item => {
o[item.id] = item.selected
})
return o
}
mutations:
updateGoodsSelected(state, info) {
state.car.some(item => {
if (item.id == info.id) {
item.selected = info.selected
}
})
// 把最新的 所有购物车商品的状态保存到 store 中去
localStorage.setItem(\'car\', JSON.stringify(state.car))
}
实现勾选数量和总价的自动计算
main.js中 getters: getGoodsCountAndAmount(state) {
var o = {
count: 0, // 勾选的数量
amount: 0 // 勾选的总价
}
state.car.forEach(item => {
if (item.selected) {
o.count += item.count
o.amount += item.price * item.count
}
})
return o
}
组件里:
<p>已勾选商品 <span class="red">{{ $store.getters.getGoodsCountAndAmount.count }}</span> 件, 总价 <span class="red">¥{{ $store.getters.getGoodsCountAndAmount.amount }}</span></p>
实现返回按钮的功能
在Mint-ui官网里找,简单修改一下app.vue
<mt-header fixed title="黑马程序员·Vue项目"> <span slot="left" @click="goBack" v-show="flag">
<mt-button icon="back">返回</mt-button>
</span>
</mt-header>
<script>
export default {
data() {
return {
flag: false
};
},
created() {
this.flag = this.$route.path === "/home" ? false : true;
},
methods: {
goBack() {
// 点击后退
this.$router.go(-1);
}
},
watch: { //监听路由的变化
"$route.path": function(newVal) {
if (newVal === "/home") {
this.flag = false;
} else {
this.flag = true;
}
}
}
};
</script>
tomcat虚拟目录
server.xml文件里的<Connector port="80"></Connector>
是打开的端口号80
在Tomcat安装目录下的conf文件夹找到server.xml文件,在结尾处的</Host>
前面加上<Context path="" reloadable="true" docBase="D:\Demo" />
path为浏览器访问目录,docBase项目的虚拟根目录
开启Tomcat服务器,在浏览器访问localhost:80即可看到该目录
项目外网测试
将项目托管到Apache并启用:
先把dist删除,然后webpack打包会放到dist中,把dist中的index.html,bundle.js拷贝到docBase项目的虚拟根目录
注意:如果没有设置虚拟根目录,放在默认的根目录中
输入172.0.0.1:80或者localhost:80即可看到本地
开启Apache的gzip压缩
要让apache支持gzip功能,要用到deflate_Module和headers_Module。打开apache的配置文件httpd.conf,大约在105行左右,找到以下两行内容:(这两行不是连续在一起的)
#LoadModule deflate_module modules/mod_deflate.so#LoadModule headers_module modules/mod_headers.so
然后将其前面的“#”注释删掉,表示开启gzip压缩功能。开启以后还需要进行相关配置。在httpd.conf文件的最后添加以下内容即可:
<IfModule deflate_module> #必须的,就像一个开关一样,告诉apache对传输到浏览器的内容进行压缩
SetOutputFilter DEFLATE
DeflateCompressionLevel 9
</IfModule>
最少需要加上以上内容,才可以生gzip功能生效。由于没有做其它的额外配置,所以其它相关的配置均使用Apache的默认设置。这里说一下参数“DeflateCompressionLevel”,它表示压缩级别,值从1到9,值越大表示压缩的越厉害。
使用ngrok将本机映射为一个外网的Web服务器
打开ngrok.exe,输入ngrok http 80
注意 80 是项目运行的端口号
Session Status online时说明已经上线。其中Forwarding后面的就是地址,直接输入即可。
注意:由于默认使用的美国的服务器进行中间转接,所以访问速度炒鸡慢,访问时可启用f墙软件,提高网页打开速度。
以上是 Vue商城项目05(完) 的全部内容, 来源链接: utcz.com/z/379379.html