preface

Since the release of small programs, with no installation, run out, easy to reach, no registration, no login, and social fission and other advantages, all the way, become more and more popular, it revolutionized the reduction of mobile application development costs, but also just to meet the user’s habit of using applications. Small program charm is so big, as a program ape, I think how not to do one? Without further ado, let’s roll up our sleeves

The preparatory work

  • Front-end development tool: VSCode
  • Debugging: wechat developer tools
  • Mock some of your own data
  • Wechat development document

Project introduction: Millet mall combat

Project directory structure

├─ Some ICONS used by Assets ├─ lib ├─ Weui.wxSS References Weui ├── Modules ├─ showdetail.js Public JS file ├─ showcdetail.js ├─ Pages project all pages ├─ Index shopping front Page ├─ Categories commodity categories page ├─ Discovery discovery page ├─ Channel Commodity channel Directory ├─ Phone Mobile phone Channel ├─ TV TV channel ├─ Computer Computer Channel ├─ Shopping Cart ├─ Mine Personal Information Page ├─ Goods Goods Details Page ├─ Search Goods Attributes Page ├─ Addr Shipping Address page ├─ Template ├─ Slide ├─ Goods_list │ ├─ Utill │ ├─ Mock ├─ ├─ ├─ app.json Project Public SettingsCopy the code

Display and implementation of functions

First, the mall home page

Page structure analysis:

  • The search bar at the top looks like a search box, but all it needs to do is jump to the page, so you just need to set disabled to true, and you want the placeholder to be centered, Wechat applets provide a placeholder class property, which can change the placeholder style.

  • Round figure area Here WeChat small program provides us with the swiper components, direct use. However, it is possible to have a different image on each page, so use the idea of componentization, write it as a template, and import the template where you want to use it.

<template name="slide">
    <view class="section section-swiper">
		<swiper class="slide" indicator-dots="{{true}}" autoplay="{{true}}" interval="2000" duration="1000">
			<block wx:for="{{slides}}" wx:key="{{index}}">
				<swiper-item>
					<image src="{{item.slide_url}}" mode="widthFix" class="slide-image" data-id="{{item.id}}" />
				</swiper-item>
			</block>
		</swiper>
	</view>
</template>
Copy the code

When used, this is introduced

<import src=".. /.. /.. /templates/slide/slide.wxml" />
<view class="container">
    <template is="slide" data="{{slides}}"></template>
</view>
Copy the code
  • Mall navigation area, activity area here is just a simple layout, there is no need to repeat. However, it should be noted that the use of flexible layout is highly recommended in wechat mini programs
  • In the commodity display area on the home page, the commodities here are displayed in blocks, very regularly, so the whole commodity display can be directly usedwx:forLet’s iterate. WXML:
<! -- Home page commodity section -->
	<view class="section block">
		<block wx:for="{{index_block}}" wx:key="{{item.id}}">
			<view class="section cover">
				<image class="cover-img" src="{{item.img_url}}" data-cid="{{item.id}}" bindtap="showcDetail"/>
			</view>
			<view class="section goods-list">
				<block wx:for="{{item.section}}" wx:key="index" wx:for-item="product">
					<view class="goods-item">
						<image class="goods-img {{product.is_new? 'new':''}} {{product.on_sale? 'on-sale':''}}" src="{{product.goods_cover}}" data-pid="{{product.id}}" mode="aspectFill" bindtap="showDetail"/>
						<text class="title">{{product.header}}</text>
						<text class="desp">{{product.description}}</text>
						<text class="meta">{{product.meta}}</text>
						<text class="discount">{{product.discount}}</text>
					</view>
				</block>
			</view>
		</block>
	</view><! -- end-section block -->
Copy the code

Here is a detail, each section of the goods will be divided into “new”, “immediate reduction” (discount), “no discount” three, so how to do? Here I use a clever method: bind the Boolean values is_new and on_SALE to the class of each item and use the ternary operator to determine whether to attach a class name to the item, then use the pseudo-element to label the item as “new” or “new minus” as follows:

WXML:

<image class="goods-img {{product.is_new? 'new':''}} {{product.on_sale? 'on-sale':''}}" src="{{product.goods_cover}}" data-pid="{{product.id}}" mode="aspectFill" bindtap="showDetail"/>
Copy the code

wxss

.goods-img.new:before{      /* New label style */
  position: absolute;
  left: 0;
  top: 0;
  width: 100rpx;
  height: 40rpx;
  line-height: 40rpx;
  content: "New";
  color: #fff;
  font-size: 9pt;
  text-align: center;
  background: #8CC64A;
}
.goods-img.on-sale:before{   /* Vertical subtracting label style */
  position: absolute;
  left: 0;
  top: 0;
  width: 100rpx;
  height: 40rpx;
  line-height: 40rpx;
  content: "Knock";
  font-size: 9pt;
  color: #fff;
  text-align: center;
  background: #ec6055;
}
Copy the code

Logical analysis: the home page is just some goods, so the logical layer as long as according to the ID of each commodity to jump to the corresponding commodity details page, it is obvious that this method in multiple pages to use, so the use of modular idea, create a modules folder, write the method in a separate JS file, and output

const showDetail=(e) = >{
    const id=e.currentTarget.dataset.pid; // Get the id of each item
    wx.navigateTo({
        url: `/pages/goods/show? id=${id}`})};export default showDetail;
Copy the code

Where do you want to use it, import it

import showDetail from ".. /.. /modules/showDetail";
Copy the code

Ii. Commodity classification page

scroll-view
scroll-y
scroll-view
scroll-into-view
a
scroll-into-view
There is a small pit here
This ID cannot start with a number

It would look so ugly.

** Solution: Add the following styles to the global style

// Hide the scrollbar ::-webkit-scrollbar{height: 0; width: 0; color: transparent; }Copy the code

Well, beautiful!!

Commodity classification function

If the current subscript is the same as that of the selected menu, it will be in active state.

<view class="main">
    <scroll-view scroll-y class="category-left">
        <view class="cate-nav-list" wx:for="{{cate_nav_list}}" wx:key="{{item.id}}" data-id="{{item.id}}" data-index="{{index}}"
            bindtap="switchCategory">
            <text class="cate-name {{curIndex===index? 'on':''}}">{{item.name}}</text>
        </view>
    </scroll-view>
    <scroll-view class="category-right" scroll-y="{{true}}" scroll-into-view="{{toView}}" scroll-with-animation="true">
        <view class="cate-content">
            <view class="cate-list-content" wx:for="{{detail}}" wx:key="{{item.id}}" id="{{item.id}}">
                <view class="banner">
                    <image src="{{item.banner}}"/>
                </view>
                <view class="header">{{item.cate_name}}</view>
                <view class="cate-list">
                    <view class="cate-item"  wx:for="{{item.cate_list}}" wx:key="{{index}}" wx:for-item="cateList">
                        <image src="{{cateList.item_img}}" />
                        <text>{{cateList.item_name}}</text>
                    </view>
                </view>
            </view>
            
        </view>
    </scroll-view>
</view>
Copy the code

js:

const app=getApp();

Page({

  /** * initial data for the page */
  data: {
    cate_nav_list:[
      {name:"New".id:"new"},
      {name:"Mobile phone".id:"phone"},
      {name:"Television".id:"tv"},
      {name:"Computer".id:"laptop"},
      {name:"Home appliances".id:"appliance"},
      {name:"Routing".id:"router"},
      {name:"Smart".id:"smart"},
      {name:"Children".id:"kids"},
      {name:Lamps and lanterns "".id:"lignts"},
      {name:"Power".id:"adapter"},
      {name:"Headphones".id:"headset"},
      {name:"Speaker".id:"voicebox"},
      {name:"Life".id:"life"},
      {name:"Service".id:"service"},
      {name:"Rice noodle card".id:"card"}].curIndex:0.// initialize the current subscript to 0
    toView:"new".// Display new product by default
    detail:[]
  },
  switchCategory(e){
    constcurIndex=e.currentTarget.dataset.index? e.currentTarget.dataset.index:0;  // Get the id of each menu
    // Update data
    this.setData({
      toView:e.currentTarget.dataset.id,
      curIndex
    });
  },
  onLoad: function (options) {
    const detail=app.globalData.category; // Get classified display data
    this.setData({ detail }); }})Copy the code

Discovery page

Page structure analysis:

So here’s the document

4. Product Details page

Click here for a quick look
Product overview and parameter configuration

Of course, to use weui you have to import its style file, which we did in app.wxss, and it’s available globally

@import "./lib/weui.wxss";
Copy the code

Well, weui’s official website and Github address are a must. Read code on Github is a very effective way to learn, but folder nesting is too deep to find a file is not easy, here offer github reading artifact

Weui used: Allow me to post a copy of weui’s structure

