Imitation hongxing erke micro channel small program

preface

Recently Hongxing erke directly brush the screen circle of friends, a while ago also learned a period of micro channel small program development, in order to consolidate the knowledge and improve practical experience, and support a Bohongxing Erke, so with the micro channel small program cloud development to start making a simple version of hongxing Erke small program. In the development process, focuses on the realization of the function, realize the basic function of online shopping, and encountered in the process of developing learning not met in the pit, in the article I’ll share my pain points of development of small and medium-sized application difficulty, and share the pit to like me, I have encountered the beginners of small programs have some help.

Part of the project:

Preparing development tools

  • VScode code editor.
  • Wechat developer tools
  • (Fiddler tool) grab the url of the picture in hongxing Erke applet
  • Vant component download
  • (Alibaba Vector icon library) provides some icon ICONS

Cloud Database Design

In this small program development, I used the cloud database to help me complete the project. Two database tables were used this time, one of which is the products table storing all the commodities. The following is a screenshot of the Products table and a brief introduction.The other is the ShopCar shopping cart table, which is empty at the beginning. After entering the details page, the user clicks “Add to Cart”, a data will be added to the ShopCar shopping cart table. The following is a screenshot of the ShopCar table with a brief introduction.

Home page/home design

The code framework in home.wxml is as follows:

There is an HX__HD setting for some of the navigation information shown above, and it is fixed here. Then there is a swiper TAB with five swiper-Items representing the home page/recommended page/Product/New page/Promotion page. Then set the width of the navigation on the home page, and set the class=hx_swiper_list in the view TAB to 1. Using the elastic layout, assign it to all heights except the navigation height on the home page. Finally, set the child height to 100% to inherit the height obtained from hx_swiper_list. Complete the layout.

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

Custom tabBar

  "tabBar": {
    "selectedColor": "#fece00".// The selected color
    "borderStyle": "white"."backgroundColor": "#ededed".// Background color
    "list": [   // Start writing the navigation bar
      {
        "text": "Home page".// The following words
        "pagePath": "pages/home/home".// The corresponding page
        "iconPath": "assets/images/tabs/home.png"./ / picture
        "selectedIconPath": "assets/images/tabs/home-active.png" // The selected image
      },
      {
        "text": "Classification"."pagePath": "pages/sort/sort"."iconPath": "assets/images/tabs/sort.png"."selectedIconPath": "assets/images/tabs/sort-active.png"
      },
      {
        "text": "Shopping cart"."pagePath": "pages/shopcar/shopcar"."iconPath": "assets/images/tabs/shopcar.png"."selectedIconPath": "assets/images/tabs/shopcar-active.png"
      },
      {
        "text": "I"."pagePath": "pages/my/my"."iconPath": "assets/images/tabs/my.png"."selectedIconPath": "assets/images/tabs/my-active.png"}},Copy the code

Define “tabBar”: {} in app.json to define the navigation bar, and you can define the color of the selected font, and the different styles of the selected image. This allows the navigation bar to represent and reflect which navigation tabs are selected.

Click home/recommendation/product/New/promotion to switch data linkage with finger horizontal sliding

data:{
    activeSwiperIndex:0.// activeSwiperIndex, activeTabIndex binding linkage is recommended on the home page
    activeTabIndex:0.// Make swiping bound to clicking on home page and recommendations
}
Copy the code

In the data data in home.js:

    <view>
        <view bindtap="switchTab"  data-index="0"
        class="hd__tabs_item {{activeTabIndex == 0? \"hd_tabs__item_on\":\ \ ""}}" >Home page</view>
        <view bindtap="switchTab" data-index="1"
        class="hd__tabs_item {{activeTabIndex == 1? \"hd_tabs__item_on\":\ \ ""}}" >recommended</view>
        <view bindtap="switchTabproduct" data-index="2"
        class="hd__tabs_item {{activeTabIndex == 2? \"hd_tabs__item_on\":\ \ ""}}" >goods</view>
        <view bindtap="switchTabNew" data-index="3"
        class="hd__tabs_item {{activeTabIndex == 3? \"hd_tabs__item_on\":\ \ ""}}" >On the new</view>
        <view bindtap="switchTab" data-index="4"
        class="hd__tabs_item {{activeTabIndex == 4? \"hd_tabs__item_on\":\ \ ""}}" >Sales promotion</view>
    </view>
Copy the code

We then set the click event switchTab for these buttons in home.wxml, passing in an index value and setting a teradata operator that will underline the selected value if the current click corresponds to the activeTabIndex value.

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

The switchTab event assigns the date-index value to the variable of index. If index is equal to activeTabIndex, the switchTab event assigns the value of index to activeTabIndex.

   <swiper class="hx_swiper_list_swiper"
    current="{{activeTabIndex}}"
    bindchange="doListChange">
Copy the code

Then pass a current value of {{activeTabIndex}} in the swiper TAB and use the Bindchange event to realize the linkage between the swiper and the click button.

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

Then re-assign the value passed in to the activeTabIndex value, so that a swipe and a click can affect the other.

Loop through the Products form in the database and be able to appear on the specified page based on the properties of the Products form.

Preloading gets initial initial display data

  const limit = 10;
  Page({
      data: {productlike: [].// Store the first 10 items of data you like on the home page
        productRec: [].// Store the first 10 pieces of data in the recommendation page
        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:productlike,
          product:data,
          productRec:productrec,
          productNew:productnew,
          total:total,
        })
      }
  )}
