Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Cloud development Pictures, caches, and files


May 22, 2021 Mini Program Cloud Development Study Guide


Table of contents


In the previous sections, we emphasized JavaScript's handling of data, and this section let's look at the deeper interaction between small programs and clients (phones). In the previous section, data is stored in contacts (adding phone contacts), stored on the cutboard (copy and paste with mobile phone), the small program has already interacted with the client phone, this section we will get the phone album pictures and mobile phone camera photos taken, the phone positioning and get the phone's cache, files, and use JavaScript to manipulate pictures, operation cache and operation files.

Get a picture of your phone album or take a picture

Getting pictures and photos from your phone album with a small program sounds complicated, but with the API, we just need to combine the previous click events, event handlers, and call the API to pass in the specified parameters.

Technical documentation: wx.chooseImage().

Upload a photo

Use the developer tool to create a new file page, and then enter the following code in file.wxml:

  1. <button bindtap="chooseImg">选择图片</button>
  2. <image mode="widthFix" src="{{imgurl}}"></image>
  3. <view>上传的图片</view>

Then set .js initial value for imgurl in the data of the file, and since the link src is a string type, we can set it here to a string empty value to complete the initialization of imgurl:

  1. data: {
  2. imgurl:"",
  3. },

Then add the event handler chooseImg in the file .js, in the chooseImg we call the upload function API wx.chooseImage (), where count, sizeType, sourceType are all api-written properties, API call success (image upload success), will return some information in the picture in the success callback function, the return information can be seen in the technical documentation.

  1. chooseImg:function(){
  2. let that=this
  3. wx.chooseImage({
  4. count: 1,
  5. sizeType: ['original', 'compressed'],
  6. sourceType: ['album', 'camera'],
  7. success(res) {
  8. const imgurl = res.tempFilePaths
  9. that.setData({
  10. imgurl
  11. })
  12. }
  13. })
  14. },

Although you can also see the effect in the developer tool simulator, wx.chooseImage() is a highly interactive API with mobile clients, we'd better experience it on the phone. Click on the developer tool preview, view the effect on your phone WeChat, click the Select Image button, upload a picture or take a photo.

  • count: The number of photos you can select, the default is 9 (since imgurl declares a string, multiple photos need to be array Array, followed by a case of uploading multiple pictures)
  • SourceType: Choose the source of the picture, album is the picture can come from the mobile phone album, and the camera can be taken from the phone, both are written from the album or can take pictures;
  • sizeType: the size of the selected picture, original for the original, compressed for the compression diagram, in order to reduce the pressure on the server, it is recommended for the compression diagram;
  • TempFilePaths is a list of paths for temporary files, and tempFiles is a list of temporary files, noting that both values are arrays.

    Small task: Change the value of sourceType to 'album', what's the effect on WeChat? Then change sizeType to 'compressed' to see if your phone can still upload the original image?

The processing of empty values

We can see that since imgurl is an empty value, the image component has a default width of 300px and a height of 225px (which changes size with css), so the display uploaded picture will have a blank space with the button of the selected picture, and there are three ways to handle it:

Method 1: We can give imgurl a link to the initial picture, in order to make the interface more beautiful, more interactive, usually will set a default picture, such as the default avatar, when the user uploads, setData will replace the initial picture;

Method 2: To determine whether there is content in imgurl, for example, we can add a layer of logic to judge that the component will not be displayed when the imgurl property under data in Page() is not empty;

  1. <view wx:if="{{!!imgurl}}">
  2. <image mode="widthFix" src="{{imgurl}}"></image>
  3. </view>

Method 3: This method and method two are similar, set a logical judgment, such as setting a boolean property such as hasImg in data, the initial value is false,

  1. data: {
  2. hasImg:false,
  3. },

When the chooseImg callback is successful, change hasImg to true in the that.setData, that is, to the thot.setData() in the success callback function of wx.chooseImage()

  1. that.setData({
  2. imgurl,
  3. hasImg:true,
  4. })

So if there's a picture that goes into the logic of the callback function, then we change the code for file.wxml to the following:

  1. <view wx:if="{{hasImg === false}}">
  2. <button bindtap="chooseImg">选择图片</button>
  3. </view>
  4. <view wx:if="{{hasImg === true}}">
  5. <image mode="widthFix" src="{{imgurl}}"></image>
  6. </view>

