您的位置:首页 > 移动开发 > 微信开发

前段.微信小程序开发Ⅰ(结构、逻辑、工作流)

2017-07-29 14:19 295 查看
最近因为一些原因,在负责微信小程序的开发与维护。对于一个初接触的东西,在开发过程中就难免会遇到一些问题,自然就需要去将其解决并进行一定的总结。

一个小程序分为逻辑层和视图层,逻辑层包括js文件,视图层包括wxml文件和wxss文件。

初建项目会有两个文件夹和三个以app命名的js/json/wxss文件,即



其中

app.js为小程序的逻辑文件,其中包括了小程序的生命周期函数、监听函数,以及定义全局的方法等。

app.json是小程序的公共设置文件。

1)它的“pages”属性必须包括所有小程序的界面,即所有的页面链接必须在“pages”中进行声明才能够进行跳转。“pages”属性中的路径文件后不需要标明文件类型后缀,因为在此处声明的页面文件类型都是默认的wxml。“pages”属性中的第一个页面链接为小程序的首页。

2)它包括了小程序默认页面和底部栏的样式,即“window”和”tabBar”。“window”属性中包括了导航栏的背景色、标题颜色,界面窗口的背景色的样式。“tabBar”用于定义底部list的属性,它只能配置最少2个、最多5个 tab。 tabBar中的颜色等属性需要放到与list同级的位置才能生效。

app.wxss是小程序的公共样式表。

打开pages文件,已经自动生成了一个默认的index文件,其中包括了四个文件,即.js/.json/.wxml/wxss,分别对应页面逻辑、页面结构。页面样式表、页面配置。其中的Js中必须要有Page的注册。这个就是小程序的页面文件了,跟我们平常写Web页面的结构差不多。

但是,小程序的视图层运用的是xml类的规则,即和平常我们写网页的html和css标签有很大的差别,必须按官方提供的标签来写,官方链接在此【传送至官方文档 】。

然后是源码逻辑与工作流。

先看入口app.js,app(obj)注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。其他文件可以通过全局方法getApp()获取app实例,进而直接调用它的属性或方法,例如(getApp().globalData)

//app.js
App({
//当程序初始化时执行onLaunch中的内容
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
//把用户信息赋给globalData,再次调用getUserInfo时,不需要调用登录接口
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
})
}
},
globalData:{
userInfo:null
}
})


我理解app.js为入口初始化文件,也是提供全局API拓展的地方。下边分析下自带的几个方法和属性

onLaunch钩子函数会在小程序初始化完成后会自动执行一次,然后在小程序生命周期里如果你不主动调用onLaunch,它就不会在执行。

wx.setStorageSync(‘logs’, logs) 将数据存入本地缓存,因为wx为全局对象,所以可以在其他文件中直接调用wx.getStorageSync(‘logs’)获取本地缓存数据。

然后是 getUserInfo函数,顾名思义就是获取登录用户信息,相当于此函数提供了获取用户信息的接口,其他页面不调用自然不会执行。其他页面通过getApp().getUserInfo(function(userinfo){console.log(userinfo);})这种方式调用该方法,获取用户信息。

getUserInfo:function(cb){
//参数为cb,类型为函数
var that = this
if(this.globalData.userInfo){
//用户信息不为空
typeof cb == "function" && cb(this.globalData.userInfo)
//若参数cb类型为函数,则typeof cb == "function" 为真,执行&&后面的cb,获取用户信息
}else{
//如果用户信息为空,也就是说第一次调用getUserInfo,会调用用户登录接口。
wx.login({
success: function () {
wx.getUserInfo({
success: function (res) {
         console.log(res)
//把用户信息赋给globalData,如果再次调用getUserInfo函数的时候,不需要调用登录接口
typeof cb == "function" && cb(that.globalData.userInfo)
//如果参数cb类型为函数,执行cb,获取用户信息
}
})
}
})
}
}


globalData对象用来存储全局数据,在其他地方调用

然后简要分析下app.json文件,该文件作用是对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等

  最重要的是pages属性,必填,为数组,数组内的元素为字符串性文件路径,指定小程序由哪些页面组成,第一项必须是小程序初始页面。

{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}


然后来看下项目index和logs文件夹。微信小程序初始项目把每个页面相关的js、wxss、wxml放在各自的文件,这样看起来结构清晰明朗很多。

  先来看index文件夹,即小程序初始页面。index文件夹下为index.js、index.wxml、index.wxss三个小文件。小程序把js、css、html代码分离开来,放在独自的文件里,各司其职。js和样式表文件名必须与当前文件夹的wxml文件名保持一致,这样才能保证js和样式表的效果能够在页面中显现出来。我很欣赏这样的设计理念,整齐划一,职责明确,减轻代码设计复杂度。

  index.wxml,这就是常见的模板文件,数据驱动,有过前端mvc、mvvm项目开发的对这个一定不会陌生,毕竟这是基于react开发的。  

<!--index.wxml-->
<view class="container">
<!--视图容器-->
<view  bindtap="bindViewTap" class="userinfo">
<!--bindtap为容器绑定点击触摸事件,在触摸离开时触发bindViewTap事件处理函数,bindViewTap通过index.js page()设置添加-->
<image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
<!--大双括号的变量来自于index.js的data对象解析成对应的值,而且是实时的-->
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>


index.js,与reaact用法几无二异,换汤不换药。page()来注册一个页面。接受一个 OBJECT 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。

var app = getApp() // 获取入口文件app的应用实例
Page({
data: {
motto: 'Hello World',
userInfo: {}
},
//自定义事件处理函数,点击.userinfo的容易触发此函数
bindViewTap: function() {
wx.navigateTo({//全局对象wx的跳转页面方法
url: '../logs/logs'
})
},
onLoad: function () {//发生页面加载时,自动触发该生命周期函数
console.log('onLoad')
var that = this
//调用应用实例的方法获取全局数据
app.getUserInfo(function(userInfo){
//更新数据,页面自动渲染
that.setData({
userInfo:userInfo
})
})
}
})


index.wxss文件只渲染当前所属页面,会覆盖全局app.wxss同一样式。

再分析下logs日志文件夹,logs文件夹下为logs.wxml、logs.js、logs.wxss、logs.json,同理保证同名,才能完成效果渲染。

logs.wxml文件

<!--logs.wxml-->
<view class="container log-list">
<block wx:for="{{logs}}" wx:for-item="log">
<!--//block容器作用,无其他实际含义。wx:for作用:遍历logs数组,遍历多少次,block块就会复制多少次,for-item等同于为<br>遍历元素起一个变量名,方便引用。</br>-->
<text class="log-item">{{index + 1}}. {{log}}</text>
</block>
</view>


logs.js 文件

//logs.js
var util = require('../../utils/util.js') //util.js相当于一个函数库,我们可以在这个文件内自定义扩展和封装一些常用的函数和方法
Page({
data: {
logs: []
},
onLoad: function () {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(function (log) {//通过wx.getStorageSync获取本地缓存的logs日志数据
return util.formatTime(new Date(log))//日期格式化
})
})
}
})


logs.json文件

{
"navigationBarTitleText": "查看启动日志"
<!--当前页面配置文件,设置window当前页面顶部导航栏标题等相关内容-->
}


官方API https://mp.weixin.qq.com/debug/wxadoc/dev/api/

文件流原贴 http://www.cnblogs.com/dupd/p/5905880.html ,有一定的修改

以上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: