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}
}
}