• 【Vue2】VantUI项目-基础入门02


    1、搜索产品展示区块

    1.1 传递商品列表数据和分类数据 到对应组件中去使用

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    SearchProducts.vue中接收:

    <Products :goodsList="goodsList"/>
    props:["goodsList", "filterCategory"]
    
    • 1
    • 2

    Products.vue中接收:

    props:["goodsList"]
    
    • 1

    1.2 搜索产品内容数据渲染

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.3、分类的数据属性的改造及渲染

    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
            }
    
        })
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    SearchProducts.vue

     <van-dropdown-item title="分类" v-model="value2" :options="filterCategory" />
    
    • 1

    1.4 分类选中项的获取

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1.5 细化发送搜索请求

    SearchProducts.vue子组件点击要由高到低(或者低到高)查看产品列表,需要发送搜索请求携带更多参数。

    所以需要细化发送请求。

    SearchProducts.vue中:

    data () {
        return {
            priceVal: 0,
            // 价格下拉菜单选项
            option1: [
                { text: '价格由高到低', value: 0 },
                { text: '价格由低到高', value: 1 },
            ],
            // 分类下拉菜单当前项
            categoryVal: "",
    
        }
    },
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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    // 排序方式
                })
       ... ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    1.6 点击分类中选项发起搜索请求(子传父)

    SearchProducts.vue组件

     <van-dropdown-item title="分类" ... @change="categorychange"/>
    
    <script>
    	methods:{
            categoryChange(val){
                this.$emit("categoryChange", val);
            }
        }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SearchPopup.vue中:

    <SearchProducts v-else
         ...
         @categoryChange="categoryChange"
    />
    
    <script>
    	methods:{
            categoryChange(val){
                this.categoryId = val
                this.onSearch(this.searchVal)
            },
        }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.7 点击价格中选项发起搜索请求(子传父)

    SearchProducts.vue组件中

    <van-dropdown-item title="价格" ... @change="priceChange(priceVal)"/>
    
    
    <script>
    	methods:{
            priceChange(val){
                this.$emit("priceChange", val);
            }
        }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    SearchPopup.vue中:

    <SearchProducts v-else
         ...
          @priceChange="priceChange"
    />
    <script>
    	methods:{
    		priceChange(val){
           	this.order=val;
            this.sort="price";
            this.onSearch(this.searchVal)
       },
                
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.8 (历史和热门)点击标签执行搜索(子传父)

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    当goodlist为空的时候展示空图片,在SearchProducts.vue中:

    <van-empty v-if="goodsList.length==0" image="search" description="描述文字" />
    <Products v-else :goodsList="goodsList"/>
    
    • 1
    • 2

    1.9 点击搜索提示列表执行搜索

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SearchPopup.vue中

    <SearchTipsList v-else-if="blockShow==2"  :searchTipsListData="searchTipsListData" @cellClick="tagClick"/>
    
    • 1

    1.10 删除历史记录

    api中:

    // 清除历史记录
    export const Clearhistory = () => request.post("/search/clearhistory")
    
    • 1
    • 2

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2、tabar展示

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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')
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3、刷新页面时tabbar当前样式调整

    此时,在 http://localhost:5000/topic 下刷新页面,tabbar当前样式不正确,我们可以利用路由中的meta来解决

      {
        path: '/home',
        name: 'Home',
        component: Home,
        meta:{
          num:0
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在AppTabar.vue组件中可以通过$route.meta.num来获取本路由的num值

    <van-tabbar v-model="$route.meta.num"  active-color="darkred" inactive-color="#666">
    
    • 1

    4、路由拦截/路由守卫

    文档地址: https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB

    路由拦截(导航守卫:前置导航守卫和后置导航守卫)
    前置导航守卫有三个参数
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5、(小技巧)快速修改某个数组中一个或多个对象的属性名

    先进行深拷贝,再做替换:

    JSON.parse(JSON.stringify(data).replace(/name1/g, 'new_name1').replace(/name2/g, 'new_name2').replace(/name3/g, 'new_name3')...)
    
    • 1

    replace可以重复链式编程,name1表示旧属性名,new_name表示新属性名

  • 相关阅读:
    【蓝桥杯选拔赛真题23】C++计算24 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析
    Vue课程61-判断用户添加的数据是否为空
    【HTTP协议——八股文(下)篇】
    使用easyexcel模板导出的两个坑(Map空数据列错乱和不支持嵌套对象)
    基础IO介绍
    WPF 控件专题 TreeView控件详解
    基于Mongodb分布式锁简单实现,解决定时任务并发执行问题
    橘子学Mybatis02之基本对象前置了解
    零基础自学SQL课程 | IF函数
    element-ui实现分页——前端代码
  • 原文地址:https://blog.csdn.net/shentian885/article/details/126692228