我们在开始微信小程序开发的时候,对JS,HTML等前端知识一无所知,完完全全就是门外汉在尝试一个新的方向。

在下载好开发工具,微信就已经提供了一个DEMO例子:

从程序开发的角度来看这个陌生的目录结构,pages是存放页面的,utils是存放工具类的,而app开头的三个文件既然放在根目录级别,那么按理讲,应该是和配置有关。

我们看app.js文件的内容:

//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函数用于注册一个小程序,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: {
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 = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate() var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds() 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
} module.exports = {
formatTime: formatTime
}

这里的内容很简单,就是对log的日期进行格式化,不过我们注意到最后的内容,module.exports执行了赋值操作。

这个其实是和require搭配的,require返回的就是这个module.exports,然后定义了一个formatTime对象,也就是可以调用的对象,而这个对象就是formatTime函数。

通过require和module.exports来确定了这个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
//调用应用实例的方法获取全局数据
app.getUserInfo(function(userInfo){
//更新数据
that.setData({
userInfo:userInfo
})
})
}
})

我们通过getApp函数来获取小程序实例,因为我们需要调用app.js中的函数,这里调用的是getUserInfo,可以理解为app.js中定义的方法都是公共方法,因为这里并没有require和module.exports的调用。

这里有一个新的知识点: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,我们大概了解到小程序的目录结构,和一些相关的基础知识,后面会在具体的开发工作中继续补充相关的知识。

微信小程序官方DEMO解读的更多相关文章

  1. 微信小程序官方demo学习

    最近微信小程序很火,很喜欢那种轻应用,用完就走的理念.于是,下载好微信开发者工具,学习一下官方demo. 体验下来,有类似react和vue的感觉,dom类似react那种组件的,data-bindi ...

  2. 03——微信小程序官方demo讲解——page部分

    一个page由一个文件夹以及文件夹下四个文件组成. 比如一个页面叫index.则需要在pages目录下新建一个index目录,且包含由index+类型(js\wxml\wxss\json)为名组成的若 ...

  3. 02——微信小程序官方demo讲解——app部分

    第一节讲了目录结构,这节主要讲解下目录中app.js部分. 它由三部分组成app.js.app.json与app.wxss 1.JS部分 1.1概述 //app.js App({ onLaunch: ...

  4. 01——微信小程序官方demo讲解——文件结构

    1.环境概览 首先环境配置的部分略过,打开小程序开发工具.选择一个空目录,即可开始一个demo项目. 其中新建成功后的目录如图所示: 2.文件结构描述 如图所示,左边是界面展示,右边是目录结构. 目录 ...

  5. 【福利】微信小程序精选Demo合集

    小编最近在开发小程序,也读到了不少优秀的小程序源码,项目中有些需求可以直接从源码里粘贴复制过来,虽然这样做不利于自己独立编写代码,但比较是给公司做项目啊,秉着效率第一的原则,简直没有什么比ctrl+c ...

  6. 微信小程序开源Demo精选

    来自:http://www.jianshu.com/p/0ecf5aba79e1 文/weapphome(简书作者)原文链接:http://www.jianshu.com/p/0ecf5aba79e1 ...

  7. Mac上微信小程序官方开发工具卡死的问题

    Mac上微信小程序官方开发工具打开后卡死,无法操作,也关不掉,解决方案: 三步: 1.在应用中删除“微信web开发者工具” 2.删除一下几个配置和缓存文件: 1.-/Library/Applicati ...

  8. weapp微信小程序初探demo

    https://github.com/donglegend/weapp-demo 参考文档开发工具安装微信weapp API git项目源码微信小程序 demo效果展示效果预览

  9. 微信小程序(组件demo)以及预览方法:(小程序交流群:604788754)

    1. 获取微信小程序的 AppID 登录 https://mp.weixin.qq.com ,就可以在网站的"设置"-"开发者设置"中,查看到微信小程序的 Ap ...

随机推荐

  1. solr6.5.0(windows)教程

    第一步:安装Tomcat8重命名结尾加上solr6(自定义) 第二步: 解压solr,把solr-6.5.0\solr-6.5.0\server\solr-webapp下的webapp文件夹拷贝到to ...

  2. anaconda源配置

    1. 生成配置文件 第一次运行 conda config命令时,将会在用户的home目录创建该文件..condarc配置文件,是一种可选的(optional)运行期配置文件,其默认情况下是不存在的. ...

  3. linux学习笔记 ftp命令

    ftp server with sites et up for downloaing files sometimes provides an anonymous ftp account 数据传输 ft ...

  4. XamarinSQLite教程在Xamarin.Android项目中提取数据库文件

    XamarinSQLite教程在Xamarin.Android项目中提取数据库文件 由于不能直接打开该文件,开发者需要先将数据库文件从Android系统中提取出来.操作步骤如下. (5)选择MyDoc ...

  5. Bluestein's Algorithm

    网上很少有人提到,写的也很简单,事实上就是很简单... \(Bluestein's\ Algorithm\),用以解决任意长度\(DFT\). 考虑\(DFT\)的形式:\[\begin{aligne ...

  6. Codeforces.209C.Trails and Glades(构造 欧拉回路)

    题目链接 \(Description\) 给定一张\(n\)个点\(m\)条边的无向图,允许有自环重边.求最少加多少条边后,其存在从\(1\)出发最后回到\(1\)的欧拉回路. 注意,欧拉回路是指要经 ...

  7. Java笔记(十六)并发容器

    并发容器 一.写时复制的List和Set CopyOnWrite即写时复制,或称写时拷贝,是解决并发问题的一种重要思路. 一)CopyOnWriteArrayList 该类实现了List接口,它的用法 ...

  8. LeetCode(976. 三角形的最大周长)

    问题描述 给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的.面积不为零的三角形的最大周长. 如果不能形成任何面积不为零的三角形,返回 0. 示例 1: 输入:[2,1,2] 输出:5 ...

  9. quepy

    A python framework to transform natural language questions to queries in a database query language. ...

  10. elastic-job详解(四):失效转移

    elastic-job中最关键的特性之一就是失效转移.配置了失效转移之后,如果在任务执行过程中有一个执行实例挂了,那么之前被分配到这个实例的任务(或者分片)会在下次任务执行之前被重新分配到其他正常节点 ...