前台项目-搜索页参数合并、品牌操作、综合/价格排序、分页


1.由首页跳转到搜索页进行查询时,通过传递不同的参数展示对应不同的数据

🍕🍕🍕components/TypeNav/index.vue

methods:{
	// 触发事件
	gosearch(event){
			 //使用(事件委派 + 编程式导航)进行路由跳转 
      //但是 事件委派父元素包含子元素很多 不知道点击的是div 还是a 2.如何区分传递的参数(名称、id)
      // this.$router.push('/search')
      // this.$router.push({name:"",query:{categoryName:'xxx',category1Id:'xx'}})
      //第一个问题 把子节点当中a标签 加上一个自定义属性 data-categoryName 其余的子节点是没有的
      let el = event.target;
      //获取到当前点击事件的节点【h3、a、dt、dl】 只要带有data-categoryName自定义属性的标签 就一定是 a标签
      //节点有一个方法 dataset 可以获取节点的自定义属性与属性值
      // console.log(el.dataset) //分别解构出属性
      let { categoryname, category1id, category2id, category3id } = el.dataset
      //区分 各个级别的a标签 新的自定义属性就可以知道是 一级、二级、三级的a标签了
      if (categoryname) {
        //整理路由跳转的参数
        let location = { name: "search" };
        //此时query参数不确定 需要动态添加 声明query参数  //给location 动态添加query参数
        let query = { categoryName: categoryname }
        //一级分类 二级分类 三级分类的a标签
        if (category1id) {
          query.category1Id = category1id;
        } else if (category2id) {
          query.category2Id = category2id;
        } else {
          query.category3Id = category3id;
        }
       //判断 如果带有header组件传的params参数(搜索的关键字) 稍带着也应该传递过去
       if(this.$route.params){
        location.params = this.$route.params;
         //把参数合并整理 
        //console.log(location,query);//现在是两个对象 {name:'xxx'} {categoryName:'xxx',category1Id:'x'}
        //给location 动态添加query参数
        location.query = query;
        //跳转传递合并之后的参数
        this.$router.push(location)
       }
      }
	}
}

🍗🍗🍗components/Header/index.vue

  • 同样定义方法携带参数传递
methods:{
	headerGoSearch(){
		 //如果有query参数 也带过去,通过携带参数去查询对应的数据
      if(this.$route.query){
        let location = {name:"search",params:{ keyword:this.keyword || undefined }}
        location.query = this.$route.query;
        this.$router.push(location)
      }	
	}
}

🌯🌯🌯pages/Search/index.vue

  • 此时的路由就可以获取到传递的参数了,不过,现在的dispatch是在mounted生命周期回调的,挂载完毕之后,派发一次,应该定义一个方法,在挂载时,调用方法
  data() {
    return {
      // 初始化参数
      searchParams: {
        "category1Id": "",
        "category2Id": "",
        "category3Id": "",
        "categoryName": "", 
        "keyword": "",
        "order": "",
        "pageNo": 1,
        "pageSize": 10,
        "props": [],
        // 品牌种类
        "trademark": ""
      }
    }
  },
// 挂载之前获取到路由参数进行操作
beforeMount(){
	Object.assign(this.searchParams,this.$route.query,this.$route.params);
	console.log("发请求之前":this.searchParams)
},
mounted(){
	this.getData();
},
 methods: {
    // 调用获取搜索数据方法
    getData() {
      this.$store.dispatch("reqGetSearchList", this.searchParams)
    }
  },

🍞🍞🍞这次使用getters,简化仓库数据

  • src\store\search\index.js
const getters = {
	goodsList(state){
		 // 参数a 是当前仓库state里面的searchList
        console.log(state);
        return state.searchList.goodsList	
	}
}

🧈🍚组件获取到仓库数据 展示

  • src\pages\Search\index.vue
import { mapGetters } from "vuex";
computed:{
	...mapGetters(["goodsList"])
}
  • 监听组件实例身上的属性值的变化 监听路由是否变化 如果变化需要再次请求获取数据
