微信小程序初探

小程序是一种不须要下载安装便可使用的应用,它实现了应用「触手可及」的梦想,用户扫一扫或搜一下便可打开应用。也体现了「用完即走」的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。 ——张小龙javascript

微信小程序框架

clipboard.png
微信小程序分为视图层和逻辑层,视图层包含WXML(相似HTML)、WXSS(相似css),逻辑层包含javascript文件。视图层经过事件通知逻辑层,而逻辑层经过控制data来更新视图。此外,微信还提供了API、组件、配置文件,使微信小程序的开发更加简单。css

在开发微信小程序时,咱们经过网络请求请求数据,对数据进行必定的处理绑定到视图便可,因为组件的存在,简单的展现变得更加简单。涉及网络请求、媒体、文件、缓存、位置、设备、支付、二维码等功能时,均可以去调用相应的API。因此,微信小程序的开发足够简单,能够快速开发并实现。html

固然,利弊是共存的,微信小程序开发起来虽然简单,可是限制也较多、灵活性却不足。在微信小程序中,要更新视图就只能修改data,而视图层也只能经过事件向逻辑层传递交互信息。前端传统的Dom操做在微信小程序中是不可用的,由于window、document在微信小程序中都不存在,因此,只要涉及操做Dom的代码均不可复用。微信小程序WXML提供的标签也比HTML要少不少,可是常见的标签都是有的,WXSS支持的样式也比CSS要少一些。若是要将H5页面移植到微信小程序,要修改的地方还比较多:前端

  1. WXML标签与HTML标签并不一致,要重写;java

  2. 微信小程序无DOM交互能力,涉及DOM操做的代码须要在小程序中单独设计;git

  3. 网络请求、媒体、文件、缓存、界面等相关内容须要使用小程序提供的API来实现,API的使用比较简单;程序员

  4. 与上述内容无关的JS逻辑代码是能够复用的;github

  5. css代码可复用率高,除了一些复杂的CSS3样式外,基本移植可用。小程序额外提供了flex、rpx的实现,作响应式页面变得更加容易。json

综上,微信小程序开发简单,码农们能够快速上手,开发出一个可用的小程序。可是,微信小程序限制也很多,不能操做DOM,支持的HTML标签和CSS样式少一些,作一些炫酷的动画或者复杂的功能就比较困难。H5页面移植到微信小程序要修改的地方也还比较多,主要是WXML标签、JS和HTML的交互及小程序提供的API功能部分。小程序

微信小程序开发姿式

