shoppe项目15----全部商品

商品分类

  1. 前端需求分析,参照上线项目,所有类别从数据库的category表中加载。
  2. 加载所有类别前端接口
    在App组件中找到’全部商品‘的代码,它是一个el-menu-item节点,点击时触发路由的跳转–>’/goods’–>则创建对应的Goods组件实例。 然后到Goods组件中找交互的代码部分。
    代码如下:
//Goods组件创建完成时,执行
created() {
    // 获取分类列表
    this.getCategory();
  },

//methods中的方法
// 向后端请求商品类别----laufing
getCategory() {
  this.$axios
    .post("/goods/category/getCategory/", {})
    .then(res => {
      // 获取种类的响应
      console.log("@@获取商品所有种类的响应:", res)
      const val = {
        // category_id: 0,
        id: 0, //种类id
        // category_name: "全部"
        cate_name: "全部",//种类名
      };
      const cate = res.data.category;
      cate.unshift(val);
      this.categoryList = cate;
    })
    .catch(err => {
      return Promise.reject(err);
    });
},

组件后续没有销毁,所以此created方法只执行一次
注意后端响应的json中需有category属性,即

{
	code: 200,
	msg: xxxx,
	category: [{id:1, cate_name:'手机'}, {}, {}, ...]
}

然后将category赋值给categoryList数组,供分类标签使用。

  1. 加载所有类别后端接口
    在goods应用中配置路由
# 获取商品的所有类别:
path('category/getCategory/', GetGoodsCategory.as_view()),

 
视图接口

class GetGoodsCategory(APIView):
    def post(self,request):
        """
        查询所有的商品类别
        :param request:
        :return:
        """
        cate = Category.objects.all()
        cate_ser = CategorySer(cate, many=True)
        return Response({"code":200, "msg":"获取类别成功!", "category":cate_ser.data})

  1. 分类数据的Vue前端展示
<!-- 分类标签 -->
<div class="nav">
  <div class="product-nav">
    <div class="title">分类</div>
    <el-tabs v-model="activeName" type="card">
      <el-tab-pane
        v-for="item in categoryList"
        :key="item.id"
        :label="item.cate_name"
        :name="''+item.id"
      />
    </el-tabs>
  </div>
</div>

以上可以展示出所有的分类标签
在这里插入图片描述

前端Vue的数据管理

全部商品这块,会从django后端加载很多的数据,为了数据的使用和管理,Vue使用一些变量来接收并管理这些数据。

data() {
    return {
      categoryList: "", //分类列表, 如[{id:1, cate_name:'手机'},...]
      categoryID: [], // 分类id,表示当前展示的类别,如[5]
      product: [], // 商品列表,内部为每个商品对象
      productList: "", //暂时没用
      total: 0, // 商品总量,用于前端Vue的分页
      pageSize: 15, // 每页显示的商品数量, 前端Vue的分页
      currentPage: 1, //当前页码
      activeName: "-1", // 分类列表 当前选中的类别id,设置有监视属性
      search: "" // 搜索条件,即输入的搜索内容,设置有监视属性
    };
  },

加载商品数据

  1. 前端接口分析
    /goods路由到Goods组件刚刚跳转完成,展示所有商品
    /goods?categoryID=5 跳转到Goods组件完成跳转时,显示对应类别的商品
    具体执行如下:
activated() {//跳转到Goods组件后触发。
    this.activeName = "-1"; // 初始化 分类列表当前选中的id为-1
    this.total = 0; // 初始化商品总量为0
    this.currentPage = 1; //初始化当前页码为1
    
    // 如果路由没有传递参数,默认为显示全部商品,即刚跳转时/goods
    console.log("路由激活:", this.$route.query)
    if (Object.keys(this.$route.query).length == 0) {
      // 这里的路由/goods 没有查询参数
      this.categoryID = [];  //触发监视属性
      this.activeName = "0";// 触发监视属性
      return;
    }
    // 如果路由传递了{categoryID:array(1)},则显示对应的分类商品
    // 如/goods?categoryID=5
    if (this.$route.query.categoryID != undefined) {
      //获取类别id
      this.categoryID = this.$route.query.categoryID;
      if (this.categoryID.length == 1) {
        // 跳转过来时有传递查询参数,改变activeName的值
        this.activeName = "" + this.categoryID[0]; //触发监视属性
      }
      return;
    }
    // 如果路由传递了search,则为搜索,显示对应的分类商品
    if (this.$route.query.search != undefined) {
      console.log("这里是需要搜索商品")
      this.search = this.$route.query.search;//触发search监视属性
    }
  },

第一次跳转/goods时,展示所有的商品(activeName=‘0’&categoryID=[]), 触发如下监视属性对应的函数:

