美文网首页
小程序“友福图书馆”项目研究

小程序“友福图书馆”项目研究

作者: Arthur澪 | 来源:发表于2018-01-25 22:46 被阅读0次

开启项目

  • 新项目
    采用WePY开源框架开发,WePY项目的创建与使用步骤如下
    1、在全局安装WePY命令行工具,执行命令:
    npm install wepy-cli -g
    2、在开发目录中,生成Demo开发项目文件夹:
    wepy new myDemo
    3、移动到项目目录下,开始编译
    wepy build --watch

  • 开源项目
    下载一个开源的采用WePY框架开发的小程序项目,“友福图书馆”,对其进行研究学习。下载完后,打开并启动项目:
    1、移动到项目的根目录
    cd library
    2、安装npm,demo项目中可能运用到相关的库
    npm install
    3、运行
    npm run dev

下面以“友福图书馆”项目为例,进行小程序开发的研究

项目架构

把demo下载下来,编译后,结构目录变成如下所示:


QQ.png

其中,dist目录是编译后生成的,其中包含的是demo对应的小程序原生文件。在利用WePY框架开发小程序时,在src目录下进行代码的编辑。

项目结构整理

app.wpy是小程序的入口文件。
另外,将自定义的组件、配置文件、项目中用到的图片图标、小程序的各个页面、组件样式等等,进行分门别类,保存在各自的文件夹,使得项目结构清晰,且易于管理。

小程序整体架构

先预览一下这个小程序的外观呈现,如下图:


QQ.png

从功能上说,分为三大块:首页、借阅页面、个人页面。
具体代码实现是,在小程序入口文件app.wpy的APP示例中,在config对象中声明tabBar。

<script>
import wepy from 'wepy'
import 'wepy-async-function'

export default class extends wepy.app {
    config = {

      tabBar: {    //  
        color: '#AEADAD',
        selectedColor: '#049BFF',
        backgroundColor: '#fff',
        borderStyle: 'black',
        list: [{
        pagePath: 'pages/index',
        selectedIconPath: './images/tabbars/icon-mark-active@2x.png',
        iconPath: './images/tabbars/icon-mark@2x.png',
        text: '首页'
      }, {
        pagePath: 'pages/borrow',
        selectedIconPath: './images/tabbars/icon-shelf-active@2x.png',
        iconPath: './images/tabbars/icon-shelf@2x.png',
        text: '借阅'
      }, {
        pagePath: 'pages/user',
        selectedIconPath: './images/tabbars/icon-smile-active@2x.png',
        iconPath: './images/tabbars/icon-smile@2x.png',
        text: '我的'
      }]
    },
    }
}

除此之外,应该事先编辑好TabBar中包含的各个页面。这样,就实现了图中的效果。

另外,还可以在config中声明:整个项目各个页面的文件路径、整体风格样式、以及一些全局配置和全局方法等等。如下:

 pages: [
      'pages/index',
      'pages/main/search',
      'pages/main/list',
        ... ...    //  整个项目各个页面的文件路径
      'pages/user/collect'
    ],
    window: {
      navigationBarTitleText: '友福图书馆',
      navigationBarTextStyle: 'white',
      navigationBarBackgroundColor: '#049BFF',
      backgroundColor: '#eaeaea',
      backgroundTextStyle: 'light',
      enablePullDownRefresh: true    //   是否下拉刷新
    },

在APP实例中,除了config对象外,还可以设置一些项目中要用到的工具方法。注意:app.wpy中没有</template>部分。

以上是从整体的角度来看的,下面逐渐更加细节地来研究小程序的开发。这里重点看了首页的设计、自定义组件的设计与使用,以及网络工具封装使用,这3大不同类别的模块的设计。

首页

首页的文件内容总体分为3大块:<template>部分、<script>部分、</style>部分
其中,

  • 在<template>部分进行静态页面的设计
<template>
  <view class="page-index">
    <SearchBar :placeholder="searchText"></SearchBar>
    <BookList :list.sync="list" title="图书推荐"
     :loading.sync="loading" :noMore.sync="noMoreList"></BookList>
  </view>
</template>

1、组件的引入与声明
在<template>标签当中堆积、嵌套了许多组件。
其中自定义组件需要在<script>部分import进来。
如:import SearchBar from '../components/searchbar'
并要在页面示例中的component对象中进行声明,如:

    components = {
      SearchBar,    //命名与import的一致
    }

2、组件的属性设置
在首页中,组件的属性值来自页面示例中data对象声明的属性。

    <SearchBar :placeholder="searchText"></SearchBar>

      ... ...

    data = {
      searchText: '搜索图书',
    }

另外,进行了父组件与子组件的属性的数据绑定,用到的语法是:props.sync,这样实现了属性的动态设置。

3、“推荐图书”列表组件

<BookList :list.sync="list" title="图书推荐"
     :loading.sync="loading" :noMore.sync="noMoreList"></BookList>

