在微信小程序浅析中讲到微信小程序原理以及怎么新建一个hello world 工程,还挖了坑。现在把坑填上,捋一捋小程序的代码结构。看一下截图:
看一下目录结构:
前面也说到,全局文件有且只有三个app.js、app.json、app.wxss。我们瞄一瞄里面的内容:
//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
}
})
可以看到,app.js里面有个app方法负责注册小程序,该方法接收一个object对象,该object对象包含小程序的全局数据、全局函数和生命周期函数等。比如globalData是全局数据,getUserInfo为全局函数、onLaunch是启动时调用的生命周期函数。值得注意的是小程序只能再里面注册,并且在其他地方不要调用生命周期函数,生命周期函数应由微信内部调用,我们只负责实现。
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
hello world 一共有两个页面,都在page项里都进行了配置,如果没有进行配置的话微信将无法加载页面,还有就是页面文件除了后缀名外都必须同名配置项及其属性有很多,详见框架->配置。
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
这个没什么好说的,主要负责全局样式。如果页面的子样式有属性和全局属性重合,子样式会覆盖全局样式。其实这些跟css差不多,wxss是weixin style sheets的缩写,但是它不支持css级联选择器,并且为了适配,引入了rpx作为单位,详见框架->WXSS
页面文件除了包含js、json、wxss外,还多了一个wxml文件。前面三个和全局配置的功能几乎是一样的,只不过作用域是在页面而不是全局,那我们看看wxml是个什么鬼。这里以index页面为例:
<view class="container">
<view bindtap="bindViewTap" class="userinfo">
<image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover">image>
<text class="userinfo-nickname">{{userInfo.nickName}}text>
view>
<view class="usermotto">
<text class="user-motto">{{motto}}text>
view>
view>
结合预览视图,可以看到,这是一个类似xml格式的页面描述文件—-wxml(WeiXin Markup Language 微信标记语言),为了后续的介绍,把剩下的两个文件也贴出来:
//index.js
//获取应用实例
var app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {}
},
//事件处理函数
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
console.log('onLoad')
var that = this
//调用应用实例的方法获取全局数据
app.getUserInfo(function(userInfo){
//更新数据
that.setData({
userInfo:userInfo
})
})
}
})
/**index.wxss**/
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
}
.usermotto {
margin-top: 200px;
}
仔细观察上面三个文件,可以看到,wxml页面的样式是通过wxss控制的,类似于html与css。没有什么好说的,我们关键看看页面文件数据是如何和脚本交互的。
在wxml中:
<text class="userinfo-nickname">{{userInfo.nickName}}text>
<text class="user-motto">{{motto}}text>
在js中:
data: {
motto: 'Hello World',
userInfo: {}
}
也就是说页面中的内容是通过{{content}}与js中data属性中的content相对应。我们看看具体是怎么更改的:
在页面的onLoad方法中,调用app全局对象的getUserInfo方法,并传递一个函数进去:
onLoad: function () {
console.log('onLoad')
var that = this
//调用应用实例的方法获取全局数据
app.getUserInfo(function(userInfo){
//更新数据
that.setData({
userInfo:userInfo
})
})
}
而在app的getUserInfo方法中:
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)
}
})
}
})
}
}
这里为什么在登录收到用户数据的时候使用setData方法设置而不是直接改变data属性的值呢?因为框架–>注册页面中规定了只有通过setData才能改变this.data的值,并且页面也会更新,直接改变data的值会造成数据的混乱。
总的来说,微信小程序和web前端开发原理差不多。逻辑层由js控制,视图层由wxml和wxss进行描述和渲染。获取更详细的框架信息,请点击框架;获取视图组件,请点击组件;获取微信提供的js接口,请点击 API
写了一个多小时,有点小累,发现写得也蛮长了,继续挖坑,下一篇再依葫芦画瓢写DEMO。