乐优商城(十九)——搜索微服务

 

目录

三、搜索页面分页

3.1 如何生成分页条

3.1.1 需要的数据

3.1.2 后台提供数据

3.1.3 页面计算分页条

3.2 点击分页事件处理

3.3 页面顶部分页条

3.4 页面跳转

四、排序

4.1 页面搜索排序条件

4.2 后台添加排序逻辑

4.3 问题解决


三、搜索页面分页

3.1 如何生成分页条

3.1.1 需要的数据

分页数据应该是根据总页数当前页总条数等信息来计算得出。

  • 当前页:肯定是由页面来决定的,点击按钮会切换到对应的页

  • 总页数:需要后台传递给我们

  • 总条数:需要后台传递给我们

首先在data中记录下这几个值:page-当前页,total-总条数,totalPage-总页数

因为page是搜索条件之一,所以记录在search中。

要注意:在created钩子函数中,会读取url路径的参数,然后赋值给search。如果是第一次请求页面,page是不存在的。因此为了避免page被覆盖,需要做以下修改:

3.1.2 后台提供数据

后台返回的结果中已经包含了所需的数据:total和totalPage。

3.1.3 页面计算分页条

思路分析:

  • 最多有5个按钮,因此可以用v-for循环从1到5即可

  • 但是分页条不一定是从1开始:

    • 如果当前页值小于等于3的时候,分页条位置从1开始到5结束

    • 如果总页数小于等于5的时候,分页条位置从1开始到5结束

    • 如果当前页码大于3,应该从page-3开始

    • 但是如果当前页码大于totalPage-3,应该从totalPage-5开始

所以,页面这样来做:

a标签中的分页数字通过index函数来计算,需要把i传递过去:

需要注意的是,如果总页数不足5页,就不应该遍历1~5,而是1~总页数 :

分页的其他部分:

<div class="sui-pagination pagination-large">
    <ul style="width: 550px">
        <li :class="{prev:true,disabled:search.page === 1}">
            <a href="#">«上一页</a>
        </li>
        <li :class="{active: index(i) === search.page}" v-for="i in Math.min(5,totalPage)" :key="i">
            <a href="#">{{index(i)}}</a>
        </li>
        <li class="dotted" v-show="totalPage > 5"><span>...</span></li>
        <li :class="{next:true,disabled:search.page === totalPage}">
            <a href="#">下一页»</a>
        </li>
    </ul>
    <div>
        <span>共{{totalPage}}页&nbsp;</span>
        <span>
            到第
            <input type="text" class="page-num" :value="search.page">
            页 <button class="page-confirm" onclick="alert(1)">确定</button>
        </span>
    </div>
</div>

3.2 点击分页事件处理

点击分页按钮后,自然是要修改page的值

所以,在上一页下一页按钮添加点击事件,对page进行修改,在数字按钮上绑定点击事件,点击直接修改page:

翻页事件的方法:

page发生变化,就应该去后台重新查询数据。

不过,如果直接发起ajax请求,那么浏览器的地址栏中是不会有变化的,没有记录下分页信息。如果用户刷新页面,那么就会回到第一页。

这样不太友好,应该把搜索条件记录在地址栏的查询参数中

因此,需要监听search的变化,然后把search的过滤字段拼接在url路径后:

watch:{
    search:{
        deep:true,
            handler(val){
            // 把search对象变成请求参数,拼接在url路径
            window.location.href = "http://www.leyou.com/search.html?" + ly.stringify(val);
        }
    }
},

刷新页面测试,然后就出现重大bug:页面无限刷新!为什么?

因为Vue实例初始化的钩子函数中,读取请求参数,赋值给search的时候,也触发了watch监视!也就是说,每次页面创建完成,都会触发watch,然后就会去修改window.location路径,然后页面被刷新,再次触发created钩子,又触发watch,周而复始,无限循环。

所以,需要在watch中进行监控,如果发现是第一次初始化,则不继续向下执行。

