.gitignore 里面设置上传项目时可以忽略的文件,eg:node_modules
一、制作首页hadder和tabbar
切换页面(改造tabbar为router-link):
import VueRouter from "vue-router"
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
scss中&符号是交集选择器,不写是后代选择器
二、制作轮播图
获取数据使用vue-resource
在main.js中导入vue-rosource
在main.js中配置请求路径
Vue.http.options.root = 'http://www.liulongbin.top:3005'
渲染页面使用v-for
循环,在组件中使用v-for时,要使用:key
三、九宫格到六宫格改造工程
四、组件切换时的动画效果
用transition将中间内容包起来
设置类
问题:
解决:
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;
}
五、改造新闻资讯的路由连接
六、新闻资讯页面绘制
给时间定义一个全局过滤器
安装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)
})
使用:
发表时间:{{item.add_time | dateFormat('YYYY-MM-DD')}}
七、点击新闻资讯列表跳转到新闻详情
八、单独封装一个 comment.vue 的评论子组件
先创建一个单独的comment.vue组件模板
在需要使用comment组件的页面中,先动手导入comment组件
import comment from './comment.vue'
在父组件中,使用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
}
将注册子组件时候的注册名称以标签形式在页面中引用即可
获取所有的评论数据显示到页面中getComments()
方法
父组件向子组件传值
props: ['id']
九、点击加载更多评论的功能
加载更多
点击加载更多,让pageIndex++,然后重新调用this.getComments()方法,重新获取最新一页的数据
为了防止新数据覆盖老数据的情况,点击加载更多的时候,每当获取到新数据,应该让老数据调用数组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();
}
}
十、发表评论
v-model='msg'
@click="postComment"
在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 = "";
}
})
}
十一、制作图片分享页面
制作顶部滑动条的坑
另有博客专门介绍这部分内容:vue在引用mui.js文件时会遇到的各种问题
tab-top-webview-main.html
mui-fullscreen
类去掉mui('.mui-scroll-wrapper').scroll({
deceleration: 0.0005 //flick 减速系数,系数越大,滚动速度越慢,滚动距离越小,默认值0.0006
});
Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode
babel-plugin-transform-remove-strict-mode
mui-tab-item
重新改一下名字,并且复制其样式十二、制作图片列表区域
lazy-load
安装 npm i vue-preview -S
直接使用标签
十三、完成商品列表页面
.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;
}
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;
}
购买数量:
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 }
项目源码:商城app源码 vue_app