若是你要开始开发一款微信小程序了,那么正确的步骤是什么呢?我也不知道啊。。。如下个人我的推荐步骤:

  1. 先了解微信小程序为什么而生,从产品的角度去思考微信小程序的利与弊(对于程序员思考为何小程序要如此设计、为何里面有各类限制是很是有帮助的),推荐《一篇文章读懂微信小程序(应用号)是什么?》《你的产品适不适合作微信小程序?》

  2. 总体认识小程序的框架、设计理念、开发的利弊;

  3. 通读微信小程序官网

  4. 仔细阅读小程序官网的开发部分(https://mp.weixin.qq.com/debu...,下载微信小程序开发者工具,体验官网提供的Demo;

  5. 开始开发微信小程序。

模块化

JavaScript模块化

微信小程序中,JS文件中声明的变量和函数只在该文件中有效;不一样的文件能够声明相同名字的变量和函数,不会相互影响。若是须要获取全局的应用实例,能够在App()中设置。

// app.js
App({
  globalData: 1
})

// a.js
// The localValue can only be used in file a.js.
var localValue = 'a'
// Get the app instance.
var app = getApp()
// Get the global data and change it.
app.globalData++

此外,能够经过require()引入其余JS文件,在文件中能够经过module.exports来暴露模块接口。

// common.js
function sayHello(name) {
  console.log(`Hello ${name} !`)
}
module.exports.sayHello = sayHello
// index.js
var common = require('common.js')
Page({
  helloMINA: function() {
    common.sayHello('MINA')
  }
})

WXML模块化

WXML能够经过模板(template)来组织标签,使WXML拆分合理、清晰易读。使用template标签来定义模版,使用name属性指定模版名称;经过import标签来引入模版,并使用is属性来指定使用的模版名称,data传入属性。

// template/msgItem.wxml
<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>
// index.wxml
<import src="./template/msgItem.wxml" />
<template is="msgItem" data="{{...item}}"/>

WXSS模块化

使用@import语句能够导入外联样式表,@import后跟须要导入的外联样式表的相对路径,用;表示语句结束。

/** common.wxss **/
.small-p {
  padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
  padding:15px;
}

视图层与逻辑层交互

视图层包含相似HTML的WXML、基本等同于CSS的WXSS,逻辑层则包含ES,去除了window、document等对象及方法,提供了一些API。视图层经过事件来通知逻辑层交互,逻辑层经过修改data来更新视图。

简单交互例子

<view id="tapTest" data-name="Payton" bindtap="tapName"> {{userName}}, Click me! </view>
Page({
    data: {
        userName: 'xxx'
    },
    tapName: function(e){
        wx.showToast({
            title: 'hi,' + this.data.userName + 'I`m ' + e.currentTarget.dataset.name,
            icon: 'success',
            duration: 2000
        })
    }
})

WXML中的动态数据均来自对应 Page 的 data。数据绑定使用双大括号将变量包起来,数据改变(this.setData())时就会更新视图,更新方式相似于虚拟dom。而事件的定义须要在标签属性中指定事件处理函数名称,事件处理函数在Page({})中定义,若是事件处理函数须要传递参数,则要在标签的data-中定义,可是通常状况下,咱们是不须要传递参数的,由于大部分的数据咱们能够在事件处理函数中只是使用this.data.的方式取得。

修改data

在小程序中,要使用this.setData()的方式来修改data,进而更新视图。可是,当要修改data中的二级数据时,将不会进行合并修改。如:

Page({
    data: {
        userInfo: {
            name: 'payton',
            sex: 1
        },
        tip: 'hello, world'
    },
    onLoad: function(){
        this.setData({tip: 'hello, world!'}) // 进行合并修改,userInfo不变
        this.setData({userInfo: {name: 'peyton'}}) // 二级数据,总体修改。userInfo中sex消失,userInfo为{name: 'peyton'}
    }
})

不少时候,咱们在修改data时,是但愿只修改咱们传入的参数,而原有的参数不进行变动的,如上面咱们只但愿修改name,而sex保持和原来一致。因此,咱们能够采起一下方式:

this.setData({
    userInfo: {
        name: 'peyton',
        sex: this.data.userInfo.sex
    }
})

可是这种方式很麻烦,并且很容易形成忘记一些内容,或者修改属性名时很容易漏掉。因此,咱们设计了一个函数,来实现这种深层次数据的合并修改。使用下面的方式,即可以进行合并了。

// util.js
function mergeObject(to, source) {
    var from;
    var symbols;

    for(var s = 1; s < arguments.length; s++) {
        from = Object(arguments[s]);

        for(var key in from) {
            if(hasOwnProperty.call(from, key)) {
                to[key] = from[key];
            }
        }
    }

    return to;
};
module.exports.mergeObject = mergeObject;
var util = require('../util.js');
Page({
    ...
    onLoad: function(){
        this.setData({tip: 'hello, world!'}) //进行合并修改,userInfo不变
        this.setData({
            userInfo: util.mergeObject(this.data.userInfo, {
                name: 'peyton'
            })
        }) // 合并修改,sex不会消失。userInfo为{name:'peyton',sex:1}
    }
})

插入HTML

在开发H5页面时,咱们一般要使用innerHTML来修改一个标签内的HTML,在小程序中,咱们没法手动修改DOM。好比:后台传递过来一短内容,这段内容要展示在页面中,可是其中包含图片,且图片数目不定。咱们就没有办法经过js来构造HTML片断,并插入到视图中。在开发花样直播时,有时候一个用户发送的内容中包含表情,也就是图片,此时,使用小程序的data是没法解析标签的,这个功能实现起来就很麻烦。个人实现方式以下:

// msg.wxml
<block wx:for="{{contents}}" wx:for-item="content">
    <text wx:if="{{content.type == 'text'}}" class="content">{{content.text}}</text>
    <image wx:if="{{content.type == 'image'}}" class="emoji" src="{{content.src}}"></image>
</block>
// 后台传递的content: 主播好漂亮/:149/ (注:/:149/表示微笑表情) 
if (...) {
    return {
        type: 'text',
        text: text
    }
} else if (..){
    return {
        type: 'image',
        src: src
    }
}

也就是要将后台传递的内容转成数组,而且须要标明类型,再根据条件渲染,分别渲染成文字和图片。因为我这里的需求只须要关注展现文字和表情,因此这种方式处理起来就OK。可是,若是后台传递的是文章类型的内容(包含图片、标题等等),须要转换成多种格式,再本身写就会很麻烦了。这个时候推荐使用wxParse(https://github.com/icindy/wxP...,支持HTML及markdown解析,其实现思路其实和上面方式相似。使用wxParse的话,能够将H5版本构造的html片断直接传入wxParse,wxParse会进行解析,最终转换成小程序版本。不过,有同事用过,不过反馈说页面中图片多的话,用wxParse会比较卡,我本身没有尝试过,此处就再也不多说。

小程序组件及API

小程序自己提供了不少组件和API,使用这些组件和API能够很方便的进行开发,极大的加快开发进程。目前来讲,有些组件和API还有些小坑,目前仍在动态完善中。关注此部分,官网上全面不少,此处只作简述。

配置

在小程序中,能够经过app.json对小程序进行全局的配置,在每一个页面中能够进行有关配置(只能配置页面内的配置项,比全局配置要少)。在全局配置中,能够配置的内容为:

  1. pages,设置页面路径,第一个路径即为默认初始页,全部的页面路径均须要配置;

  2. window,设置默认页面的窗口表现,如状态栏、导航条、标题、窗口背景色等(能够在页面中配置,覆盖全局配置);

  3. tabBar,设置tab的表现,能够设置图片、文字等;

  4. networkTimeout,网络超时时间;

  5. debug,设置是否开启 debug 模式。

组件

与H5相比,WXML提供的组件种类并不算多,可是经常使用的都有,开发个小程序不成问题。其组件中提供了一些便捷的属性,仍是很方便的,可是属性与H5相比仍然不全面。

  1. 视图容器:view(相似div)、scroll-view(相似带滚动条的div)、swiper(滑块视图容器);

  2. 表单组件:button、checkbox、form、input、label等;

  3. 基础内容:icon(小程序提供的图标)、text(行内文本)、progress(进度条);

  4. 媒体组件:audio、image(background-image的形式有不少坑,最好用image)、video;

  5. 地图、画布、导航、客服会话等。

API

微信小程序提供的API仍是挺多,用起来也还不错。

  1. 网络:请求(http请求,使用手感不错)、上传、下载、WebSocket(服务器能支持就很爽了);

  2. 媒体:图片、录音、音频控制、视频控制(目前感受这部分提供的API仍然不足);

  3. 界面:提示框、弹框、导航条设置、跳转、下拉刷新、绘图等;

  4. 数据缓存、设备(罗盘、扫码、拨打电话、重力感应等)、文件等;

  5. 开放接口:登陆、微信支付、用户信息、模板消息、分享等。