⼩程序官⽅DEMO解读
我们在开始⼩程序开发的时候,对JS,HTML等前端知识⼀⽆所知,完完全全就是门外汉在尝试⼀个新的⽅向。
在下载好开发⼯具,就已经提供了⼀个DEMO例⼦:
从程序开发的⾓度来看这个陌⽣的⽬录结构,pages是存放页⾯的,utils是存放⼯具类的,⽽app开头的三个⽂件既然放在根⽬录级别,那么按理讲,应该是和配置有关。
我们看app.js⽂件的内容:
//app.js
App({
onLaunch: function () {
//调⽤API从本地缓存中获取数据
var logs = wx.getStorageSync('logs') || []
logs.w())
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 () {
success: function (res) {
that.globalData.userInfo = res.userInfo
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
})
}
},
globalData:{
userInfo:null
}
})
根据官⽅⽂档的说明,这个⽂件⽤于编写⼩程序的页⾯逻辑。
App函数⽤于注册⼀个⼩程序,onLanuch⽤于处理⼩程序的初始化,当⼩程序初始化完成的时候会调⽤⼀次。
onLanuch这⾥的处理是取出wx中的log,然后再把当前⽇期添加进去。
wx是⼀个命名空间,相当于⼀个库,它有很多公共⽅法。
我们这⾥的操作和Android中使⽤SP(SharePreferences)是差不多的,wx有个本地缓存,这个缓存可以根据相关的key值取出对应的内容。这⾥有个有趣的语法:|| [],在javascript中,表⽰如果这个变量如果是undefined,null,NAN,false,0中的任意⼀种,就设置为⼀个空的数组,可以理解为?:的⽤法。然后调⽤javascript的unshift⽅法,把当前⽇期插⼊数组的第⼀个元素。
getUserInfo是⾃定义的函数,传⼊⼀个函数作为参数,⽽且这⾥还定义了全局对象globalData,它有⼀个字段userInfo,初始值为null,通过判断userInfo是否为空,⾮空则在cb为函数类型的情况下调⽤cb,空的情况下,则通过调⽤wx.login⽅法,在success的情况下调⽤wx的getUserInfo获取userInfo。
这个js⽂件已经⼤概的展⽰了javascript的很多基本语法,因为javascript是动态语⾔,它是⾯向函数语⾔,因此和java这种⾯向对象语⾔在语义实现上,差别相当⼤,我们可以简单的理解为java操作的是对象,⽽javascript操作的是函数,⽽wx.login中的参数就是⼀个对象,因此⽤{}包起来,函数其实也是⼀
个对象,所以它后⾯同样也有{},这个对象就是loginObject,在它success的时候调⽤wx.getUserInfo函数。
⽆论是⾯向对象还是⾯向函数,本质上都是体现开发⼈员理解问题的思路,只是语义实现上不同⽽已,毕竟javascript和java要解决的问题所在的领域有着相当⼤的差异。
我们再看看app.json这个⽂件:
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
根据⽂档的解释,这个⽂件是对⼩程序进⾏全局配置,决定页⾯⽂件的路径、窗⼝表现、设置⽹络超时时间、设置多tab等。
pages⽤于设置页⾯的路径,是⼀个数组,我们这个DEMO的页⾯只有两个:index和logs,其中第⼀个元素,index,是⼩程序的第⼀个页⾯,每次新增或者删除某个页⾯,都要在这⾥进⾏修改。
window⽤来设置默认的窗⼝的属性,显然app.json是设置整个⼩程序窗⼝的默认属性,会被具体页⾯的相关属性覆盖。
最后是app.wxss:
/
**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⽂件,不过⾃⼰本⾝做了⼀些处理,这个⽂件的内容就是设置了container这个节点视图的公共属性。
从这三个根⽬录的⽂件,我们也⼤概知道⼀个⼩程序的页⾯的组成结构,但是还少了⼀个⽂件,那就是页⾯视图的⽂件。
DEMO的logs页⾯就包含了四个⽂件:.json,.js,.wxss和.wxml。
我们看⼀下logs.wxml这个⽂件:
<!--logs.wxml-->
<view class="container log-list">
<block wx:for="{{logs}}" wx:for-item="log" wx:key="*this">
<text class="log-item">{{index + 1}}. {{log}}</text>
</block>
</view>
<view/>表⽰⼀个视图的节点,相当于Android中的ViewGroup,然后通过class赋予这个view⼀个或多个类名,wxss就是通过这个class来控制对应视图的渲染效果,这⾥是两个类名:container和log-list,
⽬的就是在⼀些属性上覆盖.container的设置。
<block/>表⽰这是⼀个多节点的视图,也就是列表组件,通过wx:for表⽰这个列表组件的数组来源,在的设计中,{{}}表⽰数据绑定,这⾥绑定了logs这个数组作为数据来源。
wx:for-item指定了当前数组的元素名,我们可以理解为java中的增强for的⽤法:for(item : array)。
wx:key表⽰⼀个唯⼀标识,因为这个数组是动态数组,会不断增加⾃⼰本⾝的长度,⽽我们不希望已经创建好的元素在重新渲染的时候会被修改,因此通过wx:key指定*this,表⽰for循环中的item只是被重新排序,⽽不是被重新创建,这样是为了提⾼渲染的效率。
最后我们看⼀下<block/>⾥⾯的⼦视图,是⼀个text视图,渲染的内容是数组中的元素,默认数组的下标变量名是index,元素名称是item,因此{{index + 1}}表⽰取当前元素的下标,因为下标是从0开始,所以这⾥加1来和⼈类世界中下标从1开始的共识达成⼀致,⽽log就是logs中的元素的内容,因为我们已经通过wx:for-item指定了item的名称为log。
logs⽬录下的logs.js也是相当有意思的:
//logs.js
var util = require('../../utils/util.js')
Page({
data: {
javascript全局数组logs: []
},
onLoad: function () {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(function (log) {
return util.formatTime(new Date(log))
})
})
}
})
util.js是我们utils⽬录的⽂件,这⾥的"../../utils/util.js"是通过相对路径来导⼊这个js⽂件,按照我们的理解,相当于import⼀个库。
Page函数是⽤来注册⼀个页⾯,data声明页⾯的初始数据,这⾥是⼀个logs数组,⽽data⾥⾯的数据是通过json传递到页⾯,因此这⾥⾯的格式要确保完全符合json格式。然后调⽤onLoad函数,在加载页⾯的时候通过setData将逻辑层的数据传递到视图层,也就是所谓的数据绑定,并且改变this.data的内容。
setData中的函数通过调⽤数组的map函数,将数组的内容重新映射成新的内容,这⾥相当于初始化数组,map就是⽤来对数组内容进⾏赋值的。
我们看⼀下util.js的内容:
function formatTime(date) {
var year = FullYear()
var month = Month() + 1
var day = Date()
var hour = Hours()
var minute = Minutes()
var second = Seconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
formatTime: formatTime
}
这⾥的内容很简单,就是对log的⽇期进⾏格式化,不过我们注意到最后的内容,ports执⾏了赋值操作。
这个其实是和require搭配的,require返回的就是这个ports,然后定义了⼀个formatTime对象,也就是可以调⽤的对象,⽽这个对象就是formatTime函数。
通过require和ports来确定了这个js⽂件暴露出来的API。
我们现在来关注⼀个很重要的语法:=和:这两个操作符到底是怎么⽤的。
=就是赋值操作符,这个⽏庸置疑,⽽:其实也是赋值操作,对于a:function,其实表⽰key值为a的value的内容为function,所以formatTime:formatTime就是表⽰util.formatTime这个属性对应的是formatTime函数。
我们再来看⼀下index⽬录下的⽂件。
先看⼀下index.js:
//index.js
//获取应⽤实例
var app = getApp()
Page({
data: {
motto: 'Hell World',
userInfo: {}
},
//事件处理函数
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
console.log('onLoad')
var that = this
//调⽤应⽤实例的⽅法获取全局数据
//更新数据
that.setData({
userInfo:userInfo
})
})
}
})
我们通过getApp函数来获取⼩程序实例,因为我们需要调⽤app.js中的函数,这⾥调⽤的是getUserInfo,可以理解为app.js中定义的⽅法都是公共⽅法,因为这⾥并没有require和ports的调⽤。
这⾥有⼀个新的知识点:bindViewTap。
这个是⼀个事件处理函数,事件是逻辑层到视图层的通讯⽅式,将⽤户的⾏为反馈到逻辑层进⾏处理,bindViewTap这个事件函数是⽤户在点击时候触发的,相当于onClick,wx.navigateTo表⽰跳转到url指定的页⾯。
我们看⼀下inde.wxml⽂件就知道了:
<!--index.wxml-->
<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>
要通过bindtap指定点击事件函数。
事件分为两种:冒泡事件和⾮冒泡事件,冒泡事件会把事件往上传递,⽽⾮冒泡则反之。冒泡事件前
缀是bind,⽽⾮冒泡事件是catch。通过对这个DEMO,我们⼤概了解到⼩程序的⽬录结构,和⼀些相关的基础知识,后⾯会在具体的开发⼯作中继续补充相关的知识。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论