Frontend Development 15 min read

Building a Simple Hongxing Erke Clone with WeChat Mini Program Cloud Development

This article walks through creating a lightweight Hongxing Erke‑style e‑commerce mini‑program using WeChat's cloud development, covering tool setup, cloud database design, UI layout, tabBar customization, data loading, pagination, sorting, and detail‑page navigation with practical code examples and common pitfalls.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a Simple Hongxing Erke Clone with WeChat Mini Program Cloud Development

The author introduces a personal project to recreate the Hongxing Erke online store as a WeChat Mini Program, aiming to reinforce learning of Mini Program cloud development and share challenges faced by beginners.

Development tools include VSCode, the WeChat Developer Tool, Fiddler for extracting image URLs, the Vant UI component library, and Alibaba's icon font.

Cloud database design uses two collections: products (stores all product information) and shopcar (shopping‑cart entries). Screenshots of the collections are shown in the original article.

Home page layout (pages/home/home) is built with a flexible vertical layout. The main navigation bar is fixed, followed by a swiper containing five swiper-item sections (Home, Recommend, Products, New, Promotion). CSS used:

.hx_swiper_list{ flex: 1; }
.hx_swiper_list_swiper, .hx_swiper_list__item{ height: 100%; }

Custom tabBar is defined in app.json :

"tabBar": {
  "selectedColor": "#fece00",
  "borderStyle": "white",
  "backgroundColor": "#ededed",
  "list": [
    {"text":"首页","pagePath":"pages/home/home","iconPath":"assets/images/tabs/home.png","selectedIconPath":"assets/images/tabs/home-active.png"},
    {"text":"分类","pagePath":"pages/sort/sort","iconPath":"assets/images/tabs/sort.png","selectedIconPath":"assets/images/tabs/sort-active.png"},
    {"text":"购物车","pagePath":"pages/shopcar/shopcar","iconPath":"assets/images/tabs/shopcar.png","selectedIconPath":"assets/images/tabs/shopcar-active.png"},
    {"text":"我的","pagePath":"pages/my/my","iconPath":"assets/images/tabs/my.png","selectedIconPath":"assets/images/tabs/my-active.png"}
  ]
}

Tab switching logic in home.js :

data:{ activeSwiperIndex:0, activeTabIndex:0 }
switchTab(e){
  let index=e.currentTarget.dataset.index;
  if(index==this.data.activeTabIndex) return;
  this.setData({ activeTabIndex:index });
}

doListChange(e){
  let index=e.detail.current;
  this.setData({ activeTabIndex:index });
}

Initial data loading fetches the first 10 products and separates them by flags ( isTitle , isNew , isRec ) using async/await:

const limit = 10;
Page({
  data:{ productlike:[], productRec:[], productNew:[] },
  async onLoad(){
    let {data}=await productsCollection.limit(limit).get();
    let {data:productnew}=await productsCollection.where({isNew:true}).limit(limit).get();
    let {data:productlike}=await productsCollection.where({isTitle:true}).limit(limit).get();
    let {data:productrec}=await productsCollection.where({isRec:true}).limit(limit).get();
    let {total}=await productsCollection.count();
    this.setData({ productlike, product:data, productRec:productrec, productNew:productnew, total });
  }
});

Because the cloud database returns a maximum of 20 records per query, the limit must stay between 1‑20.

Pagination with scroll‑view uses skip() to load more items when the user scrolls near the bottom:

data:{ page:1, product:[] }
async addMore(){
  wx.showLoading({title:'正在加载中....'});
  let {data}=await productsCollection.skip(this.data.page*limit).limit(limit).get();
  wx.hideLoading();
  this.setData({
    product:[...this.data.product,...data],
    page:++this.data.page
  });
  if(this.data.product.length>=this.data.total){
    wx.showToast({title:'没有更多商品了....'});
    return;
  }
}

Price sorting demonstrates the .orderBy() API:

async switchProductTabprice(e){
  let index=e.currentTarget.dataset.index;
  if(index==this.data.activeProductTabIndex) return;
  let {data}=await productsCollection.orderBy('price','asc').skip(0).limit(limit).get();
  this.setData({ activeProductTabIndex:index, pageprice:1, product:data });
}

Displaying data uses wx:for to render product cards:

<view wx:for="{{productlike}}" wx:key="index" bindtap="goToDetail" data-item="{{item}}">
  <image src="{{item.pic}}"/>
  <view>{{item.title}}</view>
  <view>¥{{item.price}}.00</view>
</view>

Detail page navigation passes the product id via URL parameters and loads the specific record:

goToDetail(e){
  if(e.currentTarget.dataset.item.isShoes){
    wx.navigateTo({url:`../detail/detail?id=${e.currentTarget.dataset.item.id}`});
  } else {
    wx.navigateTo({url:`../detail2/detail2?id=${e.currentTarget.dataset.item.id}`});
  }
}

async onLoad(options){
  const id=parseInt(options.id);
  wx.setNavigationBarTitle({title:'商品详情'});
  let {total}=await productsCollection.count();
  this.setData({total,page:1});
  let {data}=await productsCollection.where({id:db.command.eq(id)}).get();
  this.setData({productinfo:data});
}

The article concludes with a reminder that the source code is available on Gitee and that developers need to replace the appid with their own Mini Program ID before deployment.

JavaScriptFrontend DevelopmentWeChat Mini ProgramtutorialCloud Database
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.