// pages/category/index.js import { request } from "../../request/index.js" Page({ /** * 頁面的初始數據 */ data: { //左側菜單數據 leftMenuList: [], //右側的商品數據 rightContent: [], // 被點擊的左側菜單 currentIndex: 0, //右側距離頂部距離 scrollTop:0, }, //接口返回數據 Cates: [], /** * 生命週期函數--監聽頁面加載 */ onLoad: function (options) { /** * 1,先判斷本地儲存中有沒有舊的緩存數據 * 本地存儲數據格式: * {time.Data.now(),data:[.....]} * 2,沒有數據就發送請求, * 3,有舊數據且舊數據沒有過時,直接使用本地儲存中的舊數據 */ const Cates = wx.getStorageSync("cates"); if (!Cates) { //不存在,獲取數據 this.getCates(); } else { //本地有緩存 if (Date.now() - Cates.time > 1000 * 10) { //超過10s就從新發送請求 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: "/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, //設置右側距離頂部距離 scrollTop:0, }); }, /** * 生命週期函數--監聽頁面初次渲染完成 */ onReady: function () { }, /** * 生命週期函數--監聽頁面顯示 */ onShow: function () { }, /** * 生命週期函數--監聽頁面隱藏 */ onHide: function () { }, /** * 生命週期函數--監聽頁面卸載 */ onUnload: function () { }, /** * 頁面相關事件處理函數--監聽用戶下拉動做 */ onPullDownRefresh: function () { }, /** * 頁面上拉觸底事件的處理函數 */ onReachBottom: function () { }, /** * 用戶點擊右上角分享 */ onShareAppMessage: function () { } })
{ "usingComponents": { "SearchInput":"../../components/SearchInput/SearchInput" }, "navigationBarTitleText": "商品分類" }
vscode的easyless插件會自動生成index.wxssjavascript
/* pages/category/index.wxss */ page { height: 100%; } .cates { height: 100%; .cates_container { // less中使用calc注意 height: ~'calc(100vh - 90rpx)'; display: flex; .left_menu { flex: 2; .menu_item { height: 80rpx; display: flex; justify-content: center; align-items: center; font-size: 30rpx; } .active { color: var(--themeColor); border-left: 5rpx solid currentColor; } } .right_content { flex: 5; .good_group { .good_title { height: 80rpx; display: flex; justify-content: center; align-items: center; .delimiter { color: #cccccc; padding: 0 10rpx; } .title {} } .good_list { display: flex; flex-wrap: wrap; navigator { width: 33.33%; text-align: center; image { width: 50%; } .goods_name {} } } } } } }
<view class="cates"> <SearchInput></SearchInput> <view class="cates_container"> <!-- 左側菜單 --> <scroll-view scroll-y="{{true}}" class="left_menu"> <view class="menu_item {{index===currentIndex?'active':''}}" wx:for="{{leftMenuList}}" wx:key="*this" bindtap="handleItemTap" data-index="{{index}}" > {{item}} </view> </scroll-view> <!-- 右側菜單 --> <scroll-view scroll-top="{{scrollTop}}" scroll-y="{{true}}" class="right_content"> <view class="good_group" wx:for="{{rightContent}}" wx:for-index="index1" wx:for-item="item1" > <view class="good_title"> <text class="delimiter">/</text> <text class="title">{{item1.cat_name}}</text> <text class="delimiter">/</text> </view> <view class="good_list"> <navigator class="" target="" url="/pages/goods_list/index?cid={{item2.cat_id}}" hover-class="navigator-hover" open-type="navigate" wx:for="{{item1.children}}" wx:for-index="index2" wx:for-item="item2" wx:key="cat_id" > <image class="" src="{{item2.cat_icon}}" mode="widthFix" lazy-load="false" binderror="" bindload="" /> <view class="goods_name">{{item2.cat_name}}</view> </navigator> </view> </view> </scroll-view> </view> </view>
主要是佈局文件index.less的編寫,注意less語法。css
商品列表頁功能:支持上拉加載更多,下拉刷新等
java
// pages/goods_list/index.js import { request } from "../../request/index.js" Page({ /** * 頁面的初始數據 */ data: { tabs: [{ id: 0, value: "綜合", isActive: true, }, { id: 1, value: "銷量", isActive: false, }, { id: 0, value: "價格", isActive: false, }, ], //商品列表數據 goodsList: [], }, //接口要的參數 QueryParams: { query: "", cid: "", pagenum: 1, pagesize: 10 }, //總頁數 totalPages: 1, /** * 生命週期函數--監聽頁面加載 */ onLoad: function (options) { this.QueryParams.cid = options.cid; this.getGoodsList(); }, //獲取商品列表頁數據 getGoodsList() { request({ url: "/goods/search", data: this.QueryParams, }).then(res => { //console.log(res); //數據總條數 const total = res.data.message.total; //計算總頁數 this.totalPages = Math.ceil(total/this.QueryParams.pagesize); //console.log(this.totalPages); this.setData({ goodsList:[...this.data.goodsList,... res.data.message.goods], }); //手動關閉下拉刷新界面,首次進入也不會報錯,無需處理 wx.stopPullDownRefresh(); }) }, //標題點擊事件 從子組件Tabs傳遞過來的 handleTabsItemChange(e) { //獲取被點擊的標題索引 const { index } = e.detail; //修改源數組 let { tabs } = this.data; tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false); //賦值到data中 this.setData({ tabs }); }, /** * 生命週期函數--監聽頁面初次渲染完成 */ onReady: function () { }, /** * 生命週期函數--監聽頁面顯示 */ onShow: function () { }, /** * 生命週期函數--監聽頁面隱藏 */ onHide: function () { }, /** * 生命週期函數--監聽頁面卸載 */ onUnload: function () { }, /** * 頁面相關事件處理函數--監聽用戶下拉動做 */ onPullDownRefresh: function () { //console.log('下拉了'); //重置數組 this.setData({ goodsList:[], }); //重置頁碼 this.QueryParams.pagenum=1; //從新發送請求 this.getGoodsList(); }, /** * 頁面上拉觸底事件的處理函數 */ onReachBottom: function () { //console.log('頁面觸底了~~'); //判斷還有沒有下一頁數據 if(this.QueryParams.pagenum>=this.totalPages){ //沒有下一頁數據了 wx.showToast({ title: '沒有更多數據了', }); }else{ this.QueryParams.pagenum++; this.getGoodsList(); } }, /** * 用戶點擊右上角分享 */ onShareAppMessage: function () { } })
{ "usingComponents": { "SearchInput":"../../components/SearchInput/SearchInput", "Tabs":"../../components/Tabs/Tabs" }, "navigationBarTitleText": "商品列表頁", "enablePullDownRefresh": true, "backgroundTextStyle": "dark" }
/* pages/goods_list/index.wxss */ .first_tab { .goods_item { display: flex; border-bottom: 1px solid #cccccc; .goods_img_wrap { flex: 2; display: flex; justify-content: center; align-items: center; image { width: 70%; } } .goods_info_wrap { flex: 3; display: flex; flex-direction: column; justify-content: space-around; .goods_name { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; } .goods_price { color: var(--themeColor); font-size: 32rpx; } } } }
<SearchInput></SearchInput> <!-- 監聽自定義事件 --> <Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange"> <block wx:if="{{tabs[0].isActive}}"> <view class="first_tab"> <navigator class="goods_item" wx:for="{{goodsList}}" wx:key="goods_id" > <!-- 左側的圖片容器 --> <view class="goods_img_wrap"> <image class="" src="{{item.goods_small_logo}}" mode="widthFix" lazy-load="false" binderror="" bindload="" /> </view> <!-- 右邊的商品信息 --> <view class="goods_info_wrap"> <view class="goods_name">{{item.goods_name}}</view> <view class="goods_price">¥{{item.goods_price}}</view> </view> </navigator> </view> </block> <block wx:elif="{{tabs[1].isActive}}">1</block> <block wx:elif="{{tabs[2].isActive}}">2</block> </Tabs>
// components/Tabs/Tabs.js Component({ /** * 組件的屬性列表 */ properties: { //接收父組件的傳值 tabs:{ type:Array, value:[], } }, /** * 組件的初始數據 */ data: { }, /** * 組件的方法列表 */ methods: { handleItemTap(e){ //獲取點擊索引 const {index} = e.currentTarget.dataset; //觸發父組件的事件 this.triggerEvent("tabsItemChange",{index}) }, } })
.tabs{ .tabs_title{ display: flex; .title_item{ display: flex; padding: 15rpx 0; justify-content: center; align-items: center; flex: 1; } } .tabs_content{} } .active{ color: var(--themeColor); border-bottom: 5rpx solid currentColor; }
<view class="tabs"> <view class="tabs_title"> <view class="title_item {{item.isActive?'active':''}}" wx:for="{{tabs}}" wx:key="id" bindtap="handleItemTap" data-index="{{index}}"> {{item.value}} </view> </view> <view class="tabs_content"> <slot></slot> </view> </view>
1,父組件(商品列表頁)和子組件(Tabs組件)相互傳遞數據問題
2,上拉加載更多、下拉刷新實現的邏輯web