<view class="weui-cells">
    <view class="weui-cell">
        <view class="weui-cell__bd">
            <view class="title">{{goods.header}}</view>
            <view class="desp">{{goods.description}}</view>
            <view class="meta">{{goods.meta}}</view>
        </view>
    </view>
</view>
Copy the code

Display of product details page

Logical analysis: Each item uses its ID to jump to the corresponding detail page, but where is this ID? Because the detail page is opened by item first, when the item detail page is loaded, we can get the query parameter (json data) called to open the current page in onLoad. Because only id is used to jump to the showDetail, options only has the ID attribute

onLoad: function (options) {
    console.log(options); //{id:"4"}
    const id=options.id; // Get the id in options
    const goods=app.globalData.goodsDetail.filter(item= >{
      return item.id==id;  // Filter the display of the corresponding item by id
    });
    this.setData({
      goods:goods[0] // Since the id is unique, the array filtered above has only one piece of data, which is the item data to display
    });
  }
Copy the code

Commodity picture preview implementation

Wechat applet provides us with the wx.previewImage() method to achieve the image preview, the implementation method is as follows:

previewImage(e){
    const index=e.currentTarget.dataset.index;	// Get the index of the image in swiper
	const slide=this.data.goods.goods_slides; // Get the commodity rotation map
    const imgList=[]; // Define an array to hold the url of the multicast graph
	slide.map(item= >{
        imgList.push(item.slide_url); // Use the js map method to extract the url address of the image into the array
    });
	wx.previewImage({
	    current: imgList[index], // The link to the currently displayed image defaults to the first url of the urls
		urls: imgList
	})
  }
Copy the code

5. Selection of commodity attributes

bindsubmit

radiogroup
bindchange

selectVersion(e) {
    const version = e.detail.value;
    const memory = version.split(",") [0];
    const price = version.split(",") [1];
    wx.setStorageSync('memory', memory);
    wx.setStorageSync('price', price);
    this.setData({
      memory,
      price
    });
  },
  selectColor(e) {
    let color = e.detail.value;
    let cover_img=this.data.goods_attrSelect[0].goods_slides[0].slide_url;
    wx.setStorageSync('color', color);
    wx.setStorageSync('cover', cover_img);
    this.setData({
      color,
      cover_img
    });
  },
  colorHasSelected(e) {
    const curcIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;
    console.log(curcIndex);
    this.setData({
      curcIndex
    });
  },
  versionHasSelected(e) {
    const curvIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;
    console.log(curvIndex);
    this.setData({
      curvIndex
    });
  }
Copy the code

Jump to the property page of the corresponding commodity

Logical analysis: In the product details page, jump to the current product ID

toSelect(e){
    const id=e.currentTarget.dataset.id;
    wx.navigateTo({
      url:`.. /selectGoods/selectGoods? id=${id}`
    });
 }
Copy the code

In the page of commodity attribute selection, it also displays the attribute selection information of different commodities through ID screening

onLoad: function (options) {
    const id = options.id;
    console.log(id);
    const goods_attrSelect = app.globalData.goodsDetail.filter(item= > {
      return item.id == id;
    });
}
Copy the code

Linkage selection of commodity attributes

Since it is a commodity, how can it do without attribute selection? When the mood is to write without saying anything. But here’s the rub: diversity of choices. Do you list all the choices a user might make? God, commodities so much, this is to tired to death me 😱? No, no, no, that’s not the way to go. How can there be a solution? The idea was to use data caching. Well, that works, but there’s a big problem with using caching to access user-selected values: The data cache in wechat mini program stores data in the key specified in the local cache, overwriting the original content corresponding to the key, whether wx.setStorage(asynchronous interface) or wX. setStorageSync (synchronous interface). In this way, no matter how many items the user selects, As long as the key value is the same, there is only one cached data!! My heart at this time is painful.

submit(e) {
    const pre_item = wx.getStorageSync('attr_item');
    const temp = {
      'goods_name': wx.getStorageSync('goods_name'),
      'memory': wx.getStorageSync('memory'),
      'price': wx.getStorageSync('price'),
      'color': wx.getStorageSync('color'),
      'select_num': wx.getStorageSync('select_num'),
      'cover': wx.getStorageSync('cover'),
      'selected': false.'isTouchMove': false
    }
    wx.setStorageSync('attr_item', [temp, ...pre_item]); // Store the cached pre_item and temp data into attr_item
    wx.showToast({
      title: 'Added to cart'.icon: 'success'.duration: 3000,
      success() {
        setTimeout((a)= > {
          wx.navigateBack({
            url: ".. /goods/show"
          });
        }, 1000)}}); }Copy the code