When there is no picture, that is, the value of hasImg is false, the button of the selected picture is displayed, and when there is a picture, there is no button only the picture, the user experience will be better in certain occasions (button if it is always there, the user will go to the point, the experience is not good).

Note: The uploaded pictures here are not the same as the uploaded pictures in our daily life Oh, daily life upload pictures, pictures will not only appear in small programs (web pages, apps), but also continue to upload to the storage server, and we are only the first step here, the uploaded pictures are only stored in temporary files, so recompiled, the picture will not show. There will be temporary files and images uploaded to cloud storage in the cloud development section.

Upload multiple photos

If multiple photos are uploaded, the initial value of imgurl cannot be a string, but an array of Aray,

  1. data: {
  2. imgurl:[],
  3. },

And file.wxml of the code should be corresponding to the list rendering can be, this writing in the code is relatively versatile, upload a picture, multiple pictures can be, but specifically depends on the actual product development needs.

  1. <view wx:for-items="{{imgurl}}" wx:for-item="item" wx:key="*this">
  2. <image mode="widthFix" src="{{item}}"></image>
  3. </view>

Then the value of count is modified to 2 to 9 sheets, compiled, in the mobile phone WeChat experience the effect.

The action picture

Using the small program image API can not only upload pictures, but also upload pictures to do certain things, such as getting picture information, previewing pictures, saving pictures, compressing pictures and so on.

Get picture information

Whether you're storing a picture locally in a small program or in a temporary file, cache, or network, use wx.getImageInfo() to get the width, height, path, format, and direction of the picture.

Technical documentation: wx.getImageInfo().

Using the developer tool to .js code to the file, we use wx.getImageInfo() to get information about previously uploaded images. Since obtaining image information requires waiting for the image to be uploaded successfully before executing, we can call wx.getImageInfo() in the success callback function of wx.chooseImage (), and then get the picture information before returning the picture information, so this is another callback function:

  1. chooseImg:function(){
  2. let that=this
  3. wx.chooseImage({
  4. count: 9,
  5. sizeType: ['original', 'compressed'],
  6. sourceType: ['album', 'camera'],
  7. success(res) {
  8. const imgurl = res.tempFilePaths
  9. console.log('chooseImage回调打印的res',res)
  10. that.setData({
  11. imgurl
  12. })
  13. wx.getImageInfo({
  14. src: res.tempFilePaths[0],
  15. //也可以这么写:src: that.data.imgurl[0],这里只能看到第一张照片的信息,其他照片的信息需要遍历来获取
  16. success(res){
  17. console.log('getImageInfo回调打印的res',res)
  18. }
  19. })
  20. }
  21. })
  22. },

After compilation, we upload another image, after the successful upload of the image, you can see the printed information in the console console. In the code above, we found that the success callback function nested the success callback function.

Callback function

  1. 经过之前的学习,相信大家对回调函数successfail有了一定的认识,那什么是回调函数呢?简单一点说就是:回调Callback是指在另一个函数执行完成之后被调用的函数。successfail就都是在小程序的API函数执行完成之后,才会被调用,而successfail它们本身也是函数,也能返回数据。而复杂一点说,就是回调函数本身就是函数,但是它们却被其他函数给调用,而调用函数的函数被称为高阶函数。这些大家只需要粗略了解就可以了。
  2. 异步与同步
  3. 我们前面也提及过异步,那什么会有异步呢?因为JavaScript是单线程的编程语言,就是从上到下、一行一行去执行代码,类似于排队一样一个个处理,第一个不处理完,就不会处理后面的。但是遇到网络请求、I/O操作(比如上面的读取图片信息)以及定时函数(后面会涉及)以及类似于成功反馈的情况,等这些不可预知时间的任务都执行完再处理后面的任务,肯定不行,于是就有了异步处理。
  4. 把要等待其他函数执行完之后,才能执行的函数(比如读取图片信息)放到回调函数里,先不处理,等图片上传成功之后再来处理,这就是异步。比如wx.showToast()消息提示框,可以放到回调函数里,当API调用成功之后再来显示提示消息。回调函数相当于是异步的一个解决方案。

Preview all uploaded images

Previewing a picture is opening a picture in full screen on a new page, and during the preview, users can save the picture and send it to a friend. You can preview a photo or multiple photos.

Technical documentation: wx.previewImage().

Using the developer tool to enter the following code in file.wxml, we want to preview the image uploaded from the phone album (keep the code above, and then write), if you do not upload the image, then hide the button of the preview image, let's write a complete piece of code:

  1. <view wx:if="{{hasImg === true}}">
  2. <button bindtap="previewImg">预览照片</button>
  3. </view>

