从零开始带你撸一个小程序
微信推出小程序已经有些天了,相信同学们或多或少都把玩体验过小程序了。今天从零学习前端开发专栏就手把手带你,从零开始撸一个小程序。
P.S. 正式开始前先声明,本教程示例仅供前端萌新学习体验,闲杂人等可以退散啦。

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

给有条件的同学的传送门: 小程序注册图文教程
如果你之前有玩过微信公众号的话,注册和配置流程其实都大同小异。
小程序本地开发环境搭建
小程序使用微信Web开发者工具作为IDE。微信Web开发者工具是微信官方使用 NW.js 开发的一个跨平台桌面端应用,好坏先不做评价,至少能用。虽然现在小程序已经有了一些第三方的开发工具,有更多Hack以及更少的限制,但为了教程的简洁这里就不再赘述,有兴趣的同学可以自己去玩玩看。
第三方小程序开发工具
微信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