//此时监听是浅层监听
watch:{
	$route(){
		// 整理合并参数
		Object.assign(this.searchParams,this.$route.query,this.$route.params);
      	this.getData();
      	// 每一次请求完毕应该把上一次搜索过的分类清空
      	this.searchParams.category1Id = '';
      	this.searchParams.category2Id = '';
      	this.searchParams.category3Id = '';
	}
}
  • 同样在SearchSelector组件中展示数据
  • src\pages\Search\SearchSelector\SearchSelector.vue
    🐱‍🏍🐱‍🏍🐱‍🏍处理面包屑关键字
  • 面包屑元素触发事件
 removeKeyword(){
      //删除关键字
      this.searchParams.keyword = undefined;
      this.getData()
    }
  • 但是,此时的header组件中的keyword依然存在,需要通知兄弟组件清空keyword
  • 选用 $bus 全局事件总线通知header组件关键字清空
  • 入口文件main.js中
// 全局事件总线$bus配置
beforeCreate(){
	Vue.prototype.$bus = this;
}
  • search组件中,注册事件
this.$bus.$emit("clear",2222);
//此时,如果路径中有query参数,应该携带过去
if(this.$route.query){
	this.$router.push({name:"search",query:this.$route.query})
}
  • hearder组件中,$on触发
mounted(){
	this.$bus.$on("clear",function(){
		this.keyword = '';
	})
}

🍔🍔🍔处理品牌,点击品牌查询对应的品牌商品

  • 此时品牌作为search组件的子组件,需要传递给父组件数据,在父组件整理发请求,怎么传? 用自定义事件
 <SearchSelector @tradeMarkInfo="tradeMarkInfo"  />
 // 此时会注入trademark
tradeMarkInfo(trademark){
	  // 整理品牌字段的参数 品牌:"ID:品牌名称"
      this.searchParams.trademark = `${trademark.tmId}:${trademark.tmName}`;
      this.getData();
}
// 子组件中 注册自定义事件并传递参数
this.$emit("tradeMarkInfo",trademark)

2.平台售卖属性的操作

  • 点击售卖属性查询对应属性的商品,SearchSelector属于子组件,需要传递给父组件信息(参数)进行整理
//SearchSelector
   <li v-for="(attrValue,index) in attr.attrValueList" :key="index" @click="attrInfo(attr,attrValue)">
            <a>{{attrValue}}</a>
          </li>
 attrInfo(attr,attrValue){
        // ["属性ID:属性值:属性名"]
        console.log(attrValue );
        this.$emit("attrInfo",attr,attrValue)
      }
//search/index.vue
 <!-- 商品属性面包屑 -->
            <li class="with-x" v-for="(attrVale,index) in searchParams.props" :key="index">
              {{attrVale.split(":")[1]}}
              <i @click="removetattrVale(index)">x</i>
            </li>
 // 添加自定义事件
 <SearchSelector @tradeMarkInfo="tradeMarkInfo" @attrInfo="attrInfo" />
 attrInfo(attr,attrValue){
	let props = `${attr.tmId}:${attrValue}:${attr.tmName}`;
	if(this.searchParams.props.indexOf(props)==-1){
		this.searchParams.props.push(props)	
	}
	this.getData();
}

3.综合排序 价格排序

  • 🍔🍔由数据返回的order字段 示例"1:desc" 1:代表综合,2,代表价格 asc:升序,desc:降序 例子:‘1:desc’,代表 综合降序
  • 谁应该有箭头图标,取决于谁有类名
 <li :class="{active:isOne}" @click="changeOrder('1')">
                  <a href="#" >综合
                    <span v-show="isOne" class="iconfont" :class="{'icon-up':isAsc,'icon-down':isDesc}"></span>
                  </a>
                </li>
                <li :class="{active:isTwo}" @click="changeOrder('2')">
                  <a href="#" >价格
                    <span v-show="isTwo" class="iconfont" :class="{'icon-up':isAsc,'icon-down':isDesc}"></span>
                  </a>
                </li>
 methods:{
	   changeOrder(flag){
      let originOrder = this.searchParams.order;
      let originFlag = this.searchParams.order.split(":")[0]
      let originSort = this.searchParams.order.split(":")[1]

      // 如何区分点击的是综合按钮还是价格按钮 通过flag与originFlag是否相等 首次点击如果相等 一定是综合 多次点击是否是同一个按钮
      let newOrder = ""
      if(flag == originFlag){
        newOrder = `${originFlag}:${originSort=="desc"?"asc":desc}`
        console.log(newOrder);
      }else{
      // 价格
        newOrder = `${flag}:${'desc'}`
      };
      // 修改初始状态
      this.searchParams.order= newOrder;
      this.getData();
    }
},
 computed:{
  isOne(){
      return this.searchParams.order.indexOf('1') !=-1
    },
    isTwo(){
      return this.searchParams.order.indexOf('2') !=-1
    },
    isAsc(){
      return this.searchParams.order.indexOf('asc') !=-1
    },
    isDesc(){
      return this.searchParams.order.indexOf('desc') !=-1
    }
 }
                

