Wechat mini program – Mi Lite

For the record, this is a highly imitation of Xiaomi Lite micro – app.

I am now a junior and senior students, this small program took me a long time to write the function can basically write. I hold open source to share the psychology, as far as POSSIBLE I wrote this small program how to write, why to write, tell you in detail. Why try? That’s because I’m not very good at it, probably not very clear, so I have to try.

Project preview

Tools used

  1. easy-moke
  2. VSCode
  3. Wechat small program developer tools
  4. (Alibaba Vector Icon Library)

File directory

├ < assets > │ ├ > < images ├ < components > │ ├ < goodList > │ ├ < icon > │ ├ < tabbar > │ ├ < userList > ├ < pages > │ ├ < cart > │ ├ < category > │ ├ < deleteGoods > │ ├ < find > │ ├ < goodDetails > │ ├ < index > │ ├ < selectGoods > │ ├ < user > ├ < utils > │ └ util. Js ├ < weui > │ ├ ├.txt │ ├.txt ├.txt ├.txtCopy the code

For beginners, they may get the design drawing and write it right away. In fact, this is not good. The code written will have a lot of duplicate code, which is not conducive to the maintenance of the future. Therefore, some common code should be encapsulated, and then directly called on the line, after maintenance is also more convenient.

API package

When our front end wants to get the data from the page, we need to send an HTTP request to the API interface provided by the back end to get the data we want from the API interface. In wechat mini program, wechat official provides us with a method wx.request to request.

A program needs a lot of HTTP requests. If we write a Wx. request for each request, the code written in this way will look very long, and others will be tired when looking at our code, which is not conducive to our subsequent modification. So in order to clean the code, and easy to modify. I’m just going to wrap all of my API requests in a wXAPI file directory.

// Api.js
const banners = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/banners'

const navdata = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/navdata'

const goodList = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/goodList'

const category = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/category'

const findData = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/findData'

const userData = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/userData'

const goodDetail = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/goodDetail'

const QQ_MAP_KEY = 'NNFBZ-6DRCP-IRLDU-VEQ4F-TXLP2-PFBEN'

const MAPURL = 'https://apis.map.qq.com/ws/geocoder/v1/'

module.exports = {
  banners,
  navdata,
  goodList,
  category,
  findData,
  userData,
  goodDetail,
  QQ_MAP_KEY,
  MAPURL
}
Copy the code
import * as MOCK from "./mock"
import * as API from "./Api"
const request = (url,mock = true,data) = > {
  let _url = url
  return new Promise((resolve, reject) = > {
    if (mock) {
      let res = {
        statusCode: 200.data: MOCK[_url]
      }
      if (res && res.statusCode === 200 && res.data) {
        resolve(res.data)
      } else {
        reject(res)
      }
    } else {
      wx.request({
        url: url,
        data,
        success(request) {
          resolve(request.data)
        },
        fail(error) {
          reject(error)
        }
      })
    }
  });
}
// showLoading
const showLoading = (a)= > {
  wx.showLoading({
    title: 'Data loading'.mask: true}); }// Get the location
const geocoder = (lat, lon) = > {
  return request(API.MAPURL,false, {location: `${lat}.${lon}`.key: API.QQ_MAP_KEY,
    get_poi: 0})}module.exports = {
  getBanners: (a)= > {
    // return request('banners')
    return request(API.banners,false)  / / home page banners
  },
  getNavData: (a)= > {
    // return request('navdata')
    return request(API.navdata,false) / / navdata home page
  },
  getGoodList: (a)= > {
    // return request('goodList')
    return request(API.goodList,false)  // Home product list
  },
  getCategroy: (a)= > {
    // return request('category')
    return request(API.category,false)  // Category page
  },
  getFindData: (a)= > {
    // return request('findData')
    return request(API.findData,false)  // Discover page
  },
  getUserData: (a)= > {
    // return request('userData')
    return request(API.userData,false)  // My page
  },
  getGoodDetail: (a)= > {
    // return request('goodDetail')
    return request(API.goodDetail,false)  // Product details
  },
  showLoading,
  geocoder
}
Copy the code

