玩玩小程序:使用 WebApi 交互打造原生的微信小程序 - 图灵小书架

 使用 WebApi 交互打造原生的微信小程序 - 图灵小书架

 

目录

  • 介绍
  • 源码地址
  • 扫一扫体验
  • 代码分析
  • 其它相关信息(互联网搜集)

 

介绍

  定时抓取图灵社区官网的首页、最热、推荐和最新等栏目的相关图书信息进行展示,并且可以下载相关的 PDF 进行查阅...

主要功能

 

源码地址

  源码地址1:https://github.com/liqingwen2015/ituring_small_bookshelf

  源码地址2:https://gitee.com/liqingwen/ituring_small_bookshelf

  使用说明:

  1. 打开微信开发者工具;
  2. 路径引入 src 文件夹;
  3. 输入 APPID 和文件名即可;
  4. 本地不需要配置服务器地址,自动连接我的 WebAPI 接口资源,低成本配置;

 

  不过使用  git,我有一个这样的担忧:用了5年GIT,原来分支合并是这样协作的。假设团队3个人。 领导开创一个分支。 我和另外一个同事在领导的分支下创建一个新分支。 然后 我们各自开发。 有新功能就 去拉取 并将领导的分支合并到自己的分支。 这样,我改的东西,和同事改的不会冲突。最后,GIT 导出我们的差异,通过 QQ 传给领导。 

-- 引用 https://my.oschina.net/lcsoft/tweet/17666900

 

扫一扫体验

  可以通过小程序(已上线)二维码扫一扫,也可以在小程序中搜一下【图灵小书架】进行体验:

 

  它真的非常小(轻量、快、占用内存小),接近 10 个页面所占用的空间大小(代码+图片等)才100KB+。

 

代码分析

结构简析

  config 文件夹(可选):存放配置信息;

  images 文件夹(可选):存放图片;

  pages 文件夹:存放每个页面信息;

  utils 文件夹(可选):工具类存放;

  app.js:项目的入口文件,如包含程序生命周期定义(页面初始化、页面渲染完成、页面显示、页面隐藏和页面关闭等);

  app.json:全局配置文件,如页面路径, tabBar(导航、图标和选中样式等);

  app.wxss:全局样式配置文件,如每个页面可以重用的样式;

  project.config.json:程序的配置文件,如项目名称、微信开发工具配置(是否校验合法域名、是否压缩和样式自动补全等);

 

  为了方便统一管理 api 请求的地址,我统一在 config/config.js 中配置 api 的请求地址:

const key = require('const.js');

// 服务器域名
const baseUrl = key.urlPrefix.server;
//const baseUrl = key.urlPrefix.local;

//获取首页的图书
const getBooksOfIndex = baseUrl + 'books/v1/index';

//获取图书列表
const getBooksByShowType = baseUrl + 'books/v1/list';

//获取图书
const getBook = baseUrl + 'books/v1/detail';

const saveUserInfo = baseUrl + 'account/v1/save';

const submitComment = baseUrl + 'comment/v1/submit';

const getComments = baseUrl + 'comment/v1/list';

module.exports = {
    getBooksOfIndex: getBooksOfIndex,
    getBooksByShowType: getBooksByShowType,
    getBook: getBook,
    saveUserInfo: saveUserInfo,
    submitComment: submitComment,
    getComments: getComments
};

 

  同时,也把一些静态 const 变量统一存放在 config/const.js 中,方便管理和维护:

// Key 名
module.exports = {
    // 用户标识
    wxUserId: 'WxUserId',

    // 登录标识
    loginFlag: 'LoginFlag',

    // 图标
    icon: {
        success: 'success',
        loading: 'loading',
        none: 'none'
    },

    // url 前缀
    urlPrefix: {
        server: 'https://api.nidie.com.cn/api/', //服务器
        local: 'http://localhost:57196/api/', //本地
        test: 'http://localhost:57196/api/', //测试
        file: 'https://download.nidie.com.cn/', //文件
        image: 'http://www.ituring.com.cn/' //图片
    }
};

 

Pages 文件夹简析

 

  这里通过 detail (图书详情页)文件夹进行解析,从图中可以看到的文件夹中包含:

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML 模板文件
  3. .wxss 后缀的 WXSS 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

 

  detail.wxml:

<view>
    <block wx:if="{{showLoading}}">
        <view class="donut-container">
            <view class="donut"></view>
        </view>
    </block>
    <block wx:else>
        <view class="book-container bg-white">
            <view class="book-info">
                <image class="book-image" mode="scaleToFill" src="{{book.imageUrl}}"></image>
                <view class="book-desc">
                    <text class="book-main-text">{{book.name}}</text>
                    <text class="book-text">{{book.author}}</text>
                    <text class="book-text">¥ {{book.price}} 元</text>
                    <view class="loading-container" wx:if="{{downloading}}">
                        <progress percent="{{downloadPercent}}" stroke-width="6" activeColor="#1aad19" backgroundColor="#cdcdcd" show-info />
                    </view>
                </view>
            </view>
        </view>
        <view class="comment-container">
            <view class="comment-title">
                <text>========== 简介 ==========</text>
            </view>
            <view class="comment-area">
                <block>
                    <view class="comment-placeholder">
                        <text>{{book.intro}}</text>
                    </view>
                </block>
            </view>
        </view>
        <!-- bottom button -->
        <view class="fixed-bottom block-full-width flex-container bg-white" wx:if="{{isAllowDownload}}">
            <button class="full-button" type="primary" catchtap="download" data-id="{{bookInfo.id}}" data-name="{{bookInfo.name}}">
                随书下载<text style="font-size:26rpx; color:gray">(已存在,则立即打开)</text>
            </button>
        </view>
    </block>

</view>

  该文件非常像我们所学过的 html 结构,只不过标签替换为了小程序自己包装的语义标签而已。

 

  detail.js

// 获取服务器接口地址
const api = require('../../config/config.js');
const key = require('../../config/const.js');
const http = require('../../utils/http.js');
const file = require('../../utils/file.js');
const cache = require('../../utils/cache.js');
const tip = require('../../utils/tip.js');

Page({
    data: {
        bookIsBuy: 0,
        downloading: false,
        book: {},
        id: '',
        showLoading: true,
        isAllowDownload: false, //是否允许下载
        isDownloading: false //下载中标识
    },

    // 获取书籍
    getBook: function (id) {
        let that = this;
        let key = `Book_${id}`;
        let val = cache.getSync(key);
        let obj = {
            showLoading: false
        };

        if (val) {
            if (val.pdfUrl && val.pdfUrl.trim() !== '') {
                obj.isAllowDownload = true;
            }

            obj.book = val;
            that.setData(obj);
            return;
        }

        http.get(api.getBook + `/${id}`, function (data) {
            if (data.pdfUrl && data.pdfUrl.trim() !== '') {
                obj.isAllowDownload = true;
            }

            obj.book = data;
            that.setData(obj);

            cache.set(key, data);
        });
    },

    // 下载
    download: function () {
        let that = this;

        if (that.data.isDownloading) {
            tip.showToast('下载中,请稍安勿躁!!!');
            return;
        }
  
        let cachekey = `Book_PDF_${that.data.id}`;
        let path = cache.getSync(cachekey);

        if (!path) {
            that.setData({
                isDownloading: true
            });

            let pdfUrl = that.data.book.pdfUrl.split(',');
            
            http.downloadFile(key.urlPrefix.file + pdfUrl[0],
                function (filePath) {
                    file.openDocument(filePath);
                    cache.set(cachekey, filePath);
                },
                function () {
                    that.setData({
                        isDownloading: false
                    });
                });

            tip.showToast('已经开始下载,下载完毕后将自动打开,请稍后!!!');
            return;
        }

        file.openDocument(path);
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        let that = this;
        let id = options.id;

        that.getBook(id);
        that.setData({
            id: id
        });
    },
});

  里面的语法类似 VUE,WXML 中的动态数据均来自对应 Page 的 data,因为我把很多自己封装的方法单独放到 utils 文件夹和 config 文件夹中,在希望调用对应的方法时需要使用 require 函数将其引入,小程序有许多丰富的 API,代码中就使用了如下载、请求 json 数组、提示弹出框和 localStorage 缓存等 API(含同步、异步)。

 

  detail.json

{
  "navigationBarTitleText": "详情页"
}

  这里只是对应导航头文字进行了修改而已。

 

  detail.wxss 样式文件,并没有太多可以说的,按照自己的 css 样式进行编写就好了。

 

其它相关信息(互联网搜集)

  PC 的 IDE、苹果 IOS 和安卓 Android,它们的运行环境是存在差异,意味着不是所有提供的 API 都可以完全兼容。

  见 https://developers.weixin.qq.com/miniprogram/dev/devtools/details.html#运行环境差异

 

 

小程序 - MINA 框架

  微信团队为小程序提供的框架命名为MINA应用框架。MINA框架通过封装微信客户端提供的文件系统、网络通信、任务管理、数据安全等基础功能,对上层提供一整套JavaScript API,让开发者能够非常方便地使用微信客户端提供的各种基础功能与能力,快速构建一个应用。

 

小程序 - 启动运行机制

 

小程序 - 生命周期

 

posted @ 2018-07-23 13:44  反骨仔  阅读(8483)  评论(22编辑  收藏  举报