From Getting Started to Crashing Doors: Hand in Hand to Teach You to Develop a Small Recording Program

Recently, I developed a small recording program called “I-I” and decided to sum up the knowledge learned during this period from shallow to deep and share it with everyone. If there are any mistakes, I hope the bosses can point out.


  • Application for applets
  • Use of Developer Tools
  • Development of Small Programs
  • Statistics
  • Release
  • Advanced

1. Application for small procedures

The application process of the applet can follow the tutorial of the official website. it should be noted that in the background settings, many items can only be changed 3/5 times a month, and the development-> development settings-> server domain name can only be changed 5 times a month. therefore, it is recommended to plan the contents to be modified in advance, such as the server domain name, and the domain names such as the interface address, picture resource address, and statistical dot address should be filled in uniformly in advance (there is a delay in auditing, which is usually about 1 hour).

In addition, it is better not to use a personal mailbox for the account application, and it is suggested to register a product specifically, otherwise the account handling will be very painful if this colleague leaves office.

2. Use of developer tools


In the details in the upper right corner, you can click on all these options, and if npm module is used, click on that option. If a domain name has not been applied for or has not passed the examination, you can click the last option point and skip the white list check.
If npm module is used, you also need to click tools-> build npm to generate a miniprogram_npm file.
If you use shell commands to control developer tools, you need to open the service port in settings-> security settings-> security. let’s talk about how to use shell commands and what are the benefits of using them later.

3. Development of small programs

3.1 Small Program File Structure

◦ Node _ Modules//Project Dependencies
├── miniprogram_npm
★ Page//Page
├── images
├── .gitignore
├── app.json
├── app.wxss
├── app.js
├── package.json
├── project.config.json

3.2 Development of Custom topbar

Because the “I I” project needs to customize topbar, these problems need to be solved:

Get the distance from the capsule to the top of the mobile phone so that the return button and title can be self-adaptively in the same row as the capsule.