分页处理

  • 🐱‍🏍🐱‍🏍🐱‍🏍公共分页组件
  • main.js文件中注册全局组件
import Pagination from '@/components/Pagination';
Vue.component(Pagination.name, Pagination)
  • components中新加Pagination.vue
  • src\components\Pagination\Pagination.vue
  • 条件:1.需要知道当前页数,2.需要知道每页展示多少条数据3.需要知道整个分页器总共有多少条数据4.一共有多少页,总条数除以每页展示数量5.需要知道分页器连续页码数一般是奇数
  • 分页组件属于公共组件,使用的时候就决定了组件关系
  • 通过props把数据传递给分页组件 分页组件通过自定义事件把参数传递给父组件 进行整理 再发请求,重新拉取对应的数据
  • src\pages\Search\index.vue
 <Pagination :pageNo="searchParams.pageNo" :pageSize="searchParams.pageSize" :total="total" :continues="5" @getPageNo=getPageNo ></Pagination>
  // 分页自定义回调
    getPageNo(pageNo){
      // console.log("分页组件传过来的",pageNo);
      this.searchParams.pageNo = pageNo
      this.getData()
    }
  • src\components\Pagination\Pagination.vue
  <div class="pagination">
    <h3>{{startNumberAndEndNum}} ----- 当前的页码{{pageNo}}</h3>
  
    <button :disabled="pageNo==1" @click="$emit('getPageNo',pageNo-1)">上一页</button>
    <button v-if="startNumberAndEndNum.start > 1" @click="$emit('getPageNo',1)" :class="{active:pageNo==1}">1</button>
    <button v-if="startNumberAndEndNum.start > 2">···</button>
  
    <button @click="$emit('getPageNo',page)" v-for="(page,index) in startNumberAndEndNum.end" :key="index"
      v-if="page>=startNumberAndEndNum.start" :class="{active:pageNo==page}">{{page}}</button>
  
    <button v-if="startNumberAndEndNum.end < totalPage-1">···</button>
    <button v-if="startNumberAndEndNum.end < totalPage" :class="{active:pageNo==totalPage}">{{totalPage}}</button>
    <button :disabled="pageNo==totalPage"  @click="$emit('getPageNo',pageNo+1)">下一页</button>
  
    <button style="margin-left: 30px">共 {{total}} 条</button>
  
  </div>
props:['pageNo', 'pageSize', 'total', 'continues'],
computed:{
	// 根据总共的数据total和每页展示多少数据pageSize可以计算出总共有多少页 向上取整数计算
	totalPage(){
		return Math.ceil(this.total / this.pageSize)
	},
	// 还需要明确 连续页码的起始数字和结束数字
	startNumberAndEndNum(){
		// 通过组件实例身上解构出需要的字段
		const { continues,pageNo,totalPage} = this;
		// 需要 起始和结束初始值
		let start = 0;
		let end = 0;
		// 特殊处理 连续页码数 数据不够连续页码数
		if(this.continues > this.totalPage){
			start = 1;
			end = totalPage;
		}else{
			start = this.pageNo - parseInt(this.continues/2);
			end = this.pageNo + parseInt(this.continues/2);
			//极端情况为0|负数
			if(start < 1){
				start = 1;
				end = this.continues	
			}	
			if(end > this.totalPage){
					end = this.totalPage;
					start = this.totalPage -this.continues +1
			}
		}
		return {start,end}
		
	}
}

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值