从零开始带你撸一个小程序

阅读 1538
收藏 81
2017-01-19
原文链接:zhuanlan.zhihu.com

从零开始带你撸一个小程序

余博伦 ·
微信推出小程序已经有些天了,相信同学们或多或少都把玩体验过小程序了。今天从零学习前端开发专栏就手把手带你,从零开始撸一个小程序。

P.S.正式开始前先声明,本教程示例仅供前端萌新学习体验,闲杂人等可以退散啦。

小程序的注册(可跳过)

小程序是面向企业、政府、媒体等其他组织开放注册的,注册时必须提供相应的主体信息,所以假如你是不代表任何组织没注册过任何公司的独立开发者,就可以直接跳过这一步啦,虽然不注册就很遗憾的不能在真机体验调试自己写的小程序,不过最重要的是学习知识不是么?

给有条件的同学的传送门:小程序注册图文教程

如果你之前有玩过微信公众号的话,注册和配置流程其实都大同小异。

小程序本地开发环境搭建

小程序使用微信Web开发者工具作为IDE。微信Web开发者工具是微信官方使用NW.js开发的一个跨平台桌面端应用,好坏先不做评价,至少能用。虽然现在小程序已经有了一些第三方的开发工具,有更多Hack以及更少的限制,但为了教程的简洁这里就不再赘述,有兴趣的同学可以自己去玩玩看。

微信Web开发者工具下载

第三方小程序开发工具

微信Web开发者工具的安装更是简单,不停点下一步就好了。

创建小程序项目

按照微信官方简易教程的指引,创建一个新的小程序项目。

我们需要打开微信Web开发者工具,扫码登陆,选择开发本地小程序,然后点击新建项目,填入你的小程序AppID,项目名称,目录等等。

其实不管你有没有注册小程序,为了方便调试最好都选择无AppID,如果选择无AppID一些API的返回都是本地模拟的,并且没有请求远程服务器的域名限制,反而方便你开发调试。

创建项目的时候我们可以勾选创建quick start项目,来当作我们编写代码的模板,其实这个quick start项目的代码就是微信官方的简易教程中的示例代码,当然如果你有心的话,也可以手动跟着教程把代码敲一遍。

开发者工具简介

创建好项目并打开之后,我们会看到一个类似或者其实根本就是Chrome打开开发者工具并启用移动端模拟的界面。

左边有3个选项卡【编辑】【调试】【项目】,开发的过程中大多数时间里我们都是在【编辑】【调试】之间来回切。

切换到【编辑】选项卡,我们就能看到小程序项目目录以及代码编辑界面。

小程序示例开发

接下来我们会在quick start项目代码的基础上开发一个获取用户位置并显示天气的小程序,一边学习理解小程序的框架设计,一边尝试动手编写代码。

首先每一个小程序都需要声明一个App对象

//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
  }
})

假如你之前了解过React/Vue任意一个框架的话,应该会看到很多他们的影子:

//React
class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { secondsElapsed: 0 };
  }

  tick() {
    this.setState(prevState => ({
      secondsElapsed: prevState.secondsElapsed + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return React.createElement(
      "div",
      null,
      "Seconds Elapsed: ",
      this.state.secondsElapsed
    );
  }
}
//Vue
var vm = new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vm 实例
    console.log('a is: ' + this.a)
  },
  mounted: function () {
    console.log('mounted!')
  },
  updated: function () {
    console.log('updated!')
  },
  destroyed: function () {
    console.log('destroyed!')
  }
})

每一个小程序都会有一个app.json的配置文件,这里面其实有很多好玩的地方:

{
  "pages":[//小程序包含的页面
    "pages/index/index",//页面路径
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#2f3b53",//标题栏背景色(这也许是小程序和移动端Web应用最大的不同了)
    "navigationBarTitleText": "Weather",//标题栏文字
    "navigationBarTextStyle":"white"//标题栏文字颜色
  },
  "tabBar": {//配置小程序选项卡,是的,你不需要写多余的导航栏代码,只需要配置一段JSON即可
    "selectedColor":"#73d0f4", //Tab栏选中文字的颜色
    "list": [{//选项卡列表,最多可以配置5项
      "pagePath": "pages/index/index",//对应页面地址
      "iconPath": "assets/images/home_n.png",//Tab选项卡默认图标
      "selectedIconPath": "assets/images/home.png",//Tab选中后的图标
      "text": "首页"//Tab文字
    }, {
      "pagePath": "pages/logs/logs",
      "iconPath": "assets/images/box_n.png",
      "selectedIconPath": "assets/images/box.png",
      "text": "日志"
    }]
  }
}

你可以在quick start项目的基础上把app.json文件修改成如上内容,当然你也可以参考官方配置文档自己折腾一会儿。

另外补充一下,Tab栏的图标当然不是凭空变出来的,你可以在easyicon或者其他类似的网站下载你需要的图标,具体风格可以参考微信底部导航,需要注意的是你要为每个图标准备两个文件,一个默认显示,一个在选中时显示。

制作这样图标文件的最简单办法是在PS中打开图标文件,选择图像->调整->去色并另存为。

小程序页面

小程序的所有页面一般都被保存在pages文件夹里,每一个独立的页面也有自己的文件夹,每个页面都包含自己的js/json/wxml/wxss文件,不管每个文件里有没有内容,你创建的页面只要一次调试编译之后这四个文件都会自动生成。

.js和.json文件可以延伸刚刚介绍过的app.js/app.json文件的概念,页面的这两个文件分别储存每个独立页面的逻辑和配置信息。