Then add the .js viewImg in the file, calling the API wx.previewImage():

  1. previewImg:function(){
  2. wx.previewImage({
  3. current: '',
  4. urls: this.data.imgurl,
  5. })
  6. },

When you upload an image, click the Preview Image button to preview all the images.

This scene is mainly used to allow users to preview, save or share pictures, after all, the image component is not supported to enlarge the preview of the picture, save to the local, forward to friends, and now WeChat also supports the preview of small program code, long press can open the small program, this API is mainly to enhance the user's interactive experience.

So how do we achieve clicking on one of these images and popping up a preview of all the pictures? There's going to be a current here.

Change the code uploaded from the previous file.wxml image to the following, and bind the event handler previewImg to the picture.

  1. <button bindtap="chooseImg">选择图片</button>
  2. <view wx:for-items="{{imgurl}}" wx:for-item="item" wx:key="*this">
  3. <image mode="widthFix" src="{{item}}" data-src="{{item}} " bindtap="previewImg" style="width:100px;float:left"></image>
  4. </view>

The file.js event handler, viewImg, is then modified to:

  1. previewImg:function(e){
  2. wx.previewImage({
  3. current: e.currentTarget.dataset.src,
  4. urls: this.data.imgurl,
  5. })
  6. },

Clicking on the image will bring up a preview window to preview the picture.

Save the picture to the album

The small program does not support saving network pictures directly to the system album of the local phone, and supports the temporary file path and the local path of the small program.

Technical documentation: wx.saveImageToPhotosAlbum().

For example, we create a new image folder at the root of a small program and put a picture inside it, such as background .jpg, and then enter the following code in file.wxml so that the image component binds the event handler saveImg:

  1. <image mode="widthFix" src="/images/background.jpg" bindtap="saveImg"></image>

Then add .js saveImg in the file,

  1. saveImg:function(e){
  2. wx.saveImageToPhotosAlbum({
  3. filePath: "/images/background.jpg",
  4. success(res) {
  5. wx.showToast({
  6. title: '保存成功',
  7. })
  8. }
  9. })
  10. }

After compiling and previewing the experience on your phone, clicking on the image triggers the event handler saveImg, calls the wx.saveImageToPhotosAlbum() API, filePath is a permanent link to a small program file, and the file is saved to the phone album (no album permission prompts).

Of course, the actual development of permanent links will not be too much, the most used scene is to download the network pictures to the temporary link (because you can not save the network pictures directly), and then save the temporary link pictures to the album, just change the above permanent link to a temporary link on it. T he most important thing is to find out where the picture is, on the internet? O r is it local to the small program? O r in a temporary file? Or in the cache?

Compress the picture

Small programs have an API of compressed images wx.compressImage(), especially when uploading images, in order to reduce the pressure on the storage server, do not allow users to upload photos with too high resolution.

  • You can let the user upload the picture first;
  • After the successful upload of the image (i.e. in the success callback function of the uploaded image) to obtain the information of the picture;
  • After successfully obtaining the information (i.e. in the success callback function for obtaining the picture information) to determine whether the width or height is too large, if the picture is too large, compress the picture,
  • After the compressed picture is successful (i.e. in the success callback function of the compressed picture), the compressed picture is uploaded to the server

Upload images, get picture information, compress pictures, upload pictures to the server, each step is dependent on the next step, so will continue to write functions in the sessions callback function, the actual development involved in the business will be more complex, will continue to call back, which is called callback hell. That's why there's a Promise, which we'll mention later.

Because the compressed images use not too many scenes, after all, we can not support the upload of the original image when uploading photos, only support the compression of the pressed can ensure the size of the uploaded pictures. And wx.compressImage () compressed picture API is relatively simple, so here is no real case, I believe you can see the document can also play clearly.

Upload the file

Small programs support not only uploading images, but also uploading videos, Excel, PDFs, audio, and other file formats, but we can only select files in other formats from client sessions (i.e. WeChat single chat, group chat chat history).

Technical documentation: wx.chooseMessageFile().

Use the developer tool to add the following code in file.wxml to the button binding event handler for selecting the file:

  1. <button bindtap="chooseFile">选择文件</button>