At this point, you might wonder, why do I add a false to every request?

This is because WHEN I started writing this wechat applet, I didn’t use easy-mock to simulate HTTP request data. I put all the fake data in the mock.js file. Then I try to get the data I want by using a **return request(‘ clearly ‘)**.

When the API is wrapped, how do I call it? I’ll take my clearly passionate data on the front page as an example

// index.js 
const WXAPI = require('.. /.. /wxapi/main')

onLoad: function (options) {
    WXAPI.showLoading()
    this.getBanners()
},
getBanners() {
    WXAPI
    .getBanners()
    .then(res= > {
      wx.hideLoading()
      this.setData({
        banners: res.data
      })
    })
},
Copy the code

Remember, if you want to send HTTP request data to the page, you must add the line const WXAPI = require(‘.. /.. /wxapi/main’)


Defined components

OK, let’s start writing the page. The first step is to write the tabBar section.

TabBar component

Doesn’t it look a little weird? Why is it kind of transparent? Because I wrote the tabBar component myself.

You can write tabBar components directly into app.json.

But I didn’t think it looked that good, so I lugged a tabBar component out myself.

After writing the document, I found that the wechat applets officially provided a method to customize tabBar components. If necessary, you can check the wechat applets document

I’ve always solved some of the problems that I need to pay attention to after writing this component.

  • Select the current page, click again because this is invalid.

    So I stored a page property in app.js to store the current page, and then added a judgment to the click event goToPage() method to resolve it.

<! --components/tabbar/tabbar.wxml-->
<view class="tabbar">
  <! - home page - >
  <view class="shouye {{on === 'index' ? 'on': ''}}" data-page="index" bindtap="goToPage">
    <icon type="shouye" size="42" class="icon" color="{{on === 'index' ? '#f96702': ''}}"/>
    <text >Home page</text>
  </view>
  <! - classification - >
  <view class="fenlei {{on === 'category' ? 'on': ''}}" data-page="category" bindtap="goToPage">
    <icon type="classify" size="42" class="icon" color="{{on === 'category' ? '#f96702': ''}}"/>
    <text >classification</text>
  </view>
  <! - found - >
  <view class="faxian {{on === 'find' ? 'on': ''}}" data-page="find" bindtap="goToPage">
    <icon type="faxian" size="42" class="icon" color="{{on === 'find' ? '#f96702': ''}}"/>
    <text >found</text>
  </view>
  <! -- Shopping cart -->
  <view class="gouwuche {{on === 'cart' ? 'on': ''}}" data-page="cart" bindtap="goToPage">
    <icon type="gouwuche" size="42" class="icon" color="{{on === 'cart' ? '#f96702': ''}}"/>
    <text >The shopping cart</text>
  </view>
  <!-- 我的 -->
  <view class="wode {{on === 'user' ? 'on': ''}}" data-page="user" bindtap="goToPage">
    <icon type="wode" size="42" class="icon" color="{{on === 'user' ? '#f96702': ''}}"/>
    <text >my</text>
  </view>
</view>
Copy the code
/ / components/tabbar tabbar. Js / / global inside put a page said that the current routing const app = getApp (); Component({/** * Component property list */ properties: {// Check whether on:{type: String,
      value: ' '}}, components of the initial data * * * * / data: {}, / * * * the method of component list * / the methods: GoToPage (e) {// goToPage(e) {// goToPage(e) {let page = e.currentTarget.dataset.page || 'user';
      if(app.globalData.page === page) {
        return ;
      }
      wx.redirectTo({
        url: `/pages/${page}/${page}`}); app.globalData.page = page; }}})Copy the code
/* components/tabbar/tabbar.wxss */
.tabbar {
  width: 100%;
  height: 100rpx;
  background-color: #ffffff;
  display: flex;
  position: fixed;
  bottom: 0;
  font-size: 26rpx;
  z-index: 99;
}
.shouye,.fenlei,.faxian,.gouwuche,.wode {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  opacity: 0.5;
}
.icon {
  height: 60rpx;
}
.on {
  color:#f96702;
}
Copy the code