watch: {
    // 监测到activeName的值改变,则执行
    activeName: function(val) {
      console.log("当前activeName:", val, typeof val)
      // 字符串可以与数字比较
      if (val == 0) {
        this.categoryID = []; //显示所有商品
      }
      if (val > 0) {
        this.categoryID = [Number(val)]; //如[5]
      }
      // 初始化商品总量和当前页码
      this.total = 0;
      this.currentPage = 1;
      // 更新地址栏链接,如/goods?categoryID=5
      this.$router.push({
        path: "/goods",
        query: { categoryID: this.categoryID }//值为数组
      });
    },
    
    // 监听分类id,响应相应的商品
    categoryID: function() {
      this.getData(); //加载商品数据
      this.search = "";
    },

activeName(由’‘到’0‘)改变–>触发函数执行,修改categoryID,然后触发getData函数,加载所有商品数据。

// 向后端请求全部商品或指定分类id的商品数据
getData() {
  // 如果categoryID为空则请求全部商品数据,否则请求分类id的商品数据
  const api =
    this.categoryID.length == 0
      ? "/goods/good/getAllProduct/"
      : "/goods/good/getProductByCategory/";
  this.$axios
    .post(api, {
      categoryID: this.categoryID,
      currentPage: this.currentPage,
      pageSize: this.pageSize
    })
    .then(res => {
      console.log("@@获取商品数据的响应:", res)
      this.product = res.data.product;
      this.total = res.data.total;
    })
    .catch(err => {
      return Promise.reject(err);
    });
},

加载所有商品的API:
/goods/good/getAllProduct/
加载指定类别的商品API:
/goods/good/getProductByCategory/

请求方法POST
发送的数据data

{
	categoryID:[]/[5],
	currentPage:1, //当前页的页码
	pageSize:15,  //每页的商品数
}

需要的响应格式:

{
	code:200,
	msg:'获取商品数据成功!',
	product:[{},{},.....],
	total:总商品数
}
  1. 后端视图接口
    2.1 获取全部商品后端接口
    配置路由
#  获取所有商品信息
path('good/getAllProduct/', GetAllGoods.as_view()),

#视图接口
#获取所有商品
class GetAllGoods(APIView):
    def post(self, request):
        goods_query_set = Goods.objects.all()
        goods_ser = GoodsSer(goods_query_set, many=True)

        return Response({"code":200, "msg":"获取所有商品信息成功!",
                         "product": goods_ser.data,
                         "total": goods_query_set.count()
                         })

        2.2 获取指定类别的商品后端接口
        配置路由

#获取指定类别id的商品信息
path('good/getProductByCategory/', GetProductByCategory.as_view()),

#视图接口
## 获取指定类别id的所有商品
class GetProductByCategory(APIView):
    """
        {
          categoryID: this.categoryID,//如[5]
          currentPage: this.currentPage,
          pageSize: this.pageSize
        }
    """
    def post(self,request):
        cate_id = request.data.get('categoryID')[0]
        try:
            category = Category.objects.get(id=cate_id)
        except:
            return Response({"code":204, "msg":"查询的种类不存在!"})
        #通过种类反向查询商品
        goods_query_set = category.goods_set.all()
        goods_ser = GoodsSer(goods_query_set, many=True)
        return Response({"code":200, "msg":"查询指定类别id的商品成功!",
                         'product': goods_ser.data,
                        "total": goods_query_set.count()
                         })

前端展示商品数据

前端接收到响应后,将商品数据保存到product数组中。然后在MyList组件中使用。

<div class="list">
   <MyList :list="product" v-if="product.length>0"></MyList>
    <div v-else class="none-product">抱歉没有找到相关的商品,请看看其他的商品</div>
</div>

商品分页

  1. 后端实现分页
# 加载所有商品视图
class GetAllGoods(APIView):
    def post(self, request):
        #获取前端数据
        current_page = request.data.get("currentPage")
        page_size = request.data.get("pageSize")
        #查询搜索商品
        goods_query_set = Goods.objects.all()
        #对所有商品分页
        paginator = Paginator(goods_query_set, page_size)
        page = paginator.page(current_page)
        #对当前页的所有商品序列化
        goods_ser = GoodsSer(page.object_list, many=True)
        #返回响应
        return Response({"code":200, "msg":"获取所有商品信息成功!",
                         "product": goods_ser.data,
                         "total": goods_query_set.count()
                         })
            
#加载指定类别的商品 同理实现分页
  1. 前端Vue分页
<!-- 分页 -->
<div class="pagination">
  <el-pagination
    background
    layout="prev, pager, next"
    :page-size="pageSize"
    :total="total"
    @current-change="currentChange"
  ></el-pagination>
</div>

//点击页码触发
// 页码变化调用currentChange方法
currentChange(currentPage) {
  this.currentPage = currentPage;
  if (this.search != "") {
    this.getProductBySearch();
  } else {
  	//加载当前页的商品数据
    this.getData();
  }
  this.backtop();
},
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值