那么问题是,如何判断是不是第一次?

第一次初始化时,search中的key值肯定是空的,所以:

3.3 页面顶部分页条

3.4 页面跳转

代码:

navPage函数:

四、排序

4.1 页面搜索排序条件

在搜索商品列表的顶部,有以下内容:

这是用来做排序的,默认按照综合排序。点击新品,应该按照商品创建时间排序,点击价格应该按照价格排序。

排序需要知道两个内容:

  • 排序的字段

  • 排序的方式

因此,首先在search中记录这两个信息,因为created钩子函数会对search进行覆盖,因此在钩子函数中对这两个信息进行初始化即可:

然后,在页面上给按钮绑定点击事件,修改sortBy和descending的值:

<!--排序字段-->
<ul class="sui-nav">
    <li :class="{active:!search.sortBy}" @click="search.sortBy=''">
        <a href="#">综合</a>
    </li>
    <li>
        <a href="#">销量</a>
    </li>
    <li @click="search.sortBy='createTime'" :class="{active: search.sortBy==='createTime'}">
        <a href="#">新品</a>
    </li>
    <li>
        <a href="#">评价</a>
    </li>
    <li @click="search.sortBy='price'; search.descending = !search.descending"
        :class="{active: search.sortBy==='price'}">
        <a href="#">
            价格
            <v-icon v-show="search.descending">arrow_drop_down</v-icon>
            <v-icon v-show="!search.descending">arrow_drop_up</v-icon>
        </a>
    </li>
</ul>

当点击价格排序按钮时,可以看到发起的请求中已经包含了排序字段

4.2 后台添加排序逻辑

后台需要接收请求参数中的排序信息,然后在搜索中加入排序的逻辑。

现在的请求参数对象SearchRequest中,只有page、key两个字段。需要进行扩展:

然后在搜索业务逻辑中,添加排序条件:

注意,因为存储在索引库中的的价格是一个数组:

因此在按照价格排序时,会进行智能处理:

  • 如果是价格降序,则会把数组中的最大值拿来排序

  • 如果是价格升序,则会把数组中的最小值拿来排序

其中第四件商品包含最低价,只不过默认显示的是skus中第一个:

4.3 问题解决

需求:当进行价格排序时,第一时间选中的都是最高或者最低价格的商品。

解决方法:修改loadData函数,在给goods.selected赋值时不在是把skus中第一个商品赋给它,而是查询符合要求的商品。

loadData(){
                ly.http.post("/search/page",this.search).then((resp) => {
                    resp.data.items.forEach(goods => {
                        let max = 0;
                        let min = 0;
                        //转换skus:把字符串转变为对象
                        goods.skus = JSON.parse(goods.skus);
                        //添加默认选中项,如果按价格排序则选出skus中价格最低的或者最高的,否则选skus中的第一个
                        if (this.search.sortBy === "price"){
                            if (this.search.descending === true){
                                //降序,则skus中价格选最高的
                                goods.skus.forEach(sku => {
                                    if (sku.price > max){
                                        max = sku.price;
                                    }
                                });
                                goods.skus.forEach(sku => {
                                    if (sku.price === max){
                                        goods.selected = sku;
                                    }
                                });
                            } else {
                                //升序,则skus中价格选最低的
                                min = goods.skus[0].price;
                                goods.skus.forEach(sku => {
                                    if (sku.price < min){
                                        min = sku.price;
                                    }
                                });
                                goods.skus.forEach(sku => {
                                    if (sku.price === min){
                                        goods.selected = sku;
                                    }
                                });
                            }
                        } else {
                            goods.selected = goods.skus[0];
                        }
                    });
                    this.goodsList = resp.data.items;
                    this.total = resp.data.total;
                    this.totalPage = resp.data.totalPage;
                });
            }

猜你喜欢

转载自blog.csdn.net/lyj2018gyq/article/details/83045651