Copy the code

First, initialize the data in the home page, where limit is how many arrays to load at a time when the small program slides to the bottom of the load. Because I set limit=10 here, when sliding to the product, if there is still data, then load 10 arrays at a time. Pit tip: In the small program, the default value of data taken out from the database is 20 at a time if there is no limit. This is also the maximum value of data taken at a time, so we can only set the limit value between 1-20, beyond which there is no effect.

The BindScrolltoupper event in the Scroll view loads more data

In the text of the pit tip said, micro channel small program from the database to take data, the maximum is 20, if there are more than 20 data, then how to load more data? Here you need to use the cloud database’s.skip() method to skip to where you want the data. Next, I will lead you to experience it.


    <swiper-item class="hx_swiper_list__item item1 ">
        <scroll-view scroll-y="true" 
        bindscrolltolower="addMore_product"
        lower-threshold="100">
Copy the code

What this code is saying is that when you slide to 100 away from the bottom, it will automatically trigger the addMore_product event, which is the event that loads all the items, and the event that loads new items is almost the same, except that you add.where to restrict filtering. Next, I will introduce the addMore_product event, and other similar loading events. You are welcome to go to Gitee to view the source code, which will be linked at the end of the article.

    data:{
        page:1.// The page is already preloaded in onload, so start at 1
        product: [].// Store the product array of the obtained data
    }
    async addMore(){
        wx.showLoading({
            title: 'Loading.... '
        })
     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: 'No more goods.... ',})return; }}Copy the code

First of all, since onLoad is preloaded, the page should start from 1, and then trigger the addMore event when it slides to the bottom of the page 150 distance. Because Hongxing Erke app loads 10 data at a time, the limit is set to 10, and then skip is used to get the data of the next page. Then increment the page by +1 so that you get different data each time. But how to add these data to the product data item in JS data? Pit tip: here you need to use… Open syntax, expand this.data.product and the newly added data, and then put them into a new array together, and then add the array data to the product in the data, so as to realize the new data into the product and save the original product data.

.orderby() implements price ascending sorting

<view bindtap="switchProductTabprice"  data-index="3" 
  class="products_tabar__desc {{activeProductTabIndex == 3? \"products_tabar__desc_on\":\"\"}}"> price < / view >Copy the code

Set a switchProductTabprice event for click price, in js code as follows:

  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
    })
  },
 }
Copy the code

If the index is the index that was passed in, click on the price page and end. If not, the database is searched, and.orDerby (“price”,” ASC “) sorts by price in ascending order, and the search then increments the page increment array just like any other data.

The wx:for loop displays the data in js data:

<view id="changes" class="product__item" wx:for="{{productlike}}" wx:key="index" bindtap="goToDetail" data-item="{{item}}"> <view class="pr__hd"> <image src="{{item.pic}}" style="height:350rpx; width:350rpx;" > < / image > < view > < the view class = "item__des" > {{item. The title}} < / view > < the view class = "item__price" > ${{item. Price}}. 00 < / view > </view>Copy the code

For example, loop productLike here and here, select all products with isTitle true from the Products database. Other isNew (isNew), isRec (isRec) are the same, save in JS data data, and wx:for loop can be implemented.

Enter details page JS

Effect display:

After entering the Details page:

At this point, the color options are found through a database lookup. The following is the implementation.

Transfer the ID value in the click to enter page

   <view  id="changes" class="product__item" wx:for="{{productlike}}" 
   wx:key="index" bindtap="goToDetail"  data-item="{{item}}">
       <view class="pr__hd">
         <image src="{{item.pic}}" style="height:350rpx; width:350rpx;"/>
       </view>
       <view class="item__des">{{item.title}}</view>
       <view class="item__price">${{item. Price}}. 00</view>
  </view>
Copy the code

