0

    4 | 小程序实战之分类页面(点击菜单切换商品种类并且右侧菜单置顶 + 使用缓存

    2023.07.25 | admin | 152次围观

    1. 效果

    2. 分析接口数据

    3. 获取分类页面的数据接口

    https://api-hmugo-web.itheima.net/api/public/v1/categories
    

    4. 调用接口

    (1)为了方便演示,添加一个编译模式

    (2)现在分类页面的index.js文件中创建三个空数组

    index.js

    data: {
        // 左侧的菜单数据
        leftMenuList: [],
        // 右侧的商品数据
        rightContent: []
      },
    // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
    Cates: [],
    

    (3)发送异步请求给三个空数组赋值

    index.js

    // 引入用来发送请求的方法 一定要把路径补全
    import {request} from "../../request/index.js"
    Page({
      /**
       * 页面的初始数据
       */
      data: {
        // 左侧的菜单数据
        leftMenuList: [],
        // 右侧的商品数据
        rightContent: []
      },
      // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
      Cates: [],
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        this.getCates();
      },
      // 获取轮播图数据
      getCates(){
        request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
          .then(res=>{
            this.Cates = res.data.message;
            // 构造左侧的大菜单数据
            let leftMenuList = this.Cates.map(v=>v.cat_name);
            // 构造右侧的大菜单数据
            let rightContent = this.Cates[0].children;
            this.setData({
              leftMenuList,
              rightContent
            })
          })
      },
    })
    

    5. 页面布局

    index.wxml

    <view class="cates">
      
      <SearchInput>SearchInput>
      
      <view class="cates_container">
        
        <scroll-view scroll-y class="left_menu">
          
          
          <view
           class="menu_item {{index===currentIndex?'active':''}}"
           wx:for="{{leftMenuList}}"
           wx:key="*this"
          >
            <view>
              {{item}}
            view>
          view>
        scroll-view>
        
        
        <scroll-view scroll-y class="right_content">
          
          <view
           class="goods_group"
           wx:for="{{rightContent}}"
           wx:key="*this"
           wx:for-index="index1"
           wx:for-item="item1"
          >
            <view class="goods_title">
              <text class="delimeter">/text>
              <text class="title">{{item1.cat_name}}text>
              <text class="delimeter">/text>
            view>
            <view class="goods_list">
              <navigator
               wx:for="{{item1.children}}"
               wx:for-item="item2"
               wx:for-index="index2"
               wx:key="cat_id"
              >
                <image mode="widthFix" src="{{item2.cat_icon}}" />
                <view class="goods_name">{{item2.cat_name}}view>
              navigator>
            view>
          view>
        scroll-view>
        
      view>
    view>
    

    index.less

    page{
      // 先设置父页面高度
      height: 100%;
    }
    .cates{
      // 继承父页面高度
      height: 100%;
      .cates_container{
        // less中使用calc的时候要使用 ~ 包裹
        height: ~'calc( 100vh - 90rpx )';
        display: flex;
        .left_menu{
          // 因为现在是伸缩盒子的子项 有默认高度 100%
          flex: 2;
          .menu_item{
            display: flex;
            height: 80rpx;
            justify-content: center;
            align-items: center;
            font-size: 30rpx;
          }
          .active{
            color: var(--themeColor);
            border-left: 5rpx solid currentColor;
          }
        }
        .right_content{
          // 因为现在是伸缩盒子的子项 有默认高度 100%
          flex: 5;
          .goods_group{
            .goods_title{
              height: 80rpx;
              display: flex;
              justify-content: center;
              align-items: center;
              .delimeter{
                color: #ccc;
                padding: 0 10rpx;
              }
              .title{}
            }
            .goods_list{
              display: flex;
              // 允许换行
              flex-wrap: wrap;
              navigator{
                width: 33.33%;
                // 文字图片居中对齐
                text-align: center;
                image{
                  width: 50%;
                }
              }
              .goods_name{
              
              }
            }
          }
        }
      }
    }
    

    app.wxss

    image{
      /* 定义所有图片的宽度格式 */
      width: 100%;
    }
    

    6. 点击菜单可切换商品种类

    4 | 小程序实战之分类页面(点击菜单切换商品种类并且右侧菜单置顶 + 使用缓存

    修改左侧菜单的页面布局

    
        <scroll-view scroll-y class="left_menu">
          
          <view
           class="menu_item {{index===currentIndex?'active':''}}"
           wx:for="{{leftMenuList}}"
           wx:key="*this"
           bindtap="handleItemTap"
           data-index="{{index}}"
          >
            <view>
              {{item}}
            view>
          view>
        scroll-view>
        
    

    添加点击事件的行为

    index.js

    // 引入用来发送请求的方法 一定要把路径补全
    import {request} from "../../request/index.js"
    Page({
      /**
       * 页面的初始数据
       */
      data: {
        // 左侧的菜单数据
        leftMenuList: [],
        // 右侧的商品数据
        rightContent: [],
        currentIndex: 0
      },
      // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
      Cates: [],
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        wx.request({
          url: 'url',
        })
        this.getCates();
      },
      // 获取轮播图数据
      getCates(){
        request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
          .then(res=>{
            this.Cates = res.data.message;
            // 构造左侧的大菜单数据
            let leftMenuList = this.Cates.map(v=>v.cat_name);
            // 构造右侧的大菜单数据
            let rightContent = this.Cates[0].children;
            this.setData({
              leftMenuList,
              rightContent
            })
          })
      },
      //左侧菜单点击事件
      handleItemTap(e){
        /* 
        1 获取被点击的标题身上的索引
        2 给data中的currentIndex赋值就可以了
        3 根据不同的索引来渲染右侧的商品内容
         */
        const {index} = e.currentTarget.dataset;
        let rightContent = this.Cates[index].children;
        this.setData({
          currentIndex:index,
          rightContent
        })
      }
    })
    

    7. 使用缓存技术

    思路:在打开页面的时候,先做一个判断,判断本地储存中有没有旧的数据,如果没有的话,就发送请求获取这个数据,假如说有旧的数据微信小程序跳转子页面,并且这个数据没有过期,那么此时就可以使用本地储存中旧的数据了。所以说,我们需要解决的是怎么去存数据 和 怎么去拿数据 !

    index.js

    // 引入用来发送请求的方法 一定要把路径补全
    import {request} from "../../request/index.js"
    Page({
      /**
       * 页面的初始数据
       */
      data: {
        // 左侧的菜单数据
        leftMenuList: [],
        // 右侧的商品数据
        rightContent: [],
        currentIndex: 0
      },
      // 为了方便使用数据,在data同层级下创建Cates空数组接收接口返回的数据
      Cates: [],
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        /*
          1 先判断一下本地存储中有没有旧的数据
            {time:Date.now(),data:[...]}
          2 没有旧数据 直接发送新请求 
          3 有旧的数据 同时 旧的数据也没有过期 就使用 本地存储中的旧数据即可
        */
        //  1 获取本地存储中的数据  (小程序中也是存在本地存储 技术)
        const Cates = wx.getStorageSync('cates');
        //  2 判断  
        if(!Cates){
          // 不存在 发送请求获取数据
          this.getCates();
        }else{
          // 有旧的数据 定义过期时间5分钟 1000ms = 1s
          if(Date.now()-Cates.time>1000*300){
            // 重新发送请求
            this.getCates();
          }else{
            this.Cates = Cates.data;
            // 构造左侧的大菜单数据
            let leftMenuList = this.Cates.map(v=>v.cat_name);
            // 构造右侧的大菜单数据
            let rightContent = this.Cates[0].children;
            this.setData({
              leftMenuList,
              rightContent
            })
          }
        }
      },
      // 获取轮播图数据
      getCates(){
        request({url: 'https://api-hmugo-web.itheima.net/api/public/v1/categories'})
          .then(res=>{
            this.Cates = res.data.message;
            // 把接口的数据存入到本地存储中
            wx.setStorageSync("cates", { time: Date.now(), data: this.Cates });
            // 构造左侧的大菜单数据
            let leftMenuList = this.Cates.map(v=>v.cat_name);
            // 构造右侧的大菜单数据
            let rightContent = this.Cates[0].children;
            this.setData({
              leftMenuList,
              rightContent
            })
          })
      },
      //左侧菜单点击事件
      handleItemTap(e){
        /* 
        1 获取被点击的标题身上的索引
        2 给data中的currentIndex赋值就可以了
        3 根据不同的索引来渲染右侧的商品内容
         */
        const {index} = e.currentTarget.dataset;
        let rightContent = this.Cates[index].children;
        this.setData({
          currentIndex:index,
          rightContent
        })
      }
    })
    

    疑惑:web和小程序本地存储的区别

    1 写代码的方式不一样了

    web: localStorage.setItem(“key”,“value”) localStorage.getItem(“key”)

    小程序中: wx.setStorageSync(“key”, “value”); wx.getStorageSync(“key”);

    2 存的时候 有没有做类型转换

    web: 不管存入的是什么类型的数据,最终都会先调用一下 toString(),把数据变成了字符串 再存入进去

    小程序: 不存在 类型转换的这个操作 存什么类似的数据进去,获取的时候就是什么类型

    8. 点击菜单-右侧列表置顶

    如果你跟着我敲的话,你会发现当你点击一个菜单后,右侧列表往下拉,再点击另一个菜单,你会发现右侧列表没有置顶,那么怎么做呢?

    思路:在右侧的菜单数据的 scroll-view 标签中增加 scroll-top 属性设置竖向滚动条位置,但这标签不能写死微信小程序跳转子页面,如 scroll-top=“0”,因为这对于触发点击事件无效,你得设置一个变量,当点击左边菜单时,对这个变量赋值

    index.wxml

    
        <scroll-view
         scroll-y
         class="right_content"
         scroll-top="{{scrollTop}}"
        >
        。。。
        <scroll-view/>
    

    index.js

    data: {
        // 左侧的菜单数据
        leftMenuList: [],
        // 右侧的商品数据
        rightContent: [],
        currentIndex: 0,
        scrollTop:0
      },
    。。。
    // 左侧菜单的点击事件
      handleItemTap(e) {
        /* 
        1 获取被点击的标题身上的索引
        2 给data中的currentIndex赋值就可以了
        3 根据不同的索引来渲染右侧的商品内容
         */
        const { index } = e.currentTarget.dataset;
        let rightContent = this.Cates[index].children;
        this.setData({
          currentIndex: index,
          rightContent,
          // 重新设置 右侧内容的scroll-view标签的距离顶部的距离
          scrollTop: 0
        })
      }
    

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论