微信小程序初探

文章目录:

-微信小程序公测啦!!!
-哦。

唉我这么激动周围的人毫无反应,真的是无趣啊。不管了,今天下午终于没课了,就放着要期末的积分变换不管来学这个吧。

本质上来说,我们还是构造了一个webapp,但是微信弃用了安卓卡卡的原生webview,用x5的内核来解析应用的Js(支持ES6哦��),也不知道性能会如何。大概分为下面这么几块来研究一下这个框架:

  • 开发环境搭建
  • 应用架构
  • 逻辑层
  • 视图层

一、开发环境搭建

开发环境搭建特别简单,直接下载开发IDE就行了,直接贴地址。。开发IDE下载

二、应用架构解析

我们从官方给出的Hello World开始讲起吧,首先让我们看看目录结构:

  • 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

首先可以看到有好几种没见过的后缀,类比过去的话wxml就是htmlwxss就是css,按照那样理解就行了(当然是精简修改破解版的)。然后还有一些json,这些是作为配置文件使用的,一会单独讲。项目整体的架构相当清晰简洁(毕竟是helloworld。。),一个应用入口文件app.js,然后多个页面index, logs,一个公用的工具函数存放处utils

我们从单个页面讲起。比如说Index页面,小程序要求页面文件名和目录名(页面名称)必须一致,所以也不需要在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
      })
    })
  }
})
<!--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>

其中Page是框架提供的全局方法,然后和一般的MVVM框架一样,采用了数据绑定,然后也有事件绑定、生命周期这些东西(而且生命周期和应用需求很一致,比如说应用后台,这点很赞),可以看到也有路由跳转(index貌似是默认打开的),视图更新。

下面看看json文件是干什么的,比如说logs.json

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

因为程序是运行在微信之上的,所以我们给的这些配置就是改一下标题栏颜色啊文字啊这些东西。然后还有一个复杂一些的app.json,这个就看文档配置就好了,要注册page之类的。架构大概就这个样子。

三、逻辑层

微信小程序的逻辑层内容相当的简洁,官方文档的TAB就这几个东西

  • 注册程序
  • 注册页面
  • 模块化
  • 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. 注册页面

然后是 注册页面。和全局的App方法对应也有一个Page方法用于页面的注册,页面也会有一些生命周期的事件,除此之外还有一个比较特殊的事件:页面下拉刷新 onPullDownRefresh。其他的就是自定义事件处理函数的注册了,见DEMO

<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的import食用口感更佳。

4. API

小程序的API都通过wx这一个全局对象来访问,和运行在浏览器的javascript类似,wx也提供了如HTTP请求,本地存储,绘图这一类的API,除此之外还有一些更为本地化的API,比如拨打电话、重力感应、交互反馈、支付这一类API,非常的方便,具体使用时请查阅小程序API

四、视图层

与React Native类似,微信小程序也自制了一套标签(不过要精简的多),称为WXML(WeiXin Markup language),也同样是基于组件的。与之配合的样式表称为WXSS(WeiXin Style Sheet)。

WXML作为模板语言,少不了数据绑定、条件渲染、列表渲染这些东西,和Vue.js很像,下面简单过一遍。

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>

注意一下列表渲染里面的关键字index和item,对应的是数组的下标和元素,如果想自定义关键字的话就这样

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>

还要提到一个block标签,在学RN的时候就觉得为了将几个部分组合起来要套一个View在外面很坑,这里就诞生了一个block标签实现这个需求

<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

提到列表渲染就要提到 key 这个东西,因为框架不知道列表元素变了以后是怎么变的,所以对于动态列表需要给列表元素一个独一无二的key,使用wx:key指令提供。指令值可以是一个字符串表示属性名(循环中的item的Property),也可以是关键字*this(如果item不是一个对象的话)。

<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
<button bindtap="switch"> Switch </button>
<button bindtap="addToFront"> Add to the front </button>

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
<button bindtap="addNumberToFront"> Add to the front </button>
Page({
  data: {
    objectArray: [
      {id: 5, unique: 'unique_5'},
      {id: 4, unique: 'unique_4'},
      {id: 3, unique: 'unique_3'},
      {id: 2, unique: 'unique_2'},
      {id: 1, unique: 'unique_1'},
      {id: 0, unique: 'unique_0'},
    ],
    numberArray: [1, 2, 3, 4]
  },
  switch: function(e) {
    const length = this.data.objectArray.length
    for (let i = 0; i < length; ++i) {
      const x = Math.floor(Math.random() * length)
      const y = Math.floor(Math.random() * length)
      const temp = this.data.objectArray[x]
      this.data.objectArray[x] = this.data.objectArray[y]
      this.data.objectArray[y] = temp
    }
    this.setData({
      objectArray: this.data.objectArray
    })
  },
  addToFront: function(e) {
    const length = this.data.objectArray.length
    this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
    this.setData({
      objectArray: this.data.objectArray
    })
  },
  addNumberToFront: function(e){
    this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
    this.setData({
      numberArray: this.data.numberArray
    })
  }
})
3. 模板

还是和RN一样,因为View这些标签语义化的限制及组件化的要求,我们很多时候我们会自己定义一个模板来复用,这个直接看DEMO就懂了

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

<template is="msgItem" data="{{...item}}"/>

注意模板作用域是独立的,只能使用data属性传入的数据。

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

WXSS继承了css的大部分特性,同时针对移动端做了一些拓展优化:

  • 尺寸单位
  • 样式导入

尺寸单位是最赞的特性了,WXSS新增了rpx这个单位及重制了rem这个单位。其中使用rpx时,默认按照屏幕宽度750px进行样式编写即可,页面会根据实际页面大小进行缩放。而rem则默认屏幕为20rem宽,同样会自动缩放。

样式导入和css中的写法一样(原理肯定不一样),使用@import ()来进行导入即可。

初次之外,内联样式支持动态更新(数据绑定),选择器目前的支持范围如下:

class .intro 选择所有拥有 class=”intro” 的组件

id #firstname 选择拥有 id=”firstname” 的组件

element view 选择所有 view 组件
element, element view checkbox 选择所有文档的 view 组件和所有的 checkbox 组件
::after view::after 在 view 组件后边插入内容
::before view::before 在 view 组件前边插入内容

值得注意的是,在wx中,选择器的优先级概念有差异,不同的page下面的wxss是独立的,只作用于相应页面不会相互覆盖,只有app下面的wxss才是通用的。

7. 组件

首先还是要吐槽一下,真的和RN很像。。。wx提供了一系列组件,具体的还是查询官方文档吧~贴地址微信小程序组件

嗯,真的就这么多,感觉这个框架设计的挺好用的。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值