Add event .js the file and print the parameter objects in the callback function after the upload is successful.

  1. chooseFile: function () {
  2. let that = this
  3. wx.chooseMessageFile({
  4. count: 5,
  5. type: 'file',
  6. success(res) {
  7. console.log('上传文件的回调函数返回值',res)
  8. }
  9. })
  10. },

Using the developer tool to upload a picture or other format of the file, in the console console we can see that the printed res object has the array object Arry of the trumpFiles (no tampFilePaths, the technical documentation here is incorrect), the tempFiles object contains the name of the file name name, the temporary path path of the file, the size of the file size, the selected file session send timestamp timestamp time, The type of file type type.

We can render the information obtained by the uploaded file to the page and add the list rendered code in file.wxml, that is

  1. <button bindtap="chooseFile">选择文件</button>
  2. <view wx:for-items="{{tempFiles}}" wx:for-item="item" wx:key="*this">
  3. <view>{{item.path}}</view>
  4. </view>

Initialize a property, temFiles, in the data of Page(), with an initial value of an empty array, Arry:

  1. data: {
  2. tempFiles:[],
  3. },

Then assign the data to tempFiles using setData in the success callback function of chooseFile:

  1. chooseFile: function () {
  2. let that = this
  3. wx.chooseMessageFile({
  4. count: 5,
  5. type: 'file',
  6. success(res) {
  7. let tempFiles=res.tempFiles
  8. that.setData({
  9. tempFiles
  10. })
  11. }
  12. })
  13. },

After compiling, preview the experience on WeChat to see what works? N ote that you need to select WeChat's session box with files. Or again, this upload and our actual upload is still not the same, here just uploaded the file to a temporary file, and did not upload to the server.

Upload the location

In addition to uploading images, audio and video, and various file formats, the small program also supports upload location.

Technical documentation: wx.chooseLocation().

Using the developer tool to enter the following code in file.wxml, we uploaded the file earlier, this time we uploaded the location of the phone and rendered it:

  1. <button bindtap="chooseLocation">选择地理位置</button>
  2. <view>{{location.name}}</view>
  3. <view>{{location.address}}</view>
  4. <view>{{location.latitude}}</view>
  5. <view>{{location.longitude}}</view>

Then initialize .js in the data of The Page() in the file

  1. data: {
  2. location:{},
  3. },

Add the .js in the file file,

  1. chooseLocation: function () {
  2. let that= this
  3. wx.chooseLocation({
  4. success: function(res) {
  5. const location=res
  6. that.setData({
  7. location
  8. })
  9. },
  10. fail:function(res){
  11. console.log("获取位置失败")
  12. }
  13. })
  14. },

After compiling the preview with the phone click on the button to select the geographic location, the map selection location will pop up (this location can be your current location, or you can choose a location of your own), and then click OK, you can see the location we uploaded on the small program. For location information to appear on the map, you can add a map component in file.wxml:

  1. <map style="width: 100%; height: 300px;"
  2. latitude="{{location.latitude}}"
  3. longitude="{{location.longitude}}"
  4. show-location
  5. ></map>
  1. 小任务:上传地理位置,将该地址显示在地图上,并添加该地理位置的markers。关于markers的知识,可以去看map组件的技术文档。

Modular and formatted

In the new template applet (without cloud development services), there is a log logs page, which, although simple, contains very complex JavaScript knowledge and is a very good learning reference case, let's read it one by one.

Modular and introduced modules

In real-world development, date and time processing is often used, but the time format obtained using the Date object is very different from the form we want to present. At this point we can take the processing of time away from a separate js file such as util.js (util is an abbreviation for utility, meaning assembly, universal program, etc.) as a module.

Putting the universal module in the util .js or common.js, putting the utils .js in the utils folder and so on is the same as putting the css in the style folder, putting the page in the page folder, putting the picture in the images folder is the same reason, although the name of the folder or file you can modify at will, but for the readability of the code, the clarity of the file structure, it is recommended that we use this way of understanding.

Use the developer tool to create a new utils folder in the root of the applet, create a new util.js file under the folder, and enter the following code in the util.js (i.e. the util .js called by the logs page of the reference template .js)

  1. const formatTime = date => {
  2. const year = date.getFullYear() //获取年
  3. const month = date.getMonth() + 1 //获取月份,月份数值需加1
  4. const day = date.getDate() //获取一月中的某一天
  5. const hour = date.getHours() //获取小时
  6. const minute = date.getMinutes() //获取分钟
  7. const second = date.getSeconds() //获取秒
  8. return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') //会单独来讲解这段代码的意思
  9. }
  10. const formatNumber = n => { //格式化数字
  11. n = n.toString()
  12. return n[1] ? n : '0' + n
  13. }
  14. module.exports = { //模块向外暴露的对象,使用require引用该模块时可以获取
  15. formatTime: formatTime,
  16. formatNumber: formatNumber
  17. }

