小程序是一种不须要下载安装便可使用的应用,它实现了应用「触手可及」的梦想,用户扫一扫或搜一下便可打开应用。也体现了「用完即走」的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。 ——张小龙javascript
微信小程序分为视图层和逻辑层,视图层包含WXML(相似HTML)、WXSS(相似css),逻辑层包含javascript文件。视图层经过事件通知逻辑层,而逻辑层经过控制data来更新视图。此外,微信还提供了API、组件、配置文件,使微信小程序的开发更加简单。css
在开发微信小程序时,咱们经过网络请求请求数据,对数据进行必定的处理绑定到视图便可,因为组件的存在,简单的展现变得更加简单。涉及网络请求、媒体、文件、缓存、位置、设备、支付、二维码等功能时,均可以去调用相应的API。因此,微信小程序的开发足够简单,能够快速开发并实现。html
固然,利弊是共存的,微信小程序开发起来虽然简单,可是限制也较多、灵活性却不足。在微信小程序中,要更新视图就只能修改data,而视图层也只能经过事件向逻辑层传递交互信息。前端传统的Dom操做在微信小程序中是不可用的,由于window、document在微信小程序中都不存在,因此,只要涉及操做Dom的代码均不可复用。微信小程序WXML提供的标签也比HTML要少不少,可是常见的标签都是有的,WXSS支持的样式也比CSS要少一些。若是要将H5页面移植到微信小程序,要修改的地方还比较多:前端
WXML标签与HTML标签并不一致,要重写;java
微信小程序无DOM交互能力,涉及DOM操做的代码须要在小程序中单独设计;git
网络请求、媒体、文件、缓存、界面等相关内容须要使用小程序提供的API来实现,API的使用比较简单;程序员
与上述内容无关的JS逻辑代码是能够复用的;github
css代码可复用率高,除了一些复杂的CSS3样式外,基本移植可用。小程序额外提供了flex、rpx的实现,作响应式页面变得更加容易。json
综上,微信小程序开发简单,码农们能够快速上手,开发出一个可用的小程序。可是,微信小程序限制也很多,不能操做DOM,支持的HTML标签和CSS样式少一些,作一些炫酷的动画或者复杂的功能就比较困难。H5页面移植到微信小程序要修改的地方也还比较多,主要是WXML标签、JS和HTML的交互及小程序提供的API功能部分。小程序
若是你要开始开发一款微信小程序了,那么正确的步骤是什么呢?我也不知道啊。。。如下个人我的推荐步骤:
先了解微信小程序为什么而生,从产品的角度去思考微信小程序的利与弊(对于程序员思考为何小程序要如此设计、为何里面有各类限制是很是有帮助的),推荐《一篇文章读懂微信小程序(应用号)是什么?》、《你的产品适不适合作微信小程序?》;
总体认识小程序的框架、设计理念、开发的利弊;
通读微信小程序官网;
仔细阅读小程序官网的开发部分(https://mp.weixin.qq.com/debu...,下载微信小程序开发者工具,体验官网提供的Demo;
开始开发微信小程序。
微信小程序中,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能够经过模板(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}}"/>
使用@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.的方式取得。
在小程序中,要使用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} } })
在开发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还有些小坑,目前仍在动态完善中。关注此部分,官网上全面不少,此处只作简述。
在小程序中,能够经过app.json对小程序进行全局的配置,在每一个页面中能够进行有关配置(只能配置页面内的配置项,比全局配置要少)。在全局配置中,能够配置的内容为:
pages,设置页面路径,第一个路径即为默认初始页,全部的页面路径均须要配置;
window,设置默认页面的窗口表现,如状态栏、导航条、标题、窗口背景色等(能够在页面中配置,覆盖全局配置);
tabBar,设置tab的表现,能够设置图片、文字等;
networkTimeout,网络超时时间;
debug,设置是否开启 debug 模式。
与H5相比,WXML提供的组件种类并不算多,可是经常使用的都有,开发个小程序不成问题。其组件中提供了一些便捷的属性,仍是很方便的,可是属性与H5相比仍然不全面。
视图容器:view(相似div)、scroll-view(相似带滚动条的div)、swiper(滑块视图容器);
表单组件:button、checkbox、form、input、label等;
基础内容:icon(小程序提供的图标)、text(行内文本)、progress(进度条);
媒体组件:audio、image(background-image的形式有不少坑,最好用image)、video;
地图、画布、导航、客服会话等。
微信小程序提供的API仍是挺多,用起来也还不错。
网络:请求(http请求,使用手感不错)、上传、下载、WebSocket(服务器能支持就很爽了);
媒体:图片、录音、音频控制、视频控制(目前感受这部分提供的API仍然不足);
界面:提示框、弹框、导航条设置、跳转、下拉刷新、绘图等;
数据缓存、设备(罗盘、扫码、拨打电话、重力感应等)、文件等;
开放接口:登陆、微信支付、用户信息、模板消息、分享等。