.wxml可以理解为.html的阉割版,用来编写小程序页面的内容。

.wxss可以理解为.css的阉割版,用来设计小程序页面的样式。

接下来我们再动手写几行代码,首先把pages/index/index.wxml改写成如下内容:

<!--index.wxml-->
<!--view是wxml中最基本的一种视图容器,你可以把它理解为div一类的东西-->
<view class="container">
  <!--bindtap类似于vue里的v-on:click,用于处理页面元素的事件绑定,待会儿我们会在index.js里看到一个bindViewTap的方法-->
  <view  bindtap="bindViewTap" class="userinfo">
  <!--{{userInfo.avatarUrl}}这类的双花括号和vue简直是一模一样了,用来显示js中的变量,当然也可以包含一些简单的运算和逻辑判断,image你就理解为img标签好了-->
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
    <!--text可以理解为p标签,当然只是为了方便理解,上述所有的view/image/text等都是小程序预置的界面组件-->
    <text class="userinfo-nickname">{{userInfo.nickName}}</text>
  </view>
  <!--wx:if完全可以理解为vue当中的v-if,哈哈,其实不如去学学vue吧,weather是一个对象变量,可以用点来访问其属性值-->
  <view wx:if="{{weather.location}}" class="weather">
    <text class="city">{{weather.location.name}}</text>
    <text class="condition">{{weather.now.text}}</text>
    <text class="temp">{{weather.now.temperature}} ℃</text>
  </view>
</view>

接下来在index.wxss的底部添加下列内容,我承认我偷懒了,你可以稍微花点功夫认真设计一下你小程序的外观样式:

.weather {
  margin-top: 50px;
  display: flex;
  flex-direction: column;
}

.city,.condition,.temp {
  width:100%;
  margin-top: 10px;
}

wxss支持不完全的css选择器,引入了名为rpx的尺寸单位等,有关wxss具体可以查看wxss文档

最后到了重头戏,让我们打开index.js,将其改写为如下内容:

//index.js
//获取应用实例
var app = getApp()
Page({
  data: {
    userInfo: {},
    //这里新增了一个weather变量
    weather: {}
  },
  //事件处理函数,这就是刚刚在index.wxml当中绑定的事件函数
  bindViewTap: function() {
    //将函数的内容改写为我们自定义的一个方法
    this.getLocation()
  },
  //这个自定义方法调用了wx.getLocation和wx.request两个小程序API,用来获取用户位置信息并从远程服务器请求相关天气数据
  getLocation: function () {
    //示例中有很多这样that = this的代码,但我发现最新的开发者工具是支持ES6的,你完全可以用autobinding一类的语法糖来避免这些冗余的绑定代码
    var that = this
    //这是小程序的一个API,用来获取用户的地理位置
    wx.getLocation({
      type: 'wgs84',
      success: function(res) {
        var latitude = res.latitude
        var longitude = res.longitude
        //wx.request用来发起向远程服务器的请求
        wx.request({
          //wx.request访问的远程网址必须是https,这里使用的是很棒的心知天气的API,可以免费注册
          url: 'https://api.thinkpage.cn/v3/weather/now.json?key=xxxxxxxxxxx&location='+latitude+':'+longitude, 
          success: function(res) {
            console.log(res.data.results[0])
            //setData方法可以理解为React当中的setState方法,用来修改我们在开头定义的weather变量,你不能直接通过data.weather来修改,那样的操作会破坏数据绑定
            that.setData({
              weather:res.data.results[0]
            })
          }
        })
      }
    })
  },
  //onLoad是页面的一个生命周期函数,类似于App对象中的,小程序的页面和应用对象都有一系列相关的生命周期函数
  onLoad: function () {
    console.log('onLoad')
    //这里再啰嗦一下,因为对象中的方法this默认指向undefined,所以我们需要手动指定this,这段代码还可以写成:
    /**
    * app.getUserInfo(function(userInfo){
    *    //更新数据
    *    this.setData({
    *      userInfo:userInfo
    *    })
    * }.bind(this))
    * 或者使用es6写成:
    * app.getUserInfo((userInfo) => {
    *    this.setData({
    *      userInfo:userInfo
    *    })
    * })
    */
    var that = this
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function(userInfo){
      //更新数据
      that.setData({
        userInfo:userInfo
      })
    })
    //that.getLocation()
  }
})

示例中使用的API来自心知天气,你可以免费注册并将API地址中的key=xxxxxxxxxxx替换为你自己的key.

另外要注意的一点是,如果你注册并填写了小程序的AppID,还需要在小程序的设置中填写request请求的合法域名,否则在调试时会报错,而没有填写AppID的小程序则不受这个限制。

之后记得保存所有的文件,刷新小程序页面,我们的天气示例小程序就大功告成啦,现在点击你的微信头像,就可以获取你所在地区的天气信息啦。

如果你注册了小程序,还可以切换到【项目】选项卡,点击预览并通过微信扫码进行真机调试:

到这里我们的教程就告一段落啦,如果你对小程序很感兴趣,可以自己进行更深入的尝试和学习,还有很多在普通网页中无法访问的有意思的API可以玩。

本教程示例代码:discountry/weapp-weather

更多有关小程序的资源请访问:微信小程序开发资源汇总

而我个人以为学小程序还不如学学React或者Vue,又或者踏踏实实地学编程。

风头过后,小程序离改变世界还有着遥不可及的距离。

有任何好的建议或意见以及对小程序的任何观点看法欢迎在评论区参与讨论。


本文对你有帮助?欢迎扫码加入前端学习小组微信群:

评论
说说你的看法