Vue+Node.js开发Xmall商城——Day2

昨天完成了首页组件的设计。

今天的工作量是第二个导航菜单——全部商品模块,如图:
其中有两个难点,困惑了我很久,
第一个是三种排序方法和价格过滤。
在这里插入图片描述
第二个难点就是每页的商品量是动态划分的。
在这里插入图片描述
这两个切换菜单基本设计很简单,就是Element-UI拷贝到本地的组件。首先从官方拿到了allGoods的接口,分析了一下,唉怪自己太不细心了,以为是无传参的URL,直接把全部29件商品拿到手在前端各种操作,升序排序都是Vue实例里完成了,后来才发现这URL不简单呀!!!

http://localhost:8080/api/goods/allgoods?page=1&size=20&sort=1&priceGt=10&priceLte=1000

可以看到参数还是不少的,经过研究,各参数是这样设计的:

  1. page:当前页数,如第一页、第二页;
  2. size:每页显示商品数量,官网默认是20件;
  3. sort:排序方式,分别有升序、降序和默认排序对应值为1、-1和无参;
  4. priceGt:最低价格
  5. priceLte:最高价格

前端请求是不难的,URL改一下就好,再把这些参数动态渲染到界面上,难就难在处理接口参数的逻辑了。
我的后端是这样写的,一个接口中用到了三个函数,处理了分页、排序以及数组切割。

function sortBy(attr, rev) {
                if (rev === undefined) {
                    rev = 1;
                } else {
                    rev = rev ? 1 : -1;
                }
                return function (a, b) {
                    a = a[attr];
                    b = b[attr];
                    if (a < b) {
                        return rev * -1;
                    }
                    if (a > b) {
                        return rev * 1;
                    }
                    return 0;
                }
            }
            function range(arr, gt, lte) {
                return arr.filter(item => item.salePrice >= gt && item.salePrice <= lte)
            }
            app.get('/api/goods/home', (req, res) => {
                fs.readFile('./db/home.json', 'utf8', (err, data) => {
                    if (!err) {
                        res.json(JSON.parse(data));
                    }
                })
            })
            app.get('/api/goods/allgoods', (req, res) => {
                // 获取的是前端地址栏上的查询参数
                const page = parseInt(req.query.page);
                const size = parseInt(req.query.size);
                const sort = parseInt(req.query.sort);
                const gt = parseInt(req.query.priceGt);
                const lte = parseInt(req.query.priceLte);
                let newData = []
                fs.readFile('./db/allGoods.json', 'utf8', (err, data) => {
                    let { result } = JSON.parse(data);
                    let allData = result.data;
                    // 分页显示
                    newData = pagination(size, page, allData);
                        if (sort === 1) { //价格由低到高
                            newData = newData.sort(sortBy('salePrice', true))
                        } else if (sort === -1) { //价格由高到低
                            newData = newData.sort(sortBy('salePrice', false))
                        }
                        if (gt && lte) {
                            // 过滤 10~1000
                            newData = range(newData, gt, lte)
                        }
                        res.json({
                            data: newData,
                            total: allData.length
                        })
                })
            })

前端请求代码如下:

async getGoods(){
            const res = await this.$http.get(`/api/goods/allgoods?page=${this.currentPage}&size=${this.pageSize}&sort=${this.sort}&priceGt=${this.min}&priceLte=${this.max}`);
            console.log(res);
            this.goodsList = res.data.data;
        },
        listSort(i) {
            this.isIndex = i;
            if(i==0){
                this.sort = '';
                this.getGoods();
            }
            if(i==1){
                this.sort = 1;
                this.getGoods();
            }
            if(i==2){
                this.sort = -1;
                this.getGoods();
            }
        },

而排序方式的切换,实际渲染方式就是通过vue的sort参数绑定接口传参值,从而判断,判断完后请求刷新一下数据就好了!思维方式有问题,这些本就应该在后台处理,可以节省这个Web的很多资源,所以也是吸取教训了。

还有点琐碎时间,写了一下商品详情的组件以及前后端请求交互,这个比较简单,只有一个商品id作为传参返回一个数组就好。

由于昨天的文章提到,每个商品卡片都是一个MallGoods组件,而这个组件在首页中是作为子组件存在,其中存放了props的item,这里面的id就是我们所需要的。

<el-button type="default" size="medium" @click="productDetail(goods.productId)">查看详情</el-button>
//vue中的method
productDetail(id) {
          // 编程式导航
          this.$router.push({
            path: 'goodsDetail',
            query:{
              productId:id
            }
          });
        },

把id传给点击事件,再跳转路由并传递URL参数过去,详情组件我定义了一个goodsDetail组件,把每个商品的id传给该组件后,商品详情的接口也是在这里面请求了,请求如下

methods: {
        async getGoodsDetail() {
            try {
              const res = await this.$http.get(
                `/api/goods/productDet?productId=${this.$route.query.productId}`
              );
              this.product = res.data;
              this.small = this.product.productImageSmall;
              this.big = this.small[0];
            } catch (error) {
              console.log(error);
            }
        },
      },
      created() {
         console.log(this.$route.query.productId);
         this.getGoodsDetail();
      },

后端如下:

 app.get('/api/goods/productDet', (req, res) => {
                // const productId = req.query.productId;
                // console.log(productId);
                fs.readFile('./db/goodsDetail.json', 'utf8', (err, data) => {
                    if (!err) {
                        // let { result } = JSON.parse(data);
                        // let newData = result.find(item => item.productId == productId)
                        res.json(data)
                    }
                })
            })

唉!!!简单的后端对我这种前端刚开启nodejs的小白来说太友好了!!一种很正经的舒适圈好吧…
噢噢别忘了详情信息里也有header和footer的组件,这些直接导入用就好!!
数据明天再渲染…时间太晚了!界面是这样的反正。。。。
在这里插入图片描述
祝大家学习进步,码路一路顺风!!!
共同进步。


版权声明:本文为m0_46995864原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。