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

很早就注册了微信小程序内测,因为是拖延症晚期患者,所以一直都没有学习。直到昨天(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后的效果

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

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如何自定义呢?除了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效果

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

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

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 = blablabla 或 pageParams.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://juejin.im/post/5865e50361ff4b006ba7fa80

个人建了前端学习群,旨在一起学习前端。纯净、纯粹技术讨论,非前端人员勿扰!入群加我微信iamaixiaoxiao。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值