Add a click event to the detail page in each WX :for loop and pass the value of the loop’s data to the JS of goToDetail.

   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}`,}}}),Copy the code

Here, two detail and Detail2 pages are designed, one for shoes and the other for clothes. Because of the large number of databases, if only one detail is designed, the size design of the detail page has to be stored in an array, just like the color array. However, because there was too much data, I designed the size as a fixed size and only designed two detail interfaces to judge whether the incoming data was shoes or not. And through the string template.. /detail2/detail2? Id = ${e.c. with our fabrication: urrentTarget. Dataset. Item. Id} to data items in the database id along with jump into to the next page.

Get the id value passed in from the details page and look it up in the Products database

 async onLoad(options) {
    // console.log(typeof options.id); Type String
    const id = parseInt(options.id);
    // console.log(id);
    wx.setNavigationBarTitle({
      title: 'Merchandise Details',})let{total} = await productsCollection.count()
    this.setData({
      total:total,
      page:1,})let {data} = await productsCollection
    .where({
      id: db.command.eq(id)
    })
    .get();

    this.setData({
      productinfo:data
    })

    
   
  },
Copy the code

When the onload in the detail page is preloaded, it gets the id value that was passed in. Then use the ID value to search, here use es6 new async await asynchronous operation, can change the asynchronous operation into synchronous operation. Search the products database for a value whose ID is equal to the id passed in and get. Use the this.setData setting to pass the obtained value to productInfo in data in js of the detail interface. Pit tip: It is important to note that the id in the products database is of type number, but the string template is always of type string. If you use the. Where id, you will not find the string id, and the data will be empty. So we have to force the cast with parseInt before we compare.

Finally, the productinfo data in the data obtained is cycled through WX :for. Although each ProductINFO has only one data in the Products database, it can realize the separation of data and interface, making each detail page different.

conclusion

This code is only the general framework of the program. In this Saturday and Sunday, I will continue to update hongxing Erke wechat mini program about the use of cloud database to complete the development of shopping cart, which can add goods into the shopping cart from the details page (although I do not know the mobile phone preview can not be added, but the debugging operation on the computer is successful). If this article has helped you, please continue to support me. Here is the gitee source: gitee.com/jhqaq/hon-x… . Json and project.config.json and replace the appID with your own wechat applet ID. app.json:

{ "pages": [ "pages/home/home", "pages/test/test", "pages/sort/sort", "pages/home1/home1", "pages/home2/home2", "pages/shopcar/shopcar", "pages/my/my", "pages/search/search", "pages/detail/detail", "pages/detail2/detail2" ], "window": { "backgroundColor": "#F6F6F6", "backgroundTextStyle": "light", "navigationBarBackgroundColor": #F6F6F6", "navigationBarTitleText": "navigationBarTextStyle": "black"}, "tabBar": {"selectedColor": "# fece00 borderStyle", "" :" white ", "backgroundColor" : "# ededed", "a list" : [{" text ", "home page", "pagePath" : "pages/home/home", "iconPath": "assets/images/tabs/home.png", "selectedIconPath": "Assets /images/tabs/home-active. PNG"}, {"text": "pages ", "pagePath": "pages/sort/sort", "iconPath": "Assets/images/tabs/sort. PNG", "selectedIconPath" : "assets/images/tabs/sort - active. PNG"}, {" text ", "shopping cart", "pagePath" : "pages/shopcar/shopcar", "iconPath": "assets/images/tabs/shopcar.png", "selectedIconPath": "Assets/images/tabs/shopcar - active. PNG"}, {" text ":" my ", "pagePath" : "pages/my/my", "iconPath" : "assets/images/tabs/my.png", "selectedIconPath": "assets/images/tabs/my-active.png" } ] }, "usingComponents": { "van-search": "./miniprogram_npm/@vant/weapp/search/index", "van-cell": "@vant/weapp/cell/index", "van-cell-group": "@vant/weapp/cell-group/index", "van-grid": "@vant/weapp/grid/index", "van-grid-item": "@vant/weapp/grid-item/index" }, "sitemapLocation": "sitemap.json", "style": "v2" }Copy the code

project.config.json

{ "miniprogramRoot": "miniprogram/", "cloudfunctionRoot": "cloudfunctions/", "setting": { "urlCheck": true, "es6": false, "enhance": true, "postcss": true, "preloadBackgroundData": false, "minified": true, "newFeature": false, "coverView": true, "nodeModules": true, "autoAudits": false, "showShadowRootInWxmlPanel": true, "scopeDataCheck": false, "uglifyFileName": false, "checkInvalidKey": true, "checkSiteMap": true, "uploadWithSourceMap": true, "compileHotReLoad": false, "lazyloadPlaceholderEnable": false, "useMultiFrameRuntime": true, "useApiHook": true, "useApiHostProcess": true, "babelSetting": { "ignore": [], "disablePlugins": [], "outputPath": "" }, "enableEngineNative": false, "useIsolateContext": true, "userConfirmedBundleSwitch": false, "packNpmManually": false, "packNpmRelationList": [], "minifyWXSS": True, "showES6CompileOption" : false}, "projectname" : "weApp", "libVersion" : "2.14.1", "cloudfunctionTemplateRoot" : "CloudfunctionTemplate "," appID ": "wXB4a42D4b7e97a817 ", [] }, "conversation": { "list": [] }, "plugin": { "list": [] }, "game": { "list": [] }, "miniprogram": { "list": [ { "id": -1, "name": "db guide", "pathName": "pages/databaseGuide/databaseGuide" } ] } } }Copy the code

Finally, plug some data into the cloud database to see the effect.