在首页中,主体是一个类似listView的组件。但是,小程序中并没有封装好这么一个组件给我们直接使用。这就涉及到了自定义组件了,后面再详细来看。
这里要说的是,在首页的页面示例中,给这个组件提供数据,这部分是在<script>部分处理的。

  • <script>部分进行变量声明、逻辑交互及事件处理等

1、给组件提供数据
接着上面的思路,如何给自定义组件BookList设置数据?
首先在页面示例的data对象中,声明相关数据变量,因为涉及到网络请求数据,并分页加载,这里添加了以下变量。

data = {
      noMoreList: false,
      loading: false,
      list: [],    //  装载请求回来的数据
      page: 1   // 分页加载页数
    }

同时,添加请求数据的方法updateBookList(page) { }、下拉刷新的方法onPullDownRefresh() { }、加载更多触发方法onReachBottom() { },方法的具体内容看需求来决定,这里不多说。什么时候开始网络请求呢?

    onReady() {
      //  页面准备加载的时候,触发
    }

2、事件处理
这里,没有看到一些类似于按钮点击的数据处理,因为这在自定义组件中完成了。这是一种MVVM的设计模式。这也是采用WePY框架开发获得的一个好处。

  • </style>部分引入样式

在首页文件中,这部分代码不多。

<style lang="less">
.page-index{
  // some style
}
</style>

因为这里lang="less"标志是表示,引入了全局的公共样式page-index,其中包含了首页需要用到的样式,这在别的文件中已经编辑好了。所以,在首页直接引用即可。

到此,首页的研究大概完毕。下面看小程序中自定义组件的设计。

自定义组件

这里,以自定义的搜索栏组件为例,进行研究。
自定义组件的文件内容也分成3部分:<template>部分、<script>部分、</style>部分,与页面文件相似。
1、与页面的不同点
自定义组件示例继承wepy.component基类,而页面示例继承自wepy.page基类。另外,自定义组件中一般没有设置onLoad等表示组件周期的方法。

2、逻辑交互与事件处理
关于自定义组件,上面已经说了有关父子组件传值的问题了,这里主要看组件中的逻辑交互与事件处理。
如:搜索按钮

//  在template部分
<view class="weui-search-bar__cancel-btn" hidden="{{!inputShowed}}" @tap="search">
搜索
</view>

这里用系统组件view表示搜索按钮,并在其中绑定了一个点击事件。语法是@tap="search"。其中,search方法在部分的method对象中声明

methods = {
      search () {
        const params = {
          keyword: this.inputVal || this.placeholder
        }
        wx.navigateTo({
          url: `/pages/main/list?params=${JSON.stringify(params)}`
        })
      },
}

可以看出,其中的逻辑功能处理包括传值、页面跳转。

3、页面之间的传值,页面跳转
执行微信小程序系统提供的方法wx.navigateTo,参数url表示下一个页面的路径,并且可以带上传递的值

    wx.navigateTo({
          url: `/pages/main/list?params=${JSON.stringify(params)}`
    })

下一个页面怎么接收传过来的值呢?在下一个页面的页面示例中,方法是:

onLoad(query) {
      let params = query && query.params
      try {
        params = JSON.parse(params)
      } catch (e) {
        params = {}
      }
      this.params = params   // 保存在data对象中声明的属性params中
}

网络工具

1、在.js文件中封装网络请求工具,继承的基类是wepy.mixin。

import wepy from 'wepy'
import { service } from '../config.js'

export default class httpMixin extends wepy.mixin {

  $get(
    {url = '', headers = {}, data = {} },
    {success = () => {}, fail = () => {}, complete = () => {} }
  ) {
    const methods = 'GET'
    this.$ajax(
      {url, headers, methods, data},
      {success, fail, complete }
    )
  }