The question of how to use it is simply added to the bottom of the page where tabBar is required.

Like the Index page

<tabbar on="index"></tabbar>
Copy the code

Remember to include components in JSON

{
  "usingComponents": {
    "goodList": ".. /.. /components/goodList/goodList"."tabbar": ".. /.. /components/tabbar/tabbar"}}Copy the code

Icon component

TabBar components need ICONS, I used Ali’s icon library

How to use it?

  1. First go to the icon library to find the icon you want, add to the shopping cart.
  2. Then add it to the project and create a new one yourself.
  3. On the next download, copy all the contents of the CSS file into the WXSS file.

This component is simple enough to define and use, and to change the color and size.

<! --components/icon/icon.wxml--> <text class='iconfont icon-{{type}}' style='color:{{color}}; font-size:{{size}}rpx; '></text>
Copy the code
properties: {
    type: {
      type: String,
      value: ' '
    },
    color: {
      type: String,
      value: '# 000000'
    },
    size: {
      type: Number,
      value: '45'}},Copy the code

GoodList components

There are a lot of such items in the home page, one by one, so the written code would make the home page code too much, and difficult to maintain, so I packaged it into a component.

<! --components/goodList/goodList.wxml--> <view class="goodList-good"> <! --> <view class="goodList-good-img">
    <image src="{{url}}" mode="aspectFill"/> </view> <! --> <view class="goodList-good_detail"> <! -- name --> <view class="good_detail_name"> {{name}} </view> <! -- Information --> <view class="good_detail_brief"> {{brief}} </view> <! --> <view class="good_detail_price">
      <text class="price" >¥{{price}}</text>
      <text class="oldPrice" style="display:{{oldPrice == '' ? 'none': 'inline'}};">¥{{oldPrice}}</ view> </view> </view>Copy the code
Properties: {// image url: {type: String,
      value: ' '}, // name name: {type: String,
      value: ' '}, // message brief: {type: String,
      value: ' '}, // New price: {type: String,
      value: ' '}, // oldPrice: {type: String,
      value: ' '}},Copy the code
/* components/goodList/goodList.wxss */

.goodList-good {
  position: relative;
  width: 100%;
  height: 100%;
}
.goodList-good-img {
  width: 100%;
  height: 312rpx;
  position: relative;
}
.goodList-good-img image {
  width: 100%;
  height: 100%;
}
.goodList-good_detail {
  padding: 26rpx 23rpx;
}
.good_detail_name {
  width:100%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
}
.good_detail_brief {
  width:100%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  font-size: 25rpx;
  color: #8c8c8c;
}
.good_detail_price {
  display: flex;
  justify-content: flex-start;
  align-items: flex-end;
}
.good_detail_price .price {
  color: #a36d4a;
  font-size: 28rpx;
  padding-right: 16rpx;
}
.good_detail_price .oldPrice {
  font-size: 24rpx;
  color: #8c8c8c;
  text-decoration: line-through;
}
Copy the code

You’ll see why MY borders are so thin.


How to draw the 0.5px border

A beginner might say that a 0.5px border is border: 0.5px, but this is not true.

The browser will parse any border less than 1px to 1px, so if you write 0.5px the browser will parse it to 1px and it won’t work.

It’s actually very easy to draw using pseudo-classes.

For example, the right border of the goodList component.

In the HTML of the Index page, I added the rightBorder class to the view tag class that wraps the goodList to draw the top border.

<view class="item topBorder rightBorder" data-id="{{item.id}}" bindtap="goDetails">
  <goodList url="{{item.url}}"
    name="{{item.name}}"
    brief="{{item.brief}}"
    price="{{item.price}}"
    oldPrice="{{item.oldPrice}}" ></goodList>
</view>
Copy the code
.rightBorder::after {
  content: ' ';
  position: absolute;
  height: 200%;
  width: 1rpx;
  right: -1rpx;
  top: 0;
  transform-origin: 0 0;
  border-right: 1rpx solid#e0e0e0;
  transform: scale(.5);
  z-index: 1;
}
Copy the code

