我是靠谱客的博主 听话母鸡,最近开发中收集的这篇文章主要介绍vue项目-商城app,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

.gitignore 里面设置上传项目时可以忽略的文件,eg:node_modules

一、制作首页hadder和tabbar

  1. 完成Header区域,使用的的是mint-ui中的Header组件
  2. 制作底部的Tabbar区域,使用的是mui中的Tabbar.html
    - 在制作购物车小图标的时候,先把扩展图标的css样式,拷贝到项目中
    - 再拷贝我们的字体库ttf文件到项目中
    - 为购物车小图标添加图像样式
  3. 要在中间区域放置一个router-view来展示路由匹配的组件

切换页面(改造tabbar为router-link):

  • 在main.js中引入vue-router import VueRouter from "vue-router"
  • 将a标签改为router-link,href改为to
  • 在router.js中引入路由组件
	import VueRouter from 'vue-router'
// 导入对应的路由组件
import HomeContainer from '../components/tabbar/HomeContainer.vue'
import MemberContainer from '../components/tabbar/MemberContainer.vue'
import ShopcarContainer from '../components/tabbar/ShopcarContainer.vue'
import SearchContainer from '../components/tabbar/SearchContainer.vue'
var router = new VueRouter({
routes: [// 配置路由规则
{ path: '/', redirect: '/home' },
{ path: '/home', component: HomeContainer },
{ path: '/member', component: MemberContainer },
{ path: '/shopcar', component: ShopcarContainer },
{ path: '/search', component: SearchContainer }
],
linkActiveClass: 'mui-active' // 覆盖默认的路由高亮的类,默认的类叫做router-link-active
})
export default router
  • 给App.vue中添加一个router-view标签

scss中&符号是交集选择器,不写是后代选择器

二、制作轮播图

  1. 获取数据使用vue-resource

  2. 在main.js中导入vue-rosource

  3. 在main.js中配置请求路径
    Vue.http.options.root = 'http://www.liulongbin.top:3005'

  • 在script中methods中定义方法,获取数据
	<script>
export default {
data () {
return{
lunbotulist:[]
}
},
created() {
this.getlunbotu()
},
methods: {
getlunbotu() {
this.$http.get('api/getlunbo').then(res => {
if(res.body.status === 0) {
this.lunbotulist = res.body.message
}
})
}
}
}
</script>

渲染页面使用v-for循环,在组件中使用v-for时,要使用:key

三、九宫格到六宫格改造工程

  • 使用mui中的组件,将九宫格改造为六宫格
  • 图标可引入自己的图标,修改样式就ok

四、组件切换时的动画效果

用transition将中间内容包起来

	<transition>
<router-view></router-view>
</transition>

设置类

<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(100%);
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}
</style>

问题:

  1. Header栏向右偏移
  2. 底部也会偏移,并且出现滚动条
  3. 要进入的元素先向左然后向上飘

解决:

  • 出现滚动条的原因:因为在切换页面的时候,他的真正宽度是两个页面拼接起来的宽度
    - 给外层container添加一个overflow-x: hidden
	.app-container {
padding-top:40px;
padding-bottom: 50px;
overflow-x: hidden;
}
  • 解决底部滚动条问题

.v-enter {
opacity: 0;
transform: translateX(100%);
}
.v-leave-to {
opacity: 0;
transform: translateX(-100%);
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}
  • 解决元素飘动问题,给.v-leave-to动画加一个定位
	.v-enter {
opacity: 0;
transform: translateX(100%);
}
.v-leave-to {
opacity: 0;
transform: translateX(-100%);
position: absolute;
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}

五、改造新闻资讯的路由连接

  • 将a标签改为router-link,href改为to,to=‘home/newslist’
  • 在router.js导入对应的路由组件

六、新闻资讯页面绘制

  1. 绘制界面,使用mui中的midia-list.html
  2. 使用vue-resource获取数据
  3. 渲染真实数据

给时间定义一个全局过滤器

安装moment npm install moment -S

	import moment from 'moment'
// 导入格式化的时间插件
Vue.filter('dateFormat', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
return moment(dataStr).format(pattern)
})

使用:

	<span>发表时间:{{item.add_time | dateFormat('YYYY-MM-DD')}}</span>

七、点击新闻资讯列表跳转到新闻详情

  1. 把列表中的每一项改造为 router-link,同时在跳转的时候应该提供唯一的id标识符
    <router-link :to="'/home/newsinfo/'+item.id">
  2. 创建新闻详情的组件页面NewsInfo.vue
  3. 在路由模块router.js中,将新闻详情的路由地址和组件页面对应起来
	<script>
export default {
data(){
return {
id: this.$route.params.id, //将url地址中传递过来的id值,挂载到data上,方便以后调用
newsinfo:{}
}
}
}
</script>
  1. 实现新闻详情页面布局和渲染

