曾经,我非常羡慕那些人见人爱的人,我也想要变成那样,可是后来我才明白人见人爱也是需要天赋的,后来我开始默默努力,我想,就算我不能让每个人都喜欢我,至少因为我做的努力能得到别人的尊重。

微信小程序开发

微信小程序开发

  • 开发环境搭建
  • 应用架构解析
  • 逻辑层
    • 注册程序
    • 注册页面
    • 模块化
    • API
  • 视图层
    • 数据绑定
    • 条件渲染和列表渲染
    • 模块
    • 事件
    • 引用
    • WXSS
    • 组件

  之前觉得微信小程序已经不行了,似乎没有任何生机,很多人可能都不知道有小程序这回事吧,但是最近在做vue的项目,发现美团和饿了么的微信公众号都连接到了小程序,主要特点就是非常像原生app,可以发送到桌面,使用感受就如同原生app,感觉还是很舒服的,所以觉得有必要尝试一下微信小程序的开发。。。嗯,现在已经是凌晨3点了,小程序啊。 

  根据上述的目录,我们主要讨论一下开发环境的搭建、应用架构、逻辑层、视图层。 

 

一、开发环境搭建

  官网有工具的下载地址,我们直接点击下载即可,目前的最新版本是2017年5月26日更新的。 看来腾讯还是不会轻易放弃小程序的。 当然我们需要提前注册一下微信小程序的appid,然后登陆即可, 值得注意的是,如果我们使用的是教老版本的微信开发者工具,并且你已经绑定了微信公众号,那么就不能进入到小程序开发的界面。 进入之后,我们就可新建一个项目,使用微信小程序的快速启动工具构建一个具有基本架构的项目,就类似于vue的vue-cli一样。

  我们进入之后,可以看到基本的框架如下所示:

  通过这些文件,就生成了基本的小程序实例。  

   点击编辑即可进入编辑代码的界面,编辑完之后,我们可以通过点击左下角的编译按钮来编译,这样就可以看到修改代码之后的效果了!

 

二、 应用架构解析

  我们看看最简单的小程序的目录结构:

  • pages
    • index
      • index.js
      • index.wxml
      • index.wxss
    • logs
      • logs.js
      • logs.json
      • logs.wxml
      • logs.wxss
  • utils
    • util.js
  • app.js
  • app.json
  • app.wxss

  首先比较突出的就是 wxss 和 wxml了, 其实就相当于css和html, 另外还有json的使用,主要是来配置小程序的,如颜色等。 毫无疑问app.js就是入口文件了。  不难看出 pages 就表示多个页面了。  还有一个公用的工具函数 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
}

这段代码也非常简单,就是把当前的时间用某种形式标准化。 

  每一个小程序页面都是由相同路径下同名的四个同名、不同后缀的文件所组成的。如这里的 index.wxml、index.wxss、index.js、index.json。 

  那么我们知道wxml是页面结构、wxss是页面的样式、js是逻辑代码、json这个配置文件呢? 实际上json文件也是样式的配置,只是控制的属于app的,不是页面的,如最上面的导航条等等。  并且如果我们在一个页面的json文件中如果设置了和app.json文件中相同的内容,那么就会覆盖掉app.json中相同的配置样式。 

  注意: json文件同js文件是完全不同的,json是一种非常严格的文件格式。 

  其中的index页即主页,log页即日志页。如下是默认的主页:

  下面是默认的日志页:

  

  这是我对小程序启动的一些基本的记录。 

  如果我们把log.json文件中添加下面的内容(原来是没有内容的,使用的设置都是app.json文件中的设置): 

{
  "backgroundTextStyle": "blue", 
  "navigationBarBackgroundColor": "blue",
  "navigationBarTextStyle": "blue",
  "navigationBarTitleText": "查看启动日志"
}

  那么日志页就是这样的:

 

  我们注意看一下 app.json中的内容:

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

  可以看到必须要在app.json中说明这个项目一共包含哪些页面,并且通过window的设置来告诉我们这是全局的。 注意:在index.json和log.json中最好不要使用这种全局的配置或压根就不要使用。

 

 

 

 

  我们先说说单个页面吧。 微信小程序要求页面文件名和目录的名称必须一致。比如这里的logs目录对应的一堆logs开头的文件,所以这样我们在使用的时候就不需要在js中import了。

  下面是js文件和模板文件:

//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
      })
    })
  }
})

 这个js也比较容易看,就是在点击之后进入log页面,在load(生命周期的钩子函数)后开始使用app这个全局实例的getUserInfo全局方法来获取到本地的userInfo, 并使用setData来修改data里的内容,这里也用了var that = this的形式,因为this指向的时app。 

<!--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>

其中 bindViewTap就是绑定一个tap事件,当我们点击进入的时候就可以引导到: 

wx.navigateTo({
url: '../logs/logs'
})

所以就进入了 logs 页面。 