Let's call this module file util .js again in the file .js, that is, introduce the utcil.js file using require in front of the file.js Page() object (the relative path of the module file relative to the current file needs to be introduced, and absolute path is not supported)

  1. const util = require('../../utils/util.js')

Then print in the onLoad page lifecycle function to see what the code processed during this time does, and here's how to call the functions in the module.

  1. onLoad: function (options) {
  2. console.log('未格式化的时间',new Date())
  3. console.log('格式化后的时间',util.formatTime(new Date()))
  4. console.log('格式化后的数值',util.formatNumber(9))
  5. },

util.formatTime() calls the functions in the module, and logs printed through the console can see different date and time formats, such as: Unformatted time Mon Sep 02 2019 11:25:18 GMT-0800 (China Standard Time) formatted time 2019/09/02 11:25:18

Unformatted time Mon Sep 02 2019 11:25:18 GMT-0800 (China Standard Time) After formatting time 2019/09/02 11:25:18

Obviously the formatted date time is more in line with our daily habits, and the 9 number is converted into the string "09". S o how is this code that formats the date time implemented? This involves knowledge of higher-order functions, which typically call parameters, while higher-order functions call other functions, i.e. use other functions as arguments.

map

It is better to believe that the formatted number of the code is better understood, if it is 15 in the 15th day, because n s1 is the second digit 5 of the 15th, for true will return directly to n, that is, 15;

  1. const formatNumber = n => { //格式化数字
  2. n = n.toString() //将数值Number类型转为字符串类型,不然不能拼接
  3. return n[1] ? n : '0' + n //三目运算符,如果字符串n第2位存在也就是为2位数,那么直接返回n;如果不存在就给n前面加0
  4. }

Formatting the date time involves map, for example, the following code has map,

  1. return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')

Map is also a data structure, and the knowledge behind it is very complex, but we just need to understand what it does, and if you want to function on every value in the array and return a new array, you can use map.

The above code is to format the numbers for every number in the arrays of year, month, day, and hour, minute, second, as we can see by printing them in file.js onLoad

  1. onLoad: function (options) {
  2. console.log('2019年9月2日map处理后的结果', [2019,9,2].map(util.formatNumber))
  3. console.log('上午9点13分4秒map处理后的结果', [9, 13, 4].map(util.formatNumber))
  4. },

The results printed from the console show that the numbers inside the array are formatted, there are two-digit unprocessed, there is no two-digit preceding plus 0, and the array is returned. As for the array Array's joy method, it is to stitch the array elements into strings to split with separators, with the separator "/" above the separator of "/" and the separator of "hour, minute, second" as ":"."

Data cache Storage

The logs page also involves knowledge of data caching Storage. T hrough the previous study, we learned that click events generated event objects are also good, the data submitted using the data form is also good, or uploaded pictures, files are good, as long as we recompile the small program, the data will disappear. Earlier we also mentioned that there are three ways to store data, files, one is to save to the local mobile phone, two is the cache, three is uploaded to the server (cloud development will explain), here we will understand the knowledge of data caching.

Technical documentation: wx.setStorageSync(), wx.getStorageSync().

Save the file

Note: Although uploading pictures and uploading files is to upload pictures or files to temporary files first, saving images wx.saveImageToPhotosAlbum() and saving files wx.saveFile() are completely different concepts, saving pictures is to save pictures to the phone's local album;

Save file technical documentation: wx.saveFile().

Before we understand the data cache case for logs, let's look at a case where the uploaded image is saved from a temporary file to the cache, using the developer tool to enter the following code in file.wxml:

  1. <view>临时文件的图片</view>
  2. <image mode="widthFix" src="{{tempFilePath}}" style="width:100px"></image>
  3. <view>缓存保存的图片</view>
  4. <image mode="widthFix" src="{{savedFilePath}}" style="width:100px"></image>
  5. <button bindtap="chooseImage">请选择文件</button>
  6. <button bindtap="saveImage">保存文件到缓存</button>

Then initialize .js path of the temporary file in the data of the file and the path of the local cache, the path of the local cache, the path

  1. data: {
  2. tempFilePath: '',
  3. savedFilePath: '',
  4. },