八、单独封装一个 comment.vue 的评论子组件

  1. 先创建一个单独的comment.vue组件模板

  2. 在需要使用comment组件的页面中,先动手导入comment组件

    import comment from './comment.vue'

  3. 在父组件中,使用components属性。将刚才导入comment组件注册为自己的子组件

	methods: {
getNewsInfo(){//获取新闻详情
this.$http.get('api/getnew/'+this.id).then(res => {
if(res.body.status ===0 ){
this.newsinfo = res.body.message[0];
}else {
Toast('加载失败');
}
})
}
},
components: {// 用来注册子组件
"comment-box": comment
}
  1. 将注册子组件时候的注册名称以标签形式在页面中引用即可

    <comment-box></comment-box>

  2. 获取所有的评论数据显示到页面中getComments()方法

    父组件向子组件传值

    <comment-box :id="this.id"></comment-box>

    props: ['id']

九、点击加载更多评论的功能

  1. 为加载更多按钮绑定点击事件,在事件中,请求下一页数据
	<mt-button type="danger" size="large" plain @click="getMore">加载更多</mt-button>
  1. 点击加载更多,让pageIndex++,然后重新调用this.getComments()方法,重新获取最新一页的数据

  2. 为了防止新数据覆盖老数据的情况,点击加载更多的时候,每当获取到新数据,应该让老数据调用数组concat方法,拼接新数组

	methods:{
getComments(){// 获取评论
this.$http.get('api/getcomments/' + this.id + '?pageindex=' + this.pageIndex).then(res => {
if(res.body.status === 0){
// 获取新评论时不会把老数据清空覆盖
this.comments = this.comments.concat(res.body.message);
}else {
Toast('获取评论失败');
}
})
},
getMore(){// 加载更多
this.pageIndex++;
this.getComments();
}
}

十、发表评论

  1. 把文本框做双向数据绑定v-model='msg'
  2. 为发表按钮绑定一个事件@click="postComment"
  3. 校验评论内容是否为空,如果为空则Toast提示用户
  4. 通过vue-resource发送一个请求,把评论内容提交给服务器并保存
  5. 当发表评论完成后,重新刷新列表,以查看最近的评论
    - 如果调用getComments方法重新刷新评论列表的话,可能只能得到 最后一页的评论,前几页的评论获取不到
    - 换一种思路:当评论成功后,在客户端手动拼接出一个最新的评论对象,然后调用数组的unshift方法,把最新的评论追加到date中comments的开头;这样就能完美实现刷新评论列表的需求

在main.js中全局设置post时候表单数据格式组织形式 application/x-www-form-urlencoded

Vue.http.options.emulateJSON = true


postComment(){// 发表评论
// 校验是否为空内容
if(this.msg.trim().length === 0){
return Toast('评论内容不能为空!');
}
this.$http.post("api/postcomment/" + this.$route.params.id,{content:this.msg.trim()}).then(function(res) {
if(res.body.status === 0){
//拼接出一个评论对象
var cmt = {user_name: '匿名用户', add_time: Date.now(), content: this.msg.trim()};
this.comments.unshift(cmt);
this.msg = "";
}
})
}

十一、制作图片分享页面

  1. 改造图片分析按钮为路由的链接并显示对应的组件页面
  2. 绘制图片列表组件页面结构并美化样式
    - 制作顶部的滑动条
    - 制作底部的图片列表
  3. 获取所有分类,并渲染分类列表

制作顶部滑动条的坑

另有博客专门介绍这部分内容:vue在引用mui.js文件时会遇到的各种问题

  1. 使用MUI中的tab-top-webview-main.html
  2. 需要把slider区域的mui-fullscreen类去掉
  3. 滑动条无法正常触发滑动,通过检查官方文档,发现这是JS组件,需要被初始化一下
    - 导入 mui.js
    - 调用官方提供的方式去初始化:
mui('.mui-scroll-wrapper').scroll({
deceleration: 0.0005 //flick 减速系数,系数越大,滚动速度越慢,滚动距离越小,默认值0.0006
});
  1. 我们在初始化滑动条的时候,导入的mui.js ,但是控制台报错: Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode
    - mui.js 中用到了’caller’,‘callee’,and’arguments’,但是webpack打包好的bundle.js 中,默认是启用严格模式的,所以这两者冲突了
    - 解决方案:
    a. 把mui.js中的非严格模式的代码改掉,但是不现实
    b. 把webpack打包时候的严格模式禁用掉
    - 最终,我们选择了plan B移除严格模式:使用这个插件babel-plugin-transform-remove-strict-mode
  2. 刚进入图片分享页面的时候滑动条无法正常工作,然后发现如果要初始化滑动条,必须要等DOM元素加载完毕,所以我们把初始化滑动条的代码,搬到了mounted生命周期函数中
  3. 当滑动条调试OK后,发现tabbar无法正常工作了,这时需要把每个tabbar按钮的样式中mui-tab-item重新改一下名字,并且复制其样式