In fact, draw a 0.5px border to remember.

  1. Use pseudo classes, and position: absolute;
  2. If you want to draw a border up and down, set width to 200%, left and right to 200% height
  3. Then use transform: scale(.5); Reduce the width and height by 0.5 times to create a 0.5px border.

There are a few other details just write what you need.


The userList components

It’s just a list of information on my page. It’s very simple

<! --components/userList/userList.wxml--> <view class="main">
  <image src="{{List.img}}" />
  <view class="text" >
    <text >{{List.text}}</text>
  </view>
  <view class="state" wx:if="{{List.state ! = = '}}">
    <text >({{List.state}})</text>
  </view>
</view>
Copy the code
/* components/userList/userList.wxss */
.main {
  width: 100%;
  height: 120rpx;
  display: flex;
  align-items: center;
  background-color: #fff;
  padding: 40rpx;
  box-sizing: border-box;
}
.main image {
  width: 80rpx;
  height: 80rpx;
}
.main .text {
  font-size: 32rpx;
  padding: 0 10rpx 0 5rpx;
}
.main .state {
  font-size: 26rpx;
  color: #8c8c8c;
}
Copy the code
properties: {
    List: {
      type: Object
    }
  },
Copy the code

Page and function description

Home Page Search section

What I’m introducing here is the search style for weUI components. How to use?

  1. Download WEUI small program version, which can be opened in wechat developer tools.
  2. Put the styly folder weui. WXSS in your project’s Weui folder
  3. In app.wxss @import “./weui/weui.wxss”. It’s ready to use

Home page rotation part

This is a component of wechat applets provided by Swiper, wechat applets developer documentation

Swiper and swiper-item can be used together. Please check the official documentation for configuration information

Specific code

<swiper indicator-dots="{{indicatorDots}}" indicator-active-color="#ffffff" autoplay="{{autoPlay}}" interval="{{interval}}" duration="{{duration}}">
    <block wx:for="{{banners}}" wx:key="index">
      <swiper-item>
        <image src="{{item.imgurl}}" mode="aspectFill" class="banner-image" />
      </swiper-item>
    </block>
  </swiper>
Copy the code
 data: {
    banners: [],
    indicatorDots: true,
    autoPlay: true,
    interval: 3000,
    duration: 1000,
    navdata: [],
    goodList: [],
    goodListOne: {},
    name:' ',},Copy the code

A commonly used feature

In the mall small program often do such a function. Such as:

Functional requirements:

  1. Click the product list on the left, and the product information on the right will slide to the corresponding position.
  2. Swipe the item information on the right and the item list on the left will be highlighted accordingly.

The functional requirements are not difficult, but can be problematic for beginners. I’m just going to say what do I do with features

First: analyze the page structure is left and right layout. And you can slide on both sides. So we can use what wechat provides for us

Scroll – the view components. Two components can be float, distributed on the left and right sides.

<! -- miniprogram/pages/category/category.wxml --> <view class="container"> <! <scroll-view scroll-y scroll-with-animation="{{true}}" class="categroy-left">
    <view wx:for="{{categroy}}" wx:key="{{index}}" data-index="{{index}}" bindtap="switchTab" class="cate-list {{curIndex === index ? 'on': ''}}"> {{item[0].name}} </view> </scroll-view> <! --> <scroll-view scroll-y scroll-into-view="{{toView}}" scroll-with-animation="true" bindscroll="scrollContent" bindscrolltolower="scrollEnd" class="categroy-right">
    <block wx:for="{{categroy}}" wx:key="inedx">
      <view id="right-list" class="right-list" id="{{index}}">
        <view class="right-title">
          <text>{{item[0].name}}</text>
        </view>
        <view class="right-content">
          <block wx:for="{{item}}" wx:key="idex" wx:for-item="product" wx:for-index="idex">
            <view class="list-detail" wx:if="{{idex > 0}}">
              <image src="{{product.picture}}" />
              <view class="detail-name">
                <text>{{product.desc}}</text>
              </view>
            </view>
          </block>
        </view>
      </view>
    </block>
  </scroll-view>
</view>
<tabbar on="category"></tabbar>