其中的 Page 是框架提供的全局方法。 和vue类似的mvvm框架一样,采用了数据绑定、事件绑定、生命周期、路由这些。  下面是一个logs.json文件:

{
    "navigationBarTitleText": "查看启动日志"
}

即json文件就是做一些基础的配置的。 因为小程序毕竟还是运行在微信上的, 所以这些配置文件log就是改一下标题栏颜色、文字之类的东西。   

 

而通过getApp()我们可以得到app实例,这个实例中包含了一些全局的方法。 

 

嗯,这个hello world级别的就是这么简单。

 

三、逻辑层

  微信小程序的逻辑层就下面这些:

  • 注册程序
  • 注册页面
  • 模块化
  • API

 1. 注册程序

  注册程序是提供给我们的,是一个全局的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
  }
})

  这里的onLaunch是一个生命周期的钩子,然后getUserInfo相当于一个全局的方法(使用getApp()获取实例以后就可以调用,在Index.js里的), 而globalData作为app的属性自然就担任了全局变量这个角色了, 然后还使用了本地存储的api,来提高用户体验。

 

  

2. 注册页面  

  Page方法就是用于注册页面的,页面也会有一些生命周期的钩子等。 另外,Page还有一个事件: 即onPullDownRefresh,即页面下拉刷新。 

    
<view bindtap="viewTap"> click me </view>

 

Page({
  viewTap: function() {
    console.log('view tap')
  }
})

  除了使用bind + event作为属性名还可以使用catch + event, 区别在于后者可以继续阻止冒泡。 事件绑定函数同样还有一个参数event, 但是event包含了该节点的星星所以很快就可以完成逻辑定制。 

 

 

3. 模块化

  目前的小程序并不支持node_modules的导入, 所以要用就可能复制过去,另外和webpack的模块化是类似的, 即小程序各个page的作用域是独立的,如果要对外暴露接口的话需要使用模块导出。

 

// common.js
function sayHello(name) {
  console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
  console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
// module.exports = { sayHello: sayHello }

 

这里要说的是: 微信小程序是完全支持es6语法的,不用担心兼容性的问题啦!  

 

 

4. API

  小程序的API都通过wx这一个全局对象来访问的, 和运行在浏览器的JavaScript类似,wx也提供了如http请求、本地存储、绘图这一类的api, 除此之外,还有一些更为本地化的api,比如拨打电话、重力感应、交互反馈、支付这样的api。 可以查询小程序api。其实真的是非常方便的。

 

 

 

四、视图层  

  微信小程序也是自制了一套标签,成为WXML(weixin Markup Language), 同样也是基于组件的。 与之配合的样式表称为 WXSS (weixin Style Sheet)。 

 

1. 数据绑定

  数据绑定采用Mustache语法,也就是双大括号。值的注意的是大括号里支持一些ES6的表达式,比如说展开语法和简化的对象属性写法

    
<template is="objectCombine" data="{{...obj1, ...obj2, e}}"></template>
Page({
  data: {
    obj1: {
      a: 1,
      b: 2
    },
    obj2: {
      c: 3,
      d: 4
    },
    e: 5
  }
})

 

这样得到的结果就是: {a: 1, b: 2, c: 3, d: 4, e: 5}。  

 

2. 条件渲染和列表渲染

条件渲染和列表渲染很简单,就像vue.js里两个指令v-ifv-for,小程序里用的是wx:ifwx:for,用两个简单的DEMO过一下

<!-- 条件渲染 -->
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
<!-- 列表渲染 -->
<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>

 

 

3. 模板

  即我们需要定义一个模板来复用。

<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>
<template is="msgItem" data="{{...item}}"/>

 

 

4. 事件

  

前面简单提了一下事件的两种绑定方式,现在简单列一下wx支持的一些冒泡事件名称:

  • touchstart 手指触摸动作开始
  • touchmove 手指触摸后移动
  • touchcancel 手指触摸动作被打断,如来电提醒,弹窗
  • touchend 手指触摸动作结束
  • tap 手指触摸后马上离开
  • longtap 手指触摸后,超过350ms再离开

其余的事件都是不冒泡的,那些就因组件而异了,比如说<form />的submit等。然后之前也提过,事件参数就只有一个event,所以要传值的时候data-属性就显得很重要了,因为事件对象可以获取到一个dataset对象,对应都是就是各个自定义的data-属性。

 

 

5. 视图的引用

就像ejs里会有include一样,模板语言肯定是会有引用嵌套的功能的,wx里提供了两种方法,分别是importinclude,见DMEO

<!-- item.wxml -->
<template name="item">
  <text>{{text}}</text>
</template>
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>

 

 

也可以是include,

<!-- index.wxml -->
<include src="header.wxml"/>
<view> body </view>
<!-- header.wxml -->
<view> header </view>

 

 

6. wxss

    继承了css的大部分特性。 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

  

  

 

posted @ 2017-06-04 02:51  Wayne-Zhu  阅读(491)  评论(0编辑  收藏  举报

一分耕耘,一分收获。