十二、制作图片列表区域

  1. 图片列表需要使用懒加载技术,使用Mint-UI提供的现成的组件lazy-load
  2. 渲染图片列表数据
  3. 实现了点击图片跳转到图片详情页面
  4. 实现详情页面的布局和美化,同时获取数据渲染页面
  5. 实现图片详情中缩略图的功能
    - 使用插件vue-preview这个缩略图插件
    安装 npm i vue-preview -S
    直接使用标签 <vue-preview :slides="list"></vue-preview>
    - 获取到所有的图片列表
    - 每个图片数据对象中,必须有w和h属性

十三、完成商品列表页面

  • 绘制商品列表页面
  • 实现商品列表的经典两列布局
	.good-list {
display: flex;
flex-wrap: wrap;
padding: 7px;
justify-content: space-between;
.goods-item {
padding: 2px;
width: 49%;
border: 1px solid #ccc;
box-shadow: 0 0 8px #ccc;
margin: 4px 0;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 293px;
img {
width: 100%;
}
.title {
font-size: 14px;
}
.info {
background-color: #ddd;
p {
margin: 0;
padding: 5px;
}
.price {
.now {
color: red;
font-weight: bold;
font-size: 16px;
}
.old {
text-decoration: line-through;
font-size: 12px;
margin-left: 10px;
}
}
.sell {
display: flex;
justify-content: space-between;
}
}
}
}
  • 加载商品列表中的数据并实现加载更多

十四、商品详情页面

  • 改造路由链接,绘制商品详情页面并美化
  • 使用编程式导航,传递对象

goDesc(id) {
this.$router.push({name: 'goodsdesc', params: {id}})
},
goComment(id) {
this.$router.push({name: 'goodscomment', params: {id}})
}
  • 绘制商品购买区域样式
  • 使用编程式导航实现图文介绍和商品评论跳转
  • 完成商品详情中的图文介绍和评论页面的渲染

十五、加入购物车的小球动画

  • 绘制小球,添加样式

.ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: red;
position: absolute;
z-index: 99;
top: 390px;
left: 146px;
}
  • 小球动画

<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="ballFlag" ref="ball"></div>
</transition>

beforeEnter(el) {
el.style.transform = 'translate(0,0)'
},
enter(el,done) {
//先得到徽标的横纵坐标,再得到小球的横纵坐标
//然后让 y 值求差, x 值也求差,得到的结果,就是横纵坐标要位移的距离
el.offsetWidth;
//获取小球在页面上的位置
const ballPosition = this.$refs.ball.getBoundingClientRect();
//获取徽标在页面上的位置
const badgePosition = document.getElementById('badge').getBoundingClientRect();
const xDist = badgePosition.left - ballPosition.left;
const yDist = badgePosition.top - ballPosition.top;
el.style.transform = `translate(${xDist}px,${yDist}px)`;
el.style.transition = 'all 0.5s cubic-bezier(.4,-0.3,1,.68)';
done()
},
afterEnter(el) {
this.ballFlag = !this.ballFlag
}

十六、加入购物车及购物车页面的数量传递问题

如何实现加入购物车时,拿到选择的数量

  • 涉及到子组件向父组件传值(事件调用机制)
  • 事件调用本质:父向子传递方法,子调用这个方法, 同时把数据当作参数传递给这个方法

getSelectedCount(count) {
//当子组件把选中的数量传递给父组件时,把选中的值保存到data上
this.selectedCount = count;
}

<p>购买数量:<numbox @getcount="getSelectedCount" :max="goodsinfo.stock_quantity"></numbox></p>

  • 子组件什么时候把值传给父组件

<input id="test" class="mui-input-numbox" type="number" value="1" @change="countChanged" ref="numbox"/>

	methods: {
countChanged() {
//每当文本框的数据被修改时,立即把最新的数据通过事件调用,传递给父组件
this.$emit("getcount",parseInt(this.$refs.numbox.value));
}
},
props: ["max"], // 设置可加入购物车数量最大值
watch: {
//使用watch监听父组件传递过来的max值
max: function(newVal,oldVal) {
mui(".mui-numbox").numbox().setOption("max",newVal);
}
}

在父组件的getSelectedCount()方法中可以拿到传递过来的值

十七、使用vuex并设计购物车数据存储方式

vuex是什么?怎么用?

将商品对象设计成以下样式

{ id: 商品id, count: 要购买数量, price: 商品价格, selected: false }

  • 在goodsInfo.vue中拼接出一个要保存到store中car数组里的商品信息对象
  • 点击加入购物车,把商品信息保存到store中的car上
    - 如果在购物车中,之前就已经有了这个对应的商品了,那么,只需要更新数据
    - 如果没有,则直接把商品数量push到car中即可

项目源码:商城app源码 vue_app

最后

以上就是听话母鸡为你收集整理的vue项目-商城app的全部内容,希望文章能够帮你解决vue项目-商城app所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部