The addition and subtraction of the quantity of goods

Implementation idea: bind an event to operate the addition or subtraction of the number of goods, and finally set the number selected by the user to the data cache. Implementation code:

 data: {
    select_num: 1  // The default is 1
  },
minusCount(e) {    // The user subtracts operations
    let select_num = this.data.select_num;
    select_num--;
    if (select_num < 1) {
      return;
    }
    this.setData({
      select_num
    });
    wx.setStorageSync('select_num', select_num);
  },
  addCount(e) {     // The user adds the operation
    let select_num = this.data.select_num;
    select_num++;
    if (select_num > 5) {
      return;
    }
    this.setData({
      select_num
    });
    wx.setStorageSync('select_num', select_num);
  }
Copy the code

6. Shopping cart operation

<view wx:if="{{cart_list==''}}">
    <view class="empty-cart">
        <view class="cart-icon">
            <image src=".. /.. /assets/icons/cart_empty.png" mode="aspectFill" />
        </view>
        <view class="prompt">The shopping cart is still empty</view>
        <button type="warn" class="btn-warn" style="background: #ff6700;" bindtap="goIndex">Visit Xiaomi Mall</button>
    </view>
</view>
<view wx:else>
    <view class="cart-box">
        <view class="cart-list" wx:for="{{cart_list}}" wx:key="{{index}}">
            <view class="cart-item {{item.isTouchMove? 'touch-move-active': ''}}" bindtouchstart="touchstart" bindtouchmove="touchmove" data-index="{{index}}">
                <view class="cart-content">
                    <icon type="{{item.selected? 'success':'circle'}}" class="" color="#ff6700" size="20" bindtap="selectList" data-index="{{index}}"
                    />
                    <image src="{{item.cover}}"
                        mode="aspectFill" />
                    <text class="item-title">{{item.goods_name}} {{item.memory}}</text>
                    <text class="item-num">{{item.color}}</text>
                    <text class="item-price">{{item. Select_num}} x</text>
                    <text class="item-price">{{item.price}}</text>
                    <view class="del-cart-item" catchtap="delCartItem">delete</view>
                </view>
            </view>
        </view>
    </view>
    <view class="user-operation">
        <view class="select-all">
            <icon wx:if="{{selectAllStatus}}" type="success" class="total-select" color="#ff6700" bindtap="selectAll" />
            <icon wx:else type="circle" class="total-select" color="#ff6700" size="20" bindtap="selectAll" />
            <text>select all</text>
        </view>
        <view class="total-price">Total:<text>{{totalPrice}}</text>
        </view>
        <view class="btn-primary pay" bindtap="checkOut">settlement</view>
    </view>
</view>
Copy the code

Bottom action bar style

.user-operation{ width: 100%; height: 100rpx; line-height: 100rpx; display: flex; flex-direction: row; justify-content: space-between; align-items: center; position: fixed; left: 0; bottom: 0; } .select-all,.total-price,.btn-primary.pay{ flex: 1; Font-size: 12pt; text-align: center; }Copy the code

Add to shopping cart operation

Logical analysis: the previous solution to the data cache problem is to add shopping cart function. In the cascade selection of item properties, you have all the data that the user wants to add to the shopping cart, and you can just pull it out on the bind to the shopping cart page.

Implementation code:

data: {
    cart_list: [].// Initialize an empty array to hold the shopping cart list
  },
  goIndex() {  // If the cart is empty, send the user to the home page
    wx.switchTab({
      url: ".. /index/index"})},onShow: function () {
    const attr_item = wx.getStorageSync('attr_item'); // Get the data from the data cache to be added to the shopping cart
    let cart_list = this.data.cart_list;
    cart_list = [...attr_item]; // Add the cached data to the shopping cart list
    const select_num = cart_list.map(item= > { // Get the number of times the user selects
      return item.select_num;
    })
    let goods_sum=select_num.reduce(function(prev,cur){
       return prev+cur;  // Use es6's reduce() method to add the numbers selected by the user each time
    });
    wx.setStorageSync('goods_sum', goods_sum);  // Cache it again
    this.setData({   // Update the shopping cart list
      cart_list
    });
  }
Copy the code

Shopping cart full selection, reverse selection, calculate the total price function

This is a very classic problem, everything involves shopping cart operation, this function is indispensable.