  $post(
    {url = '', headers = {}, data = {} },
    {success = () => {}, fail = () => {}, complete = () => {} }
  ) {
    const methods = 'POST'
    this.$ajax(
      {url, headers, methods, data},
      {success, fail, complete }
    )
  }
}
$ajax(
    {url = '', headers = {}, methods = 'GET', data = {} },
    {success = () => {}, error = () => {}, fail = () => {}, complete = () => {} }
  ) {
    // 增强体验:加载中
    wx.showNavigationBarLoading()

    // 构造请求体
    const request = {
      url: url + '?XDEBUG_SESSION_START=1',
      method: ['GET', 'POST','PUT', 'DELETE'].indexOf(methods) > -1 ? methods : 'GET',
      header: Object.assign({
        'Authorization': 'Bearer ' + wx.getStorageSync('token'),
        'X-Requested-With': 'XMLHttpRequest'
      }, headers),
      data: Object.assign({
        // set something global
      }, data)
    }

    // 控制台调试日志
    console.table(request)

    // 发起请求
    wepy.request(Object.assign(request, {
      success: ({ statusCode, data }) => {
        // 控制台调试日志
        console.log('[SUCCESS]', statusCode, typeof data === 'object' ? data : data.toString().substring(0, 100))

        // 状态码正常 & 确认有数据
        if (0 === +data.code && data.data) {
          // 成功回调
          return setTimeout(() => {
            this.isFunction(success) && success({statusCode, ...data})
            this.$apply()
          })
        } else if (data.code == 2) {
          // 删除过时token
          wx.removeStorageSync('token', null)

          // 重新登录
          wepy.login({
            success: (res) => {
              console.log('wepy.login.success:', res)

              // 根据业务接口处理:业务登陆:异步
              this.$post({ url: service.login, data: {code: res.code} }, {
                success: ({code, data}) => {
                  if(data.token){
                    wx.setStorageSync('token', data.token)
                  }

                  var route = '/' + getCurrentPages()[0].__route__;

                  if(route == '/pages/user/register'){
                    return
                  }

                  if (!data.token ){
                    // wx.reLaunch({url: '/pages/user/register'})
                    wx.navigateTo({url: '/pages/user/register'})
                  }else{
                    wx.reLaunch({url: route})
                  }
                }
              })
            },
            fail: (res) => {
              console.log('wepy.login.fail:', res)
            }
          })

        } else {
          // 失败回调:其他情况
          return setTimeout(() => {
            /* if(this.isFunction(fail)) {
              fail({statusCode, ...data})
              this.$apply()
            }else{ */
              wx.showModal({
                title: '操作错误',
                content: data.message,
                showCancel: false
              })
            // }
          })
        }

      },
      fail: ({ statusCode, data }) => {
        // 控制台调试日志
        console.log('[ERROR]', statusCode, data)
        // 失败回调
        return setTimeout(() => {
          this.isFunction(error) && error({statusCode, ...data})
          this.$apply()
        })
      },
      complete: (res) => {
        // 控制台调试日志
        //console.log('[COMPLETE]', res)
        // 隐藏加载提示
        wx.hideNavigationBarLoading()
        // 停止下拉状态
        wx.stopPullDownRefresh()
        // 完成回调
        return (() => {
          this.isFunction(complete) && complete(res)
          this.$apply()
        })()
      }
    }))
  }

2、网络工具的使用
先引入工具方法所在的文件
import http from '../mixins/http'
在mixins对象做声明
mixins = [http]
调用工具方法,如,请求图书数据

    updateBookList(page) {

      this.loading = true
      // 请求列表
      this.$get({
        url: 'http://www......',
        data: {
          // 默认从1开始为第一页
          page: page
        }
      }, {
        success: ({code, data}) => {
          //  成功回调 逻辑处理
          data = data.data
          ... ... 
        },
        fail: ({code, data}) => {
          // 失败回调
        },
        complete: () => {
          this.loading = false
        }
      })
    }

总结

了解了代码的组织,找到各个主要逻辑/功能模块与代码文件之间的对应关系,通过代码分析走通几个关键的、有代表性的执行流程,挑选感兴趣的“枝干”代码来阅读(网络工具代码)。总体来说,对于微信小程序的开发有了进一步的认识。

相关文章

  • 小程序“友福图书馆”项目研究

    开启项目 新项目采用WePY开源框架开发,WePY项目的创建与使用步骤如下1、在全局安装WePY命令行工具,执行命...

  • 微信小程序使用webview加载网页

    最近准备将项目开发一个简易版,移植到小程序上,所以研究了下小程序,因为项目中很多页面是用webview加载的,所以...

  • 随笔

    小程序前段时间研究了一遍,也做了一个小例子,但是公司没有什么实际的小程序项目,想实际做个项目,自己也没什么方法了所...

  • 微信小程序开发总结(附源代码)

    最近公司项目不是很忙,有时间研究研究微信小程序。参考了目前市场上各类答题类的app、小程序等等,做了一款自己的微信...

  • 腾讯云通讯IM 接入小程序 (一)登录

    最近小程序项目中需要客服聊天功能;所有就简单研究哈,需用用到小程序发送消息 ,图片,表情,语言,模板等功能;由于时...

  • 程序包org.apache.http不存在,解决方式

    小编iOS程序上线后,项目经理让我来研究一下安卓。好吧 那就研究吧。从最基础的来,先把现有的项目跑起来。 万万没想...

  • 微信小程序

    创建小程序 新建项目选择小程序项目,选择代码存放的硬盘路径,填入刚刚申请到的小程序的 AppID,给你的项目起一个...

  • 小程序部署流程

    小程序部署流程: 一、 注册小程序(小程序接入指南) 二、创建小程序项目(简易教程·小程序) 三、部署开发环境(开...

  • 小程序项目

    一、vscode中小程序使用less Step 1:Ctrl+Shift+X 打开扩展 - 搜索 easy Les...

  • 小程序项目

    项目的基本组成结构 pages 用来存放所有小程序的页面,每个页面都是一个单独的文件夹 utils 用来存放工具性...

网友评论

      本文标题:小程序“友福图书馆”项目研究

      本文链接:https://www.haomeiwen.com/subject/zomvaxtx.html