Add event handler .js and saveImage in the file image (function names are different from the previous chooseImg and saveImg, don't confuse it):

  1. chooseImage:function() {
  2. const that = this
  3. wx.chooseImage({
  4. count: 1,
  5. success(res) {
  6. that.setData({
  7. tempFilePath: res.tempFilePaths[0]
  8. })
  9. }
  10. })
  11. },
  12. saveImage:function() {
  13. const that = this
  14. wx.saveFile({
  15. tempFilePath: this.data.tempFilePath,
  16. success(res) {
  17. that.setData({
  18. savedFilePath: res.savedFilePath
  19. })
  20. wx.setStorageSync('savedFilePath', res.savedFilePath)
  21. },
  22. })
  23. },

We also need to assign the .js stored in the cache to the local cached path savedFilePath in the onLoad lifecycle function of the file:

  1. onLoad: function (options) {
  2. this.setData({
  3. savedFilePath: wx.getStorageSync('savedFilePath')
  4. })
  5. },

After compilation, click on the button to upload the file, will trigger the joseImage event handler, and then call the UPLOAD image upload API wx.chooseImage, the image will be uploaded to the temporary file, and the temporary file address assigned to the tempFilePath, with the trumpFilePath, the picture can be rendered.

Then clicking on the save file to the cached button triggers the saveImage event handler, then saves the file API wx.saveFile, saves the picture in the tempFilePath to the cache, and assigns the cached address to the savedFilePath (note that the temporary path is a prerequisite for saving the file), and the cached picture is rendered to the page. T he cache API wx.setStorageSync() is then called again, saving the path of the cached file to the cached key SaveFilePath. Some parameters have the same name but have different meanings, so be careful.

The data saved to the cache by wx.setStorageSync() can be obtained using wx.getStorageSync(), and we assign the acquired cache file path to SavedFilePath in onLoad.

Compile the page to see if the temporary file is different from the cache file, the temporary file will be cleared due to the compilation of the small program, and the cache file has 10M of space, as long as the user does not deliberately delete, it will always be.

The benefits of caching are many, such as the user's browsing of articles, the progress of playing videos (read which articles, give a special style, lest the user do not know where to see), the user's login information (the user logs in once, can be logged in for a long time no longer), custom template style (the user chooses their favorite style, the next time the small program is opened or the same), the most frequently used small pictures (save in the cache, open the small program faster next time) and so on.

Logs' data cache processing

Let's go back to the logs cache case and enter the following code in the lifecycle function of the applet app.js onLaunch, which is to log execution when the small program is initialized:

  1. // ||为逻辑与,就是声明logs为获取缓存里的logs记录,没有时就为空数组
  2. var logs = wx.getStorageSync('logs') || []
  3. //unshift()是数组的操作方法,它会将一个或多个元素添加到数组的开头,这样最新的记录就放在数组的最前面,
  4. //这里是把Date.now()获取到的时间戳放置到数组的最前面
  5. logs.unshift(Date.now())
  6. //将logs数据存储到缓存指定的key也就是logs里面
  7. wx.setStorageSync('logs', logs)
  8. console.log(logs)
  9. console.log(Date.now())

As we compile, the records in the logs array increase, and the values added are timestamps. So how do you render the logs in the cache to the page?

Add the following code in file.wxml, because the logs are arrays, we use list rendering, here is an array of index values, because index is recorded from 0, give index plus 1, in line with our daily usage habits.

  1. <view wx:for="{{logs}}" wx:for-item="log">
  2. <view>{{index + 1}}. {{log}}</view>
  3. </view>

Then initialize .js in the data of the file

  1. data: {
  2. logs: []
  3. },

The cached logs .js in the lifecycle function onLoad of the filed computer and assigned to the logs in the data via setData

  1. onLoad: function () {
  2. this.setData({
  3. logs: (wx.getStorageSync('logs') || []).map(log => {
  4. return util.formatTime(new Date(log))
  5. })
  6. })
  7. },

Combined with the previous understanding of map, modular knowledge is not difficult to understand the above code. The cache has the difference between a sync API and an asynchronous API, combined with what we learned earlier about synchronization and asynchronous, to see the difference between a cached synchronization API and an asynchronous API.

Note: It's important to open the Storage tab of the Developer Tools Debug panel, where cached records of small programs can be visually available, and it's important to keep an eye out when debugging.