现学现卖微信小程序开发(一)

作者: 接灰的电子产品 | 来源:发表于2016-12-30 12:45 被阅读2290次

    现学现卖微信小程序开发(一)
    现学现卖微信小程序开发(二)
    现学现卖微信小程序开发(三):引入Rx,为小程序插上翅膀

    现学现卖微信小程序开发

    很早就注册了微信小程序内测,因为是拖延症晚期患者,所以一直都没有学习。直到昨天(2016年12月28日),张小龙童鞋宣布微信小程序2017年1月9日正式上线,满屏都是小程序的消息。我这时才想起来,我不能白交了300块钱啊,得学啊。

    反正学习也得总结,倒不如现学现卖写一个教程吧。话说回来现学现卖肯定有不少错误,大家多包涵哈。废话少说,我们开工,首先下载微信小程序开发工具 https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 选择自己的平台下载安装即可。

    微信小程序开发工具下载页面微信小程序开发工具下载页面

    注册小程序号的过程我就不讲了(网上这类教程一堆,不用我花时间在这里。),你要开发的话,最好通过公司申请一个。第一次启动开发工具时需要扫码,然后选择添加一个无appId的项目。做个什么项目好呢,没想好,那就还是先把Todo牵出来吧。我们来实现一个微信小程序版的Todo,同样是带HTTP后台的版本。为什么又选择Todo呢?因为它的逻辑相对完整,增删改查都有,HTTP请求、返回俱全。在一个平台折腾明白这个app就基本可以上手干活了,这货简直就是新时代的Hello World啊。

    文件结构

    新建工程时,默认开发工具会生成一个样例给我们。我们就来看看这个样例是什么东东。开发工具的左侧是一个预览,中间那栏是文件目录,看目录结构倒是蛮简单:

    开发工具自动帮助生成了一个样本工程开发工具自动帮助生成了一个样本工程

    全局文件

    先来看一下根目录:这个目录下有三个文件app.js,app.json和app.wxss。app.js是应用入口,里面定义了App() 函数,用来注册一个小程序,就像Android里面的Application和Angular2中的。接受一个 object 参数,其指定小程序的生命周期函数等。

    //app.js
    App({
      onLaunch: function () {
        //调用API从本地缓存中获取数据
        var logs = wx.getStorageSync('logs') || []
        logs.unshift(Date.now())
        wx.setStorageSync('logs', logs)
      },
      getUserInfo:function(cb){
        var that = this
        if(this.globalData.userInfo){
          typeof cb == "function" && cb(this.globalData.userInfo)
        }else{
          //调用登录接口
          wx.login({
            success: function () {
              wx.getUserInfo({
                success: function (res) {
                  that.globalData.userInfo = res.userInfo
                  typeof cb == "function" && cb(that.globalData.userInfo)
                }
              })
            }
          })
        }
      },
      globalData:{
        userInfo:null
      }
    })
    
    

    从上面的例子代码看的话,虽然简单还是能看出一些东西的:

    • App()本身就是一个函数,在其他页面可以通过系统提供的getApp()来得到应用的实例。
    • onLaunch就是一个生命周期函数,是当小程序初始化完成时,会触发这个函数(只触发一次)。这里在应用初始化时向本地存储写入了一个日期。
    • globalData是个全局数据的存放区域,示例代码中只放置了一个userInfo作为全局变量。
    • 例子代码在这里定义了一个全局方法getUserInfo,这个全局方法的访问可以通过getApp().getUserInfo()。如果你打开 pages/index/index.js,你会发现示例代码通过getApp()取得应用实例后调用了getUserInfo这个全局方法
    //获取应用实例
    const app = getApp()
    ...
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function(userInfo){
      //更新数据
      that.setData({
        userInfo:userInfo
      })
    })
    

    那么类似像onLaunch这样的生命周期函数有哪些呢?还有onShow,onHide和onError。onShow和onHide分别是应用从后台切换到前台以及从前台进入后台时调用的。当你关闭小程序或者切换微信应用到别的应用时,微信并没有直接干掉小程序,小程序只是进入后台而已,当你切换回来,小程序就又进入了前台。这个机制其实和Android以及iOS的应用切换很像。onError顾名思义就是小程序发生脚本错误或者api调用失败是触发的。注意:请不要在其他页面调用生命周期函数

    接下来我们看看 app.json,这个东东呢,就是小程序的应用全局配置文件。结构也很简单:pages定义页面的文件路径,window定义小程序整个窗口的一些元素,比如Title的文字,Title的颜色,窗口背景颜色等等。

    {
      "pages":[
        "pages/index/index",
        "pages/logs/logs"
      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "todos",
        "navigationBarTextStyle":"black"
      },
      "debug": true
    }
    

    比如在上面的配置下,窗口的展现形式是这样的

    在默认配置下窗口的表现在默认配置下窗口的表现

    如果我们改动app.json 成为下面的样子,那么是什么效果呢?

    {
      "pages":[
        "pages/index/index",
        "pages/todos/todos"
      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#000",
        "navigationBarTitleText": "todo",
        "navigationBarTextStyle":"white",
        "backgroundColor": "#492b2b"
      },
      "debug": true
    }
    
    
    改动app.json后的效果改动app.json后的效果

    嗯,导航栏背景变成黑色了,文字白色,一切很完美。且慢,我们不是还添加了一个 "backgroundColor": "#492b2b" 吗,它的效果怎么没有出来呢?你点击头像进入log页面后,再点击左上角返回会看到一个动画,这个动画的背景竟然是我们设置的窗口背景色!?

    backgroundColor体现在界面切换时backgroundColor体现在界面切换时

    但为毛在静态界面上看不到呢,我猜想是由于Page挡在了背景前面,但是不是呢,我们来用试验验证一下。怎么验证呢,我们在window的设置中再加一个配置 "enablePullDownRefresh": "true",这个是激活下拉刷新的效果的开关,我们试一下,拖住界面往下拉,果然,窗口背景色在后面藏着呢!

    下拉后露出了窗口背景色下拉后露出了窗口背景色

    同样 backgroundTextStyle定义的是下拉背景字体、loading 图的样式(仅支持 dark/light)

    在这个配置文件中,我们还可以定义用于切换界面的工具栏(tab bar),我们也来试验一下吧。

    {
      "pages":[
        "pages/index/index",
        "pages/todos/todos"
      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#000",
        "navigationBarTitleText": "todo",
        "navigationBarTextStyle":"white",
        "backgroundColor": "#492b2b",
        "enablePullDownRefresh": "true"
      },
      "tabBar": {
        "list": [{
          "pagePath": "pages/index/index",
          "text": "首页"
        }, {
          "pagePath": "pages/logs/logs",
          "text": "日志"
        }]
      },
      "debug": true
    }
    
    配置tabBar后的效果配置tabBar后的效果

    嗯嗯,很丑陋,但是毕竟显示出来了。那么问题来了,这个tabBar如何自定义呢?除了list属性,它还提供color,selectedColor,backgroundColor,borderStyle和postion属性。我们都设置一下

      "tabBar": {
        "list": [{
          "pagePath": "pages/index/index",
          "text": "首页",
          "selectedIconPath": "assets/images/home.png"
        }, {
          "pagePath": "pages/logs/logs",
          "text": "日志",
          "iconPath": "assets/images/log.png"
        }],
        "color": "#b0bec5",
        "backgroundColor": "#2196F3",
        "selectedColor": "#fff",
        "borderStyle": "#F8BBD0",
        "position": "bottom"
      }
    
    自定义tabBar效果自定义tabBar效果

    还是比较丑,码农加直男,只能凑活了。你可能发现我在list中一个添加的是selectedIconPath,一个添加的是iconPath。其实我是犯懒,不想再找两个图片而已。恰好首页是默认选中的tab,那么正好两个图标都能显示出来。

    除了tabBar,还可以设置一个debug属性,默认是false,如果设置成true,那么你在调试的时候,会发现在console里面显示很多log信息。其信息有Page的注册,页面路由,数据更新,事件触发等。这个开关在开发时建议打开,在发布时记着关闭哈。

    debug设置成true会在console里面显示很多log信息debug设置成true会在console里面显示很多log信息

    再来看 app.wxss,估计你猜也猜得到,这个就是类似css的样式表了。这个全局样式所有页面都可以使用。

    /**app.wxss**/
    .container {
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: space-between;
      padding: 200rpx 0;
      box-sizing: border-box;
    } 
    
    

    像我这么爱折腾的人,对于这个css肯定要鼓捣一通,看看到底起什么作用?我们首先加一个背景色,红色比较显眼,background-color: red;

    首页的变化首页的变化

    首页下方有一片区域没有着色,先不管它,点头像进去看看。

    日志页面的变化日志页面的变化

    这种变化说明这个container选择器是应用于页面的,根据页面内容来决定高度,所以这个100%并不能填满全屏。好在微信小程序可以接受css的大部分设置,如果把 height: 100%; 改成 height: 100vh; 就可以填满全屏了。

    页面文件

    页面文件也很简单,基本就是和文件夹同名的 .js.json.wxss 文件,唯一多了一种类型就是 .wxml 文件。.js文件中定义一个Page函数,用于构建页面视图的逻辑,而.wxml描述页面视图的结构和布局。首先看一下index.js:

    var app = getApp()
    Page({
      data: {
        motto: 'Hello World',
        userInfo: {}
      },
      //事件处理函数
      bindViewTap: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
      onLoad: function () {
        console.log('onLoad')
        var that = this
        //调用应用实例的方法获取全局数据
        app.getUserInfo(function(userInfo){
          //更新数据
          that.setData({
            userInfo:userInfo
          })
        })
      }
    })
    

    由上面的结构可以看出基本上Page函数是一个这样的形式。它接受一个对象,这个对象有一些生命周期函数、事件处理函数和数据对象构成。也就是说上面的代码可以改写成下面这样的形式。

    let app = getApp()
    let pageParams = {
      data: {
        motto: 'Hello World',
        userInfo: {}
      },
      //事件处理函数
      bindViewTap: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
      onLoad: function () {
        console.log('onLoad')
        var that = this
        //调用应用实例的方法获取全局数据
        app.getUserInfo(function(userInfo){
          //更新数据
          that.setData({
            userInfo:userInfo
          })
        })
      }
    }
    Page(pageParams)
    

    事实上我们更倾向于这么写,因为这样的写法可以使我们避免太多嵌套,以及对pageParams做更多灵活的操作。因为是个对象,我们可以写成 pageParams.data = blablablapageParams.onLoad = someFunctionCall。对了,这个对象我也不知道叫什么,自己给它起的名字而已,反正Page函数是需要这么一个参数的。

    那么页面的内建函数有哪些呢?可以参照下表,其中前5项属于生命周期函数。

    内建函数 作用 调用机制
    onLoad 监听页面加载 生命周期内调用一次
    onReady 监听页面初次渲染完成 生命周期内调用一次
    onShow 监听页面显示 每次打开页面都会调用一次
    onHide 监听页面隐藏 当navigateTo或底部tab切换时调用
    onUnload 监听页面卸载 当redirectTo或navigateBack的时候调用
    onPullDownRefresh 监听用户下拉动作 用户动作触发
    onReachBottom 页面上拉触底事件的处理函数 事件触发
    onShareAppMessage 用户点击右上角分享 用户点击触发

    具体可以参看微信官方文档给出的页面生命周期示意图


    微信官方文档给出的页面生命周期示意图微信官方文档给出的页面生命周期示意图

    再来看看 index.wxml,其实就是类似html的一个模版文件,但是微信自己重造轮子的目的不是很清楚。这里 class="container" 应用了我们的全局样式。

    <!--index.wxml-->
    <view class="container">
      <view  bindtap="bindViewTap" class="userinfo">
        <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
        <text class="userinfo-nickname">{{userInfo.nickName}}</text>
      </view>
      <view class="usermotto">
        <text class="user-motto">{{motto}}</text>
      </view>
    </view>
    

    事件绑定是通过在组件标签内加 bindXXX=handler 来完成的,这个 handler 需要在pageParams对象中定义。 {{userInfo.nickName}} 是引用了我们在 index.js 中定义的数据对象的属性。

    index.json 也是蛮简单,就是设置页面的一些属性,比如我们改写一下的话:

    {
        "navigationBarTitleText": "首页"
    }
    

    导航栏文字就会变成我们设置的值。

    设置导航栏文字设置导航栏文字

    好的,到现在我们应该清楚了大概的微信小应用的基础知识。下一节我们会尝试着做我们的Todo应用了。

    相关文章

      网友评论

      本文标题:现学现卖微信小程序开发(一)

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