data: {
    cart_list: [].totalPrice: 0,
  },
selectList(e) {
    let selectAllStatus = this.data.selectAllStatus;
    const index = e.currentTarget.dataset.index;
    let cart_list = this.data.cart_list;
    // console.log(cart_list[index].selected);
    constselected = cart_list[index].selected; cart_list[index].selected = ! selected;console.log(selected);
    // If only one of the items in the shopping cart list is cancelled, all selections are cancelled
    const symbol = cart_list.some(cart= > {  // Here we use some() of es6
      return cart.selected === false;
    });
    if (symbol) {  // If false is found, all selections are cancelled
      this.data.selectAllStatus = false;
    } else {
      this.data.selectAllStatus = true;
    }
    this.setData({  // Update data
      cart_list,
      selectAllStatus: this.data.selectAllStatus
    });
    this.getTotalPrice();
  },
  getTotalPrice() {  // Define a method to calculate the total price
    let cart_list = this.data.cart_list;
    let totalPrice = 0;
    for (let i = 0; i < cart_list.length; i++) {
      if (cart_list[i].selected) {
        totalPrice += parseInt(cart_list[i].select_num) * parseInt(cart_list[i].price);  // Note that parseInt() is used to fetch the quantity and price}}// Update the total price
    this.setData({
      totalPrice
    });
  },
  selectAll(e) {
    let selectAllStatus = this.data.selectAllStatus; selectAllStatus = ! selectAllStatus;let cart_list = this.data.cart_list;
    for (let i = 0; i < cart_list.length; i++) {
      cart_list[i].selected = selectAllStatus; // If all is true, all shopping cart lists are true, if all is false, all shopping cart lists are false
    }
    // Update data
    this.setData({
      cart_list,
      selectAllStatus
    });
    this.getTotalPrice();
  }
Copy the code

Delete shopping cart operation

data: {
    startX: 0.// Start coordinates
    startY: 0,},// Slide event handling
  touchmove(e) {
    let
      index = e.currentTarget.dataset.index, // Get the current index
      startX = this.data.startX, // Get the starting X coordinate
      startY = this.data.startY, // Get the starting Y coordinate
      touchMoveX = e.changedTouches[0].clientX, // Slide to change coordinates
      touchMoveY = e.changedTouches[0].clientY, // Slide to change coordinates
      // Get the sliding Angle
      angle = this.getAngle({
        X: startX,
        Y: startY
      }, {
        X: touchMoveX,
        Y: touchMoveY
      });
    this.data.cart_list.forEach(function (v, i) {
      v.isTouchMove = false
      
      if (Math.abs(angle) > 30) return;// If the user slides over 30 degrees, the delete button does not come out
      if (i == index) {
        if (touchMoveX > startX) / / right slide
          v.isTouchMove = false
        else / / left smooth
          v.isTouchMove = true}})// Update data
    this.setData({
      cart_list: this.data.cart_list
    })
  },
  getAngle(start, end) {
    let X = end.X - start.X,
      Y = end.Y - start.Y
    Math.atan() returns the arctangent of the number
    return 360 * Math.atan(Y / X) / (2 * Math.PI);
  },
  delCartItem(e) {
    const index=e.currentTarget.dataset.index;  // Get the subscript of the item to be deleted from the shopping cart
    this.data.cart_list.splice(index, 1);
    wx.clearStorageSync("select_num");
    this.setData({
      cart_list: this.data.cart_list
    });
  }
Copy the code

7. Product matching and search function realization

<import src=".. /.. /templates/goods_list/goods_list.wxml" />
<view class="weui-search-bar">
    <view class="weui-search-bar__form">
        <view class="weui-search-bar__box">
            <icon class="weui-icon-search_in-box" type="search" size="14"></icon>
            <input type="text" class="weui-search-bar__input" placeholder="Search" placeholder-class="plac" bindinput="searchInput" />
        </view>
    </view>
    <view class="weui-search-bar__cancel-btn" bindtap="search">search</view>
</view>
<view class="search-list {{is_hidden? 'hidden':''}}">
    <block wx:for="{{search_list}}" wx:key="{{item.id}}">
        <text class="search-item" bindtap="showItemDetail" data-header="{{item.header}}">{{item.header}}</text>
    </block>
</view>
<template is="goods_list" data="{{goods_list}}"></template>
Copy the code

Logical analysis: My implementation idea is:

  • If the product is matched, the search box should be displayed below the search prompt box;
  • If the entered search content is empty, the search prompt box is hidden
  • When the user clicks the search button, the list of all matched commodities will be displayed. It should be noted that the search should be fuzzy and case-insensitive to improve the user experience.
  • The user clicks on the matching item and searches for the item

Implementation method:

  • filter()+indexOf()+toLowerCase();

The code is as follows:

import showDetail from ".. /.. /modules/showDetail";
const app=getApp();

Page({

  /** * initial data for the page */
  data: {
    goods_list: [].search_list: [].is_hidden:true
  },
  searchInput(e){
    let search_list=this.getList(e.detail.value); // Get the user's input value
    if(e.detail.value=="") {// If the user does not enter, the search prompt list is empty and the search prompt box is hidden
      search_list=[]; 
      this.data.is_hidden=true;
    }else{
      this.data.is_hidden=false;
    } 
    // Update data
    this.setData({
      search_list,
      is_hidden:this.data.is_hidden
    });
  },
  search(e){
     // Filter items by keyword. If the keyword matches the item name, the list of items is returned
    const keywords=wx.getStorageSync('keywords');
    wx.showLoading({
      title: 'Just a moment, please.'}); setTimeout((a)= >{
      this.setData({
        goods_list:this.getList(keywords),
        is_hidden:true  // If an item is found, hide the search box
      });
      wx.hideLoading();
    },500);
  },
  showDetail,
  showItemDetail(e){
    // Filter items by keyword. If the keyword matches the item name, the list of items is returned
      const header=e.currentTarget.dataset.header.toLowerCase(); 
      console.log(header);
      wx.showLoading({
        title: 'Just a moment, please.',
      })
      setTimeout((a)= >{
        wx.hideLoading()
        this.setData({
          goods_list:this.getList(header),
          is_hidden:true
        });
      },500)},/** * attr: data to be filtered */
  getList(attr){  // Define a method to get the title of the item
    return app.globalData.phone.goods_list.filter(item= >{
      return item.header.toString().toLowerCase().indexOf(attr)>- 1; }); }})Copy the code

8. Delivery address page

// pages/address/address.js
Page({
  data: {
    receiverName: "".mobile: "".addressDetail: "".postCode: "".isDisabled: false.isComplete: false.buttonTitle: "Save"
  },
  formSubmit(e) {
    const addrInfo = e.detail.value;
    let {receiverName,mobile,addressDetail,postCode}=addrInfo; // Put the data structure in the data
    if(receiverName==""||mobile==""||addressDetail==""||postCode=="") {this.data.isComplete=false;
      wx.showModal({
        title:"Tip".content:"Please complete the information.".showCancel:false
      }); 
    }else if(!,4,5,7,8 / ^ [1] [3] \ d {9} $/.test(mobile)){ // Determine the phone number format
      wx.showModal({
        title:"Tip".content:"Mobile phone number format is not standard".showCancel:false
      }); 
    }else if(!/ ^ [0-9] {6} $/.test(postCode)){
      wx.showModal({
        title:"Tip".content:"No standard zip code".showCancel:false
      }); 
    }else{
      this.data.isComplete=true;
      wx.setStorageSync('addrInfo', addrInfo);
      
    }
    this.setData({
        isDisabled: true.isComplete: this.data.isComplete
      });
  },
  updateAddr(e){
    this.setData({
      isDisabled:false.isComplete:false.buttonTitle: "Save"
    });
  },
  /** * lifecycle function -- listens for page loading */
  onLoad: function (options) {
    
    let addrInfo=wx.getStorageSync("addrInfo");
    console.log(addrInfo);
    let {receiverName,mobile,addressDetail,postCode}=addrInfo;
    this.setData({
      receiverName,
      mobile,
      addressDetail,
      postCode,
      isDisabled: true.isComplete:true.buttonTitle: "Change"}); }})Copy the code

Conclusion:

When doing the project encountered many problems, because a problem is halfway to for a long time, but now think about, experience is certainly can learn things, for some things can’t even think about before, but it doesn’t matter, as long as you want to do, go for it, to find information online, how to community ask Daniel, you can always learn something. For this project, many functions have not been completed, such as product comments, order generation and so on, but I will update 😊 from time to time. If I have time, I will use MPvue or wepy to rewrite, and I can learn new technology 😄

The last:

Code word is not easy, if you like, star it, the project address, I will not update oh. There are still many defects in the project, we hope you can put forward valuable suggestions 🐵