Copy the code
/ * miniprogram/pages/category/category. WXSS * / / * definition scroll bar height to width and background High width corresponding to the relation of scroll bar size * / : : - its - scrollbar {width: 0 px; height: 0px; background-color: pink; } .categroy-left { height: 100%; width: 150rpx;float: left;
  border-right: 1px solid #ebebeb;
  box-sizing: border-box;
  position: fixed;
  font-size: 30rpx;
  padding-bottom: 100rpx;
  box-sizing: border-box;
}
.categroy-left .cate-list {
  height: 90rpx;
  line-height: 90rpx;
  text-align: center;
  border: 2px solid #fff;
}
.categroy-left .cate-list.on {
  color: #ff4800;font-size: 34rpx; } /* List */.categroy-right {width: 600rpx;float: right; 
  height: 1334rpx;
  /* height: 100%; */
  padding-bottom: 100rpx;
  box-sizing: border-box;
  overflow: hidden;
}
.right-title {
  width: 100%;
  text-align: center;
  position: relative;  
  padding-top: 30rpx;
  /* font-size: 30rpx; */
  padding-bottom: 30rpx;
}
 .right-title text::before, .right-title text::after {
  content: ' ';
  position: absolute;
  width: 60rpx;
  /* height: 1px; */
  top: 50%;
  border-top: 1px solid #e0e0e0;
  /* transform: scale(.5); */
}
.right-title text::before { 
  left: 30%;
}
.right-title text::after {
  right: 30%;
}
.right-list {
  /* height: 100%; */
  background-color: #fff;
}
.right-content {
  width: 100%;
  height: 100%;
  display: flex;
  flex-wrap: wrap;
}
.right-content .list-detail {
  flex-shrink: 0;
  width: 33.3%;
  height: 100%;
  font-size: 26rpx;
  text-align: center;
  
}
.right-content .list-detail image {
  width: 120rpx;
  height: 120rpx;
  padding: 10rpx;
  /* background-color: pink; */
}
Copy the code

The difficulty with this feature lies in the JS logic

Post the required data in data first

Data: {categroy:[], //'A'// The current selected tag toView:'A', // The gone tags // Are highlighted in each list by heightening the heightArr: [], // The last list is the ID of the last tag endActive:'A'
  },
Copy the code

Click left and right to swipe

This feature is very simple to implement

Just add the event scroll-into-view=”{{toView}}” to the right scroll view component, where toView is the id of the item displayed

Note that for each item on the right, the page must be rendered with an ID attribute

Then the scroll View component on the left simply adds a click event to modify the toView value

SwitchTab (e) {this.setData({curIndex: e.target.dataset. Index, toView: e.target.dataset. Index})},Copy the code

Swipe right and highlight left to change

  1. The first thing you need to do is figure out how high each piece of the item on the right occupies and store it in an array that you can put into the onReady life cycle

    // Calculate the height occupied by each item on the rightgetPageMessage() {
        // console.log(4)
        let self = this
        let heightArr = []
        let h = 0
        const query = wx.createSelectorQuery()
        query.selectAll('.right-list').boundingClientRect()
        query.exec( res => {
          res[0].forEach( item => {
            h += item.height
            heightArr.push(h)
          })
          self.setData({
            heightArr: heightArr
          })
        })
      },
    Copy the code
  2. Add events to the scroll View component on the right. Bindscroll equals “scrollContent, which is the event that the ScrollView provides, which is triggered when it slides.

    // scrollContent(e) {const scrollTop = E.desail. scrollTop const scrollArr = this.data.heightarr const length = scrollArr.length - 1let endChar = String.fromCharCode(65 + length)
        let curChar = this.getCurrentIndex(scrollTop)
        if(this.data.endActive ! = endChar) { this.setData({ curIndex: curChar }) }else {
          this.setData({
            endActive: 'A'})}},Copy the code
    // The curIndex should be the getCurrentIndex(scrollTop) {const scrollArr = this.data.heightarrletFind = scrollarr.findIndex (item => {// trigger effect 10rpx earlierreturn scrollTop < item - 10
        })
        let curChar = String.fromCharCode(65 + find)
        return curChar
      },
    Copy the code

    This will fulfill all the functional requirements.

    But this slide is not perfect, right slide to the bottom, left highlight is not the last

    That’s what relative perfection looks like

