本项目GitHub地址:https://github.com/Yue-Shang/shop-app
学做的一个商城项目,后台地址需要另行购买(添加微信coderwhy002购买即可),项目功能正在一步步完善中,商品选择功能和购物车商品删除正在进一步完善会过几天在(三)中写出来并完成git上传,有一些小bug也正在改进中,商城基本功能都有,有做相关项目的小伙伴可以看一下有没有能用到的组件你的项目可以用到,
Date:2020.05.22
vue-app项目知识点总结(一)
vue-app项目知识点总结(三)
十一.跳转到详情页并且携带id
11.1简单实现根据id页面跳转
- 在GoodsListItem页面对页面div进行点击设置
<div class="goods-item" @click="itemClick">
itemClick(){
console.log('跳转到详情页');
this.$router.push('/detail/' + this.goodsItem.iid)
}
- 新建页面
- 配置路由
router/index.js
const Detail = () => import('../views/detail/Detail')
const routes = [
...
{
path:'/detail/:iid',//注意这里路径的写法
component: Detail
},
]
- 详情页接收信息
detail.vue
<template>
<!-- 详情页面-->
<div>
<p>详情页{
{
iid}}</p>
</div>
</template>
<script>
export default {
name: "Detail",
data() {
return {
iid:null
}
},
created() {
this.iid = this.$route.params.iid
console.log(this.iid);
}
}
</script>
效果
11.2详情页添加头部导航封装
- (1)循环出title信息,并横向排列,动态绑定class点击实现颜色切换
Detail.vue
<detail-nav-bar></detail-nav-bar>
...
import DetailNavBar from "./childComps/DetailNavBar";
...
components: {
DetailNavBar},
DetailNavBar.vue(导入NavBar)
<template>
<div class="detail-navbar">
<nav-bar>
<div slot="center" class="title">
<div v-for="(item,index) in title"
class="title-item"
:class="{active: index === isActive}"
@click="titleClick(index)"
>
{
{
item}}
</div>
</div>
</nav-bar>
</div>
</template>
...
data(){
return{
title:['商品','参数','评论','推荐'],
isActive:0
}
},
methods:{
//点击不同导航显示活跃颜色
titleClick(index){
this.isActive = index
}
}
<style scoped>
/*设置让导航栏横向排列,均匀分布不*/
.title{
display: flex;
font-size: 13px;
}
.title-item{
flex: 1;
}
</style>
- (2)添加返回按钮
<div slot="left" @click="backClick"><</div>
点击事件
methods:{
backClick(){
this.$router.back()
}
}
11.3根据id拿详细数据
- 新建一个detail.js来保存详情页的网络请求
import {
request} from './request'
export function getDetail(iid) {
return request({
url:'/detail',
params:{
iid
}
})
}
- 详情页Detail.vue导入请求数据
import {
getDetail} from "network/detail";
...
created() {
...
//2.根据iid请求数据
this.getDetail()
},
methods:{
getDetail(){
getDetail(this.iid).then(res => {
console.log(res);
})
}
}
- 在10.1中用到keep-alive,为了让视图不频繁的销毁创建,但是我们这个详情页里需要点击进入对应的id页面,我们就要把之前上一个视图销毁,所以在keep-alive中,我们加一个
exclude=“Detail”
除detail以外都不进行销毁
11.3.1轮播图
- 拿到请求到的数据中轮播图的数据Detail.vue
data() {
return {
...
topImages:[]
}
},
methods:{
getDetail(){
getDetail(this.iid).then(res => {
// 1.获取顶部轮播图数据
this.topImages = res.result.itemInfo.topImages
})
}
}
- 给详情页建一个子组件文件夹,创建轮播图子组件DetailSwiper.vue
- DetailSwiper.vue
<template>
<swiper class="dswiper">
<swiper-item v-for="(item,index) in topImages" :key="index">
<img :src="item" alt="">
</swiper-item>
</swiper>
</template>
<script>
import {
Swiper, SwiperItem} from 'components/common/swiper'
export default {
name: "DetailSwiper",
components:{
Swiper, SwiperItem
},
//拿到父组件传过来的轮播图数据
props: {
topImages:{
type: Array,
default(){
return []
}
}
}
}
</script>
<style scoped>
.dswiper{
height: 300px;
}
.dswiper img{
padding:0 20% 0 20%;
}
</style>
- 把DetailSwiper.vue导入到详情页Detail.vue上
<detail-swiper :top-images="topImages"/>
...
import DetailSwiper from "./childComps/DetailSwiper";
...
components: {
...,DetailSwiper},
11.3.2商品标题以及销量等信息
- 我们发现整个的详情信息数据太多了,我们就需要抽离组件需要的数据,让一个组件只要面向着一个对象开发开发就可以了
- 原理如下
class Person {
constructor(name,age) {
this.name = name;
this.age = age;
}
}
const p = new Person('smy',16)
- 我们在detail.js中把原数据进行抽离
export class Goods {
constructor(itemInfo,columns,services) {
this.title = itemInfo.title
this.desc = itemInfo.desc
this.newPrice = itemInfo.price
this.oldPrice = itemInfo.oldPrice
this.discount = itemInfo.discountDesc
//动态设置颜色
this.discountBgColor = itemInfo.discountBgColor
this.columns = columns
this.services = services
this.realPrice = itemInfo.lowNowPrice
}
}
Detail.vue
import {
..., Goods} from "network/detail";
...
data() {
return {
...
goods: {
}
}
},
methods:{
getDetail(){
getDetail(this.iid).then(res => {
const data = res.result
// 1.获取顶部轮播图数据
this.topImages = data.itemInfo.topImages
//2.获取商品信息
this.goods = new Goods(data.itemInfo,data.columns,data.shopInfo.services)
})
}
}
可以在vuetools里看到拿到了如下数据
- 下面我们来把这一部分单独拿出来写一个组件
<template>
<div v-if="Object.keys(goods).length !== 0" class="base-info">
<div class="info-title">{
{
goods.title}}</div>
<div class="info-price">
<span class="n-price">{
{
goods.newPrice}}</span>
<span class="o-price">{
{
goods.oldPrice}}</span>
<span v-if="goods.discount"
class="discount"
//在这里动态设置背景颜色
:style="{backgroundColor:goods.discountBgColor}"
>{
{
goods.discount}}</span>
</div>
<div class="info-other">
<span>{
{
goods.columns[0]}}</span>
<span>{
{
goods.columns[1]}}</span>
<span>{
{
goods.services[goods.services.length-1].name}}</span>
</div>
<div class="info-service">
<span class="info-service-item" v-for="index in goods.services.length-1" :key="index">
<img :src="goods.services[index-1].icon">
<span>{
{
goods.services[index-1].name}}</span>
</span>
</div>
</div>
</template>
<script>
export default {
name: "DetailBaseInfo",
props:{
goods:{
type:Object,
default() {
return {
}
}
}
}
}
</script>
Detail.vue
<detail-base-info :goods="goods"/>
...
import DetailBaseInfo from "./childComps/DetailBaseInfo";
...
components: {
DetailBaseInfo, ...},
-
v-for="item in 10"
输出1,2,3,4,5,6,7,8,9,10 数字遍历 -
Object.keys(obj).length === 0
判断一个对象是否为空
11.3.3商家信息
detail.js
//商家信息
export class Shop {
constructor(shopInfo) {
this.logo = shopInfo.shopLogo;
this.name = shopInfo.name;
this.fans = shopInfo.cFans;
this.sells = shopInfo.cSells;
this.score = shopInfo.score;
this.goodsCount = shopInfo.cGoods
}
}
DetailShopInfo.vue
<template>
<div class="shop-info">
<div class="shop-top">
<img :src="shop.logo">
<span class="title">{
{
shop.name}}</span>
</div>
<div class="shop-middle">
<div class="shop-middle-item shop-middle-left">
<div class="info-sells">
<div class="sells-count">
{
{
shop.sells | sellCountFilter}}
</div>
<div class="sells-text">总销量</div>
</div>
<div class="info-goods">
<div class="goods-count">
{
{
shop.goodsCount}}
</div>
<div class="goods-text">全部宝贝</div>
</div>
</div>
<div class="shop-middle-item shop-middle-right">
<table>
<tr v-for="(item, index) in shop.score" :key="index">
<td>{
{
item.name}}</td>
<td class="score" :class="{'score-better': item.isBetter}">{
{
item.score}}</td>
<td class="better" :class="{'better-more': item.isBetter}"><span>{
{
item.isBetter ? '高':'低'}}</span></td>
</tr>
</table