SearchPopup.vue中:
<SearchProducts v-else
:goodsList="goodsList"
:filterCategory="filterCategory"
/>
<script>
data () {
return {
...
// 搜索商品列表的数据
goodsList:[],
// 分类数据
filterCategory:[]
}
},
...
onSearch(val) { //onSearch用户回车搜索的时候执行,val就是用户输入的值
// console.log("onSearch什么时候执行",val);
this.blockShow = 3;
GetGoodsListData({keyword:val}).then(res=>{
if(res.errno==0){
this.goodsList = res.data.goodsList
this.filterCategory = res.data.filterCategory
}
})
},
...
script>
SearchProducts.vue中接收:
<Products :goodsList="goodsList"/>
props:["goodsList", "filterCategory"]
Products.vue中接收:
props:["goodsList"]
Products.vue中:
<li v-for="item in goodsList" :key="item.id">
<img :src="item.list_pic_url" style="display:block;" width="100%" alt="" />
<div class="van-ellipsis">{{item.name}}div>
<div class="price">{{item.retail_price | RMBformat}}div>
li>
SearchPopup.vue中:
onSearch(val) {
...
GetGoodsListData({keyword:val}).then(res=>{
if(res.errno==0){
...
let arr = res.data.filterCategory
arr = JSON.parse(JSON.stringify(arr).replace(/name/g, 'text').replace(/id/g, 'value'))
this.filterCategory = arr
}
})
},
SearchProducts.vue
<van-dropdown-item title="分类" v-model="value2" :options="filterCategory" />
SearchProducts.vue
<van-dropdown-item title="分类" v-model="categoryVal" ... />
<script>
data () {
return {
...
// 分类下拉菜单当前项
categoryVal: "",
}
},
mounted(){
// 把this.categoryVal 的值改成checked为真的那一项的value值
let arr = this.filterCategory.map(item=>{
if(item.checked){
this.categoryVal = item.value
}
})
}
script>
SearchProducts.vue子组件点击要由高到低(或者低到高)查看产品列表,需要发送搜索请求携带更多参数。
所以需要细化发送请求。
SearchProducts.vue中:
data () {
return {
priceVal: 0,
// 价格下拉菜单选项
option1: [
{ text: '价格由高到低', value: 0 },
{ text: '价格由低到高', value: 1 },
],
// 分类下拉菜单当前项
categoryVal: "",
}
},
SearchPopup.vue中细化发送搜索请求:
data () {
return {
...
// 价格排序(高到底或者低到高)
order:"desc",
// 分类id
categoryId:0,
// 排序方式:按照id排序还是按照价格price排序
sort:"id"
}
},
methods: {
onSearch(val) {
...
GetGoodsListData({
keyword:val,
page:1,
size:20,
order:this.order, // 价格排序
categoryId:this.categoryId, // 分类id
sort:this.sort // 排序方式
})
... ...
SearchProducts.vue组件中
<van-dropdown-item title="分类" ... @change="categorychange"/>
<script>
methods:{
categoryChange(val){
this.$emit("categoryChange", val);
}
}
script>
SearchPopup.vue中:
<SearchProducts v-else
...
@categoryChange="categoryChange"
/>
<script>
methods:{
categoryChange(val){
this.categoryId = val
this.onSearch(this.searchVal)
},
}
script>
SearchProducts.vue组件中
<van-dropdown-item title="价格" ... @change="priceChange(priceVal)"/>
<script>
methods:{
priceChange(val){
this.$emit("priceChange", val);
}
}
script>
SearchPopup.vue中:
<SearchProducts v-else
...
@priceChange="priceChange"
/>
<script>
methods:{
priceChange(val){
this.order=val;
this.sort="price";
this.onSearch(this.searchVal)
},
script>
HistoryHot.vue中:
<van-tag @click="tagClick(item)" v-for="(item,index) in historyListData" :key="index" plain type="default">{{item}}van-tag>
....
<van-tag @click="tagClick(item.keyword)" v-for="(item,index) in hotKeywordListData" :key="index" plain type="default" :class="item.is_hot?'red':''">{{item.keyword}}van-tag>
<script>
methods:{
tagClick(val){
this.$emit("tagClick",val)
}
}
script>
SearchPopup.vue中:
<HistoryHot
v-if="blockShow==1"
:historyListData="historyListData"
:hotKeywordListData="hotKeywordListData"
@tagClick="tagClick"
/>
<script>
methods: {
tagClick(val){
console.log(val);
this.searchVal=val
this.onSearch(this.searchVal)
},
...
script>
当goodlist为空的时候展示空图片,在SearchProducts.vue中:
<van-empty v-if="goodsList.length==0" image="search" description="描述文字" />
<Products v-else :goodsList="goodsList"/>
SearchTipsList.vue中:
<van-cell @click="cellClick(item)" v-for="(item,index) in searchTipsListData" :key="index" :title="item" />
<script>
methods:{
cellClick(val){
this.$emit("cellClick",val)
}
}
script>
SearchPopup.vue中
<SearchTipsList v-else-if="blockShow==2" :searchTipsListData="searchTipsListData" @cellClick="tagClick"/>
api中:
// 清除历史记录
export const Clearhistory = () => request.post("/search/clearhistory")
HistoryHot.vue中:
<div class="his-hot" v-if="isShowHistory">
...
<van-icon name="delete" @click="clearFn"/>
...
<script>
data () {
return {
isShowHistory:true
}
},
methods:{
clearFn(){
Clearhistory().then(res=>{
if(res.errno==0){
console.log(res);
this.$toast.success('删除成功');
setTimeout(()=>{
this.isShowHistory=false
},1000)
}
})
}
}
script>
components中新建组件AppTabar.vue
<template>
<div>
<van-tabbar v-model="active" active-color="darkred" inactive-color="#666">
<van-tabbar-item to="/home" icon="home-o">首页van-tabbar-item>
<van-tabbar-item to="/topic" icon="label-o">专题van-tabbar-item>
<van-tabbar-item to="/category" icon="apps-o">分类van-tabbar-item>
<van-tabbar-item to="/cart" icon="cart-o">购物车van-tabbar-item>
<van-tabbar-item to="/user" icon="user-o">我的van-tabbar-item>
van-tabbar>
div>
template>
<script>
export default {
data() {
return {
active: 0,
};
},
};
script>
<style lang = "less" scoped>
style>
App.vue中:
<template>
<div id="app">
<router-view/>
<AppTabar />
div>
template>
<script>
import AppTabar from "@/components/AppTabar"
export default {
name: 'App',
data(){
return {
}
},
created(){
},
components: {
AppTabar
}
}
script>
views目录下新建Topic.vue,Category.vue,Cart.vue,User.vue组件
router/index.js中配置路由
{
path: '/topic',
name: 'Topic',
component: () => import(/* webpackChunkName: "Topic" */ '../views/Topic.vue')
},
{
path: '/category',
name: 'Category',
component: () => import(/* webpackChunkName: "Category" */ '../views/Category.vue')
},
{
path: '/cart',
name: 'Cart',
component: () => import(/* webpackChunkName: "Cart" */ '../views/Cart.vue')
},
{
path: '/user',
name: 'User',
component: () => import(/* webpackChunkName: "User" */ '../views/User.vue')
}
此时,在 http://localhost:5000/topic 下刷新页面,tabbar当前样式不正确,我们可以利用路由中的meta来解决
{
path: '/home',
name: 'Home',
component: Home,
meta:{
num:0
},
在AppTabar.vue组件中可以通过$route.meta.num来获取本路由的num值
<van-tabbar v-model="$route.meta.num" active-color="darkred" inactive-color="#666">
路由拦截(导航守卫:前置导航守卫和后置导航守卫)
前置导航守卫有三个参数
to 表示即将进入的路由
from 表示即将离开的路由
next() 表示执行进入这个路由
router.beforeEach((to, from, next)=>{
// 有token就表示已经登录
// 想要进入购物车页面,必须有登录标识token
// console.log('to:', to)
// console.log('from:', from)
let token = localStorage.getItem('token')
if(to.path=='/cart'){
// 此时必须要有token
if(token){
next(); // next()去到to所对应的路由界面
}else{
Vue.prototype.$toast('请先登录');
// 定时器
setTimeout(()=>{
next("/user"); // 强制去到"/user"所对应的路由界面
}, 1000);
}
return;
}
// 如果不是去往购物车的路由,则直接通过守卫,去到to所对应的路由界面
next()
})
export default router
先进行深拷贝,再做替换:
JSON.parse(JSON.stringify(data).replace(/name1/g, 'new_name1').replace(/name2/g, 'new_name2').replace(/name3/g, 'new_name3')...)
replace可以重复链式编程,name1表示旧属性名,new_name表示新属性名