To make it perfect, I’m going to add an event to the right scroll view: BindScRolltolower =”scrollEnd”

// The page slides to the bottomscrollEnd() {
    const scrollArr = this.data.heightArr
    const length = scrollArr.length - 1
    let endChar = String.fromCharCode(65 + length)
    this.setData({
      curIndex: endChar,
      endActive: endChar
    })
  },
Copy the code

Shopping logic

It’s not that hard to pull off.

Logical order: Click product information on the home page -> Product details page to display the corresponding product details -> Shopping cart page to display the product information purchased. -> After modification, the product details page will display the modified information.

To achieve such a function, an ID must be passed to the page when the page jumps, and the page jumps to obtain the data required by the page through the ID value

For example: Home page -> Product details page

This is information about a list of items, which jumps to the corresponding page by clicking on the event bindtap=”goDetails”.

<view class="list">
      <block wx:for="{{goodList}}" wx:key="{{item.id}}">
        <view class="item topBorder rightBorder" data-id="{{item.id}}" bindtap="goDetails">
          <goodList url="{{item.url}}"
            name="{{item.name}}"
            brief="{{item.brief}}"
            price="{{item.price}}"
            oldPrice="{{item.oldPrice}}" ></goodList>
        </view>  
      </block>
    </view>
Copy the code
goDetails(e) { const id = e.currentTarget.dataset.id wx.navigateTo({ url: `/pages/goodDetails/goodDetails? id=${id}`}); },Copy the code

Product Details Page:

The id value passed in can be retrieved from the options parameter of the onLoad life cycle

onLoad: function(options) {wxapi.showloading () // Get user address const address = wx.getStoragesync (options) {wxapi.showloading ()'Address');
    this.setData({
      id: options.id,
      address
    })
    this.getGoodDetail()
  },
Copy the code

Data storage logic

I am storing the data directly in the local cache (or directly in the cloud database) using wx.setStorage()

Two data are stored locally, one is the information of all goods purchased, the other is the total quantity of goods purchased

// Add to carttoAddCart() {
    let cartData = wx.getStorageSync('goods') | | [];let data = {
      id: this.data.id,
      name: this.data.goodData.name,
      memory: this.data.memory,
      color: this.data.color,
      price: this.data.price,
      num: this.data.selectNum,
      img: this.data.imgSrc,
      select: true
    }
    // wx.removeStorageSync('goods');
    cartData.push(data)
    const allNum =this.getAllNum(cartData)
    wx.setStorage({
      key: 'goods',
      data: cartData,
      success: (res) => {
        console.log(res)
        let pageIndex = getCurrentPages()
        letbackIndex = pageIndex.length - 2 wx.navigateBack({ delta: backIndex }) }, fail: () => {}, complete: () => {} }); // Storage wx.setStoragesync ('allNum', allNum); // Write it outside to make showToast appear on the previous pagesetTimeout(()=>{
      wx.showToast({
        title: 'Added to cart',
        icon: 'success', duration: 2000 }); },500)}, // Get all quantities getAllNum(cartData) {return cartData.reduce((sum, item) => {
      return sum + (+item.num)
    },0)
  },
Copy the code

Overview of parameter switching

All you need to do is add a state, change the value of the state when clicked, and modify the relevant rendered data.

data: {
 state: 'details_img', // Determine the outline parameters}Copy the code
<view class="summarize-parameter">
    <view class="title">
      <view class="summarize" bindtap="changeState">
        <text class="{{state === 'details_img'? 'on' : ''}}"> Overview </text> </view> <view class="parameter" bindtap="changeState">
        <text class="{{state === 'param_img'? 'on' : ''}}"> Parameter </text> </view> </view> <view class="state">
      <block wx:for="{{state === 'details_img'? details_img : param_img}}" wx:key="index">
          <image src="{{item}}" mode="widthFix"/>
      </block>
    </view>
  </view>
Copy the code
// Change the overview and parameterschangeState() {
    let state = this.data.state
    if(state === 'details_img') {
      state = 'param_img'
    } else {
      state = 'details_img'
    }
    this.setData({
      state
    })
  },