success: function(res) {
that.globalData.comPostInfo = res;
if (res.system.indexOf('iOS') > -1) {
that.globalData.system = 'ios';
that.globalData.paddingTop = res.statusBarHeight + 6;
} else {
that.globalData.system = 'android';
that.globalData.paddingTop = res.statusBarHeight + 10;

viaStatusBarHeight of wx.getSystemInfoThe distance from the capsule to the top of the mobile phone can be obtained, and a few pixels can be added as required to center the text and the capsule.


In addition, the return button should not appear in all cases. When the user is on a first-level page or enters through a two-dimensional code, there should not be a return button at this time (if entering through two-dimensional code or other means, a button to return to the first page should be added). Here, let’s judge as follows:

let that = this;
 Lettabs = ['pages/index/index',' pages/find/find',' pages/msg/msg',' pages/me/me']//4 first-level pages in "me and me"
 let pages = getCurrentPages();
 for (let i = 0;   i < pages.length;  i++) {
 let page = pages[i];
 if (tabs.indexOf(page.route) > -1) {
 } else {
 show: true

viagetCurrentPagesSo as to obtain the current page list and further judge whether a first-level page exists.

Incidentally, there will be a bug when using custom topbar now, that is, Android will not get screenshots when sharing it for the first time. You have to share it once and then cancel sharing it again to get screenshots. To solve this problem, you can only use canvas to generate a sharing map or not use custom topbar at all. (Added: Android’s latest update has solved this bug. )

3.3 Some Use Skills of Tabbar

“I” tabbar icon uses the size of 176×176. It is important to note that the content of the picture should not be full of the whole picture, which will cause tabbar icon to appear very large. It is best to leave a circle of blank around the icon, so the size of the icon is just right.


In addition, I have also done a skin change function before, which can change the style and color of icons and characters. It can be realized as follows:

 index: 0,
 iconPath: `/images/focus${str}.png`,
 selectedIconPath: `/images/focus-on-${color}.png`
 selectedColor: colorStr,
 color: '#767477',
 backgroundColor: '#ffffff'

3.4 First Page Data Cache

In order to prevent a white screen from appearing every time the user enters the home page, I cache the latest data locally every time the user pulls out the first screen data. The user will read the local data first when opening the applet next time. If the new data is pulled out, rendering will be performed again, thus the white screen time will be greatly reduced: = wx.getStorageSync('firstIndexData').list || [];  //Render Local Data
url: url,
type: 'get',
cb: function(e) {
if ( === 0) {
wx.setStorageSync('firstIndexData',;  //store data
hasMore: !  !  ( / 1)

3.5 center rendering of picture

When rendering data, it is necessary to center and adapt the pictures of respective sizes. There are two methods in the applet. One is to directly use the image tag of the applet:

<image class="item-img" lazy-load="true" mode="aspectFill" src="{{itemData.user.avatar}}"></image>

Or by using the picture as the background:

<view class="img-item" style="background-image: url({{item.url}})" data-index="{{index}}" catchtap="showImg"></view>
 .card-item .item-card-imglist .img-item {
 position: relative;
 padding-top: 100%;
 background-position: 50% 50%;
 background-repeat: no-repeat;
 background-size: cover;
 border-radius: 12rpx;

3.6 User Login Status Judgment

Because it is a small recording program, it is necessary to ensure that the user is in the login state so that the user can obtain relevant data. Therefore, it is necessary to judge the login state of the user at any time. This is the official login flow chart of the small program:


A session is required to judge whether the user’s login has expired, while the acquisition of the session requires wx.login to acquire several parameters and initiate a request to the backend to acquire the session:

function getLoginCode() {
 return new Promise(function (resolve, reject) {
 success: function (res) {
 fail: function (e) {
 function getLogin(opt) {
 url: opt.url,
 method: 'post',
 success: function (res) {
 console.log('login:' +;
 if ( === 0) {
 } else {
 function checkSession(opt) {
 getLoginCode().then(e => {
 success: res => {
 url: ......,
 data: {
 code: e.code,
 encryptedData: res.encryptedData,
 iv: res.iv,
 signature: res.signature
 cb: function(e) {
 if (e) {

It can then be passedwx.checkSessionTo determine whether it has expired, but the “I-I” processing method is that after the front end requests the interface each time, the back end directly returns the result; if it has not expired, it returns normal data; if it has expired, it returns the corresponding error code, and the front end reacquires the session through wx.login.

3.7 User Authorization

In order to let the user log in, we must first obtain the user’s information, which requires the user’s authorization. At present, the applet does not support the pop-up of the authorization box directly for the user to authorize. It will pop up only after the user clicks on the button label. “I-I” guides the user’s authorization through a special welcome page:

<button class="welcome-login-btn" open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo"></button>


In addition to the authorization to obtain information, “I-I” also uses the permission to save pictures to photo albums, which will be discussed in the poster section later.

3.8 Implement an Input Box

Since it is a small program of record class, there will naturally be a comment function to facilitate others to make comments on your records, we need to implement a comment box. I used the input tag at the beginning, but only one line of input can not meet the needs of people who want to make large comments, so it is changed to the textarea tag:

<textarea auto-height adjust-position="{{false}}" name="commentInput" class="detail-input" value="{{inputVal}}" show-confirm-bar="{{false}}  " fixed focus maxlength="500" bindfocus="inputFocus" bindinput="inputChange" placeholder="{{placeholder ?  Placeholder:' enter what you want to say' }}"></textarea >

Many self-contained functions of the applet are still very practical. textarea’s auto-height can support the comment box to automatically increase when the content changes. show-confirm-bar can choose whether to hide the column above the keyboard to complete, but the function of adjust-positon has some problems. when I use it, it will cause users to click on the input box. The textarea will have an animation that is pushed up by the keyboard, and some Android phones will not push up the textarea directly, causing users to be unable to input, so we need to find a way to replace this function.

First, let adjust-positon=false and turn it off. Then, by adjusting the keyboard to obtain the height of the keyboard and setting the bottom of the input box to this height, the input box will automatically float up when focusing:

inputFocus: function(e) {
 inputBottom: e.detail.height || 0
 inputBlur: function(e) {
 inputBottom: 0

In addition, in order for the user to have a better experience, we should help the user to save the id corresponding to the unfinished content locally when the user has already entered the content in the input box and closed the input box without submitting it. The next time the user opens this article to comment, he can directly display the unfinished content:

let cmtStoreId = `${}-${id}`;  // feedid+Comment id to locate
let cmtStoreObj = wx.getStorageSync('cmtStoreId') || {};
let oldVal = cmtStoreObj[cmtStoreId] || '';

inputVal: oldVal,
submitDisabled: !  util.trim(oldVal),
placeholder: ?  Reply'':':'',
inputShow: true


3.9 Share a Poster

Finally, the poster has arrived. In fact, the poster is still very important for a small program, because the sharing of the small program can only be done by sharing it with friends or making a poster with two-dimensional code, so let’s take a look at what knowledge points there will be when making the poster:

Since it is a poster, it must contain a two-dimensional code. How to make the two-dimensional code a designated page with parameters? This requires us to pass the corresponding parameters to the back end and let the back end go.calling interfaceA two-dimensional code is generated, and our parameters are written in a scene.

let scene = encodeURIComponent('feedid=' +;
let pageStr = ?   'pages/detail/detail' : ''; = util.getQrCode(scene, pageStr) || '/images/share-default.jpg';
function getQrCode(scene, page) {
let pageStr = page ?   'page=' + page : '';
return `${g.rootUrl}/v1/user/orcode?  ${pageStr ?   pageStr + '&' : ''}scene=${scene}`;

When the user enters by scanning the two-dimensional code, there will be a scene in the onLoad parameter of this page (note that the two-dimensional code will only take effect after the project is online, and cannot be tested when the applet is not online).

Making posters has many functions that can be used as common methods, such as multi-line text rendering, avatar making, and picture adaptation. I’d like to share with you the picture adaptation methods I wrote below:

* function: center the picture to adapt
* canvasBuild
* scale
* res:
* url: picture address (should be local address)
* dx: the position of the upper left corner of the image on the x axis of the target canvas
* dy: the position of the upper left corner of the image on the y axis of the target canvas
* sWidth: width of rectangular selection box of source image, optional
* sHeight: The height of the rectangular selection box of the source image, optional
* dWidth: the width of the drawn image on the target canvas, allowing the drawn image to be scaled.
* dHeight: the height of the drawn image on the target canvas, allowing the drawn image to be scaled.
* cb: callback
function autoDrawImage(canvasBuild, scale, res) {
let opt = {
url: res.url,
dx: res.dx,
dy: res.dy,
sWidth: res.sWidth || 0,
sHeight: res.sHeight || 0,
dWidth: res.dWidth,
dHeight: res.dHeight,
cb: res.cb

if (!  opt.url) {

let backData = function(width, height) {
let imgProp = width / height;
let prop = opt.dWidth / opt.dHeight;
if (imgProp > prop) {
//The proportion of the original image is wider.
opt.sHeight = height;
opt.sWidth = height * prop; = 0; = (width - opt.sWidth) / 2;
} else {
//Higher proportion of original drawings
opt.sWidth = width;
opt.sHeight = width / prop; = 0; = (height - opt.sHeight) / 2;

if (opt.sWidth && opt.url !  == '/images/avatar-default.png') {
backData(opt.sWidth, opt.sHeight);
} else {
src: opt.url,
success: function(res) {
backData(res.width, res.height);

And save posters to photo albums:

* function: save to photo album
* storeImgPath: picture address
* successCb: callback after success
function savePhotosAlbum(storeImgPath, successCb) {
setTimeout(function() {
filePath: storeImgPath,
success: function(res) {
fail: function(res) {
console.log('fail:' + res);
Title:' Failed to save album',
icon: 'none',
duration: 2000
}, 500);

This is the final poster effect:


Incidentally, under Android (yes, it’s Android again, and Android has a lot of holes), if you directly call canvasBuild.draw () to render canvas, there will be confusion of styles, so you need a setTimeout to execute canvasBuild.draw ().

3.10 Template Message (Not Online yet)

When a user receives a compliment or comment, he can send a message to remind the user, which is a small program.Template message.


3.11 Content Review

If users can send content by themselves, they need to do content review, otherwise they will be called back (even if they pass, you can’t let people use it, if you want to send out some disharmonious content, it will be cold), “I” uses Tencent News’s content review platform, and in general, it can be directly brought with small programs.Content auditing interface, the disadvantage is that there is no background to see and operate the user’s message, all rely on small program processing.

In addition, the “I-I” treatment of content started with “review first and then post”. However, it was found that this may cause the content that users worked so hard to post to be suddenly lost in harmony. Moreover, it is not good to see the content experience after clicking the post. Therefore, we later changed it to “review first and then post”. After the user posts, the status of this message will default to only be visible to the user. If there is a problem with the content, the user will be informed that the content does not conform to the specifications at the notification place, which can avoid the problem just now and the user experience will be much better.



The small program official has its own statistics, but many functions requiring statistics cannot be supported, and can only be seen after the small program goes online, which is not convenient for testing before going online, so “I” chose to introduce another statistical tool: mta:

mta: The advantages are more statistics of sharing, pull-down refresh, page bottoming, as well as user track, stay time, etc. Other small programs have their own statistics functions mta, which is an enhanced version of official statistics, and statistics can be carried out without online application of small programs.

5. Release

At this time, the functions of the applet have been basically developed. If there is no problem with the test, the applet can be ready to go online. There are three versions of the applet: development version, experience version and official version.

  • Development version: the version used when developing on the developer tool, which is generally entered through the two-dimensional code generated by preview of the developer tool;
  • Experience version: after clicking the upload in the developer tool, the project will be uploaded to the background to generate an experience version. the experience version of the two-dimensional code is valid for a long time. each time the experience version is updated locally, the latest version will be updated automatically. there is no need to scan the two-dimensional code again. the experience version can only be used by project members and experience members. the maximum number of experience members is 90 and can be viewed.Official documents;
  • Official version: after confirming that there is no problem, the experience version can be submitted for review, and the official version can be released after the review is passed.

Items that are audited for the first time may be very strict and may be called back many times. It can be re-submitted after being corrected according to the prompts. Generally, the first audit will take a little longer, about 2 days, and each online audit will take about 1 day later.

In addition, a new applet evaluation has recently been added to the applet. If the performance and user evaluation are excellent, a quick audit can be conducted and the audit can be completed within a few hours.

6. Advanced

In the process of web development, we all meet some unconventional requirements more or less, and need to skillfully apply the unknown side of the technology we master. this kind of strange technology is obscene and skillful, which we call black magic.Awesome-blackmagic projectThese magical technology applications will be shared regularly for web developers.

Welcome to watch ~

Advertising time

If you are interested in the “me-me” applet, you can come and watch it. the project is still in its initial stage, and more interesting content will be added later, mua da ~