Copy the code

Shopping data changes, product details data modification

Compare the difference between the two pictures above.

The product quantity and specific product information selected in the shopping page will be changed after jumping back to the product details page

<view class="sales" bindtap="goSelectGoods">
      <text class="describe"> Selected </text> <view class="detail detail-change"> {{default_change.name}} {{default_change.memory}} {{default_change.color}} <text >× {{{default_change.num}}</text> </view> <view class="right"></view>
    </view>
Copy the code
<view class="shopping-img" bindtap="goCart">
    <icon type="gouwuche" color="#e0e0e0" size="40"/>
    <text wx:if="{{allNum ! = 0}}">{{allNum}}</text>
  </view>
Copy the code

Above, the two HTML structures are modified

By default, after clicking OK on the shopping page, I added the item to the cart and placed it at the end of the data

The onShow lifecycle function is retriggered when the item details page is returned.

So ALL I have to do is trigger the change method in onShow.

// Change the default version data default_changechangeDefauleChange() {
    const goods = wx.getStorageSync('goods') | | [];if(goods.length === 0) {
      return
    }
    const id = this.data.id
    const default_change = goods[goods.length - 1]
    let memory = default_change.memory.toString()
    memory = memory.substring(0,memory.length - 4)
    default_change.memory = memory
    this.setData({
      default_change
    })
  },
Copy the code

Draw a triangle

This triangle is drawn using CSS, not an icon.

Drawing a triangle using CSS is not that difficult. The pseudo-class and the border attribute are used

.right:before,
.right:after {
  content: ' ';
  position: absolute;
  top: 35%;
  right: 0;
  border-width: 8px;
  /* transform: translateY(10000rpx); */
  border-color: transparent transparent transparent transparent;
  border-style: solid;
  transform: rotate(90deg);
}

.right:before {
  border-bottom: 8px #aaaaaa solid;} .right:after { right: 1px; /* Overlay and stagger 1px*/ border-bottom: 8px#fff solid;
}
Copy the code

Modify the quantity of goods

You can directly use the picker component provided by wechat mini program. Please refer to the documentation for specific configuration

Get your location using Google Maps

Search Tencent map first, and register the developer information, apply for a key key.

Const geocoder = (lat, lon) => {return request(API.MAPURL,false,{
    location: `${lat}.${lon}`,
    key: API.QQ_MAP_KEY,
    get_poi: 0
  })
}
Copy the code

And then I copy the key, because I’ve encapsulated all the APIS. Therefore, api.qq_map_key is used instead. Here, just fill in the application key.

To get the user’s latitude and longitude information, use wx.getLocation().

getLocation() {
    wx.getLocation({
      type: 'gcj02',
      success: this.getAddress,
      fail: () => {
        this.openLocation()
      }
    })
  },
  getAddress(res) {
    let { latitude: lat, longitude: lon} = res
    WXAPI.geocoder(lat, lon)
    .then(res => {
      if(res.status ! = = 0 | |! res.result) {return
      } 
      let {address_component
      } = res.result
      const Address = {
        city: address_component.city,
        district: address_component.district
      }
      wx.setStorageSync("Address", Address); })},Copy the code

Because I did not let the user authorization, so directly to obtain the location, save in the local storage.

The location obtained can then be displayed on the delivery page of the product details

conclusion

The process of doing this project was very happy, without using the cloud function (the page data is not much, I think it can be written without need), so the total writing time is also very short, less than a week to finish. The sense of accomplishment at that moment was also very good. If you find this article helpful, give it a thumbs up! Also, I’d love to see the suggestions below! Finally, here is the source code. Help yourself if you need it!

Finally, a little digress, because I’m a 2020 graduate, and I’m under internship pressure. Because I need some time to read the interview questions, I just briefly wrote out the important functional logic in the following paragraph. Please forgive me if IT is not clear.