小程序

框架

什么是框架?

​ 框架就是开发作者(个人或团队)约定好的一种规则,如果要使用框架做开发,遵循框架约定好的规则或方式去组建文件和书写业务逻辑代码

​ 框架的主要作用:就是具备有基础的结构,便于他人在这个框架的基础之上进行快速开发,解放开发者的双手,无需从0开始

小程序框架

​ 整个小程序框架系统分为两部分:逻辑层(App Service)视图层(View)。 ​ 小程序提供了自己的视图层描述语言WXMLWXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

  • 响应的数据绑定 框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当数据做修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。 示例:
  • 页面管理 框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的 生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。

  • 基础组件 框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。

    <navigator></navigator>
    <map></map>
    <button></button>
    ......
    
  • 丰富的 API 框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

场景值

场景值用来描述用户进入小程序的路径。完整场景值的含义请查看场景值列表

由于Android系统限制,目前还无法获取到按 Home 键退出到桌面,然后从桌面再次进小程序的场景值,对于这种情况,会保留上一次的场景值。

获取场景值

​ 开发者可以通过下列方式获取场景值,可以在 ApponLaunchonShowwx.getLaunchOptionsSync 中获取上述场景值。 ​ 部分场景值下还可以获取来源应用、公众号或小程序的appId。获取方式请参考对应API的参考文档。

逻辑层(App Service)

​ 小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发者 JavaScript 代码的运行环境以及微信小程序的特有功能。

​ 逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

​ 开发者写的所有代码最终将会打包成一份 JavaScript文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似ServiceWorker,所以逻辑层也称之为App Service

​ 在 JavaScript 的基础上,我们增加了一些功能,以方便小程序的开发:

  • 增加 App 和 Page 方法,进行程序注册和页面注册。
  • 增加 getApp 和 getCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 提供模块化能力,每个页面有独立的作用域。

注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等。

生命周期

  • 什么是生命周期?
         所谓的生命周期就是将一个过程划分成很多个阶段,然后在某一个阶段完成过后自动的发送一个信号,通知一下程序当前执行到哪个位置。
    
  • 小程序的生命周期有两种
    1. 小程序生命周期(它只会创建一次,除非小程序被销毁了)
    2. 页面的生命周期

      注册小程序

      每个小程序都需要在 app.js 中调用 App 方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。 详细的参数含义和使用请参考 App 参考文档
// app.js
App({
  onLaunch(options) {
    // Do something initial when launch.
  },
  onShow(options) {
    // Do something when show.
  },
  onHide() {
    // Do something when hide.
  },
  onError(msg) {
    console.log(msg)
  },
  globalData: 'I am global data'
})

整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 实例,获取App上的数据或调用开发者注册在 App 上的函数

// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data

注册页面

对于小程序中的每个页面,都需要在页面对应的 js 文件中调用 Page 方法注册页面示例,指定页面的初始数据、生命周期回调、事件处理函数等。

详细的参数含义和使用请参考 Page 参考文档

// index.js
Page({
  data: {
    text: 'This is page data.'
  },
  onLoad(options) {
    // Do some initialize when page load.
  },
  onReady() {
    // Do something when page ready.
  },
  onShow() {
    // Do something when page show.
  },
  onHide() {
    // Do something when page hide.
  },
  onUnload() {
    // Do something when page close.
  },
  onPullDownRefresh() {
    // Do something when pull down.
  },
  onReachBottom() {
    // Do something when page reach bottom.
  },
  onShareAppMessage() {
    // return custom share data when user share.
  },
  onPageScroll() {
    // Do something when page scroll
  },
  onResize() {
    // Do something when page resize
  },
  onTabItemTap(item) {
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  // Event handler.
  viewTap() {
    this.setData({
      text: 'Set some data for updating view.'
    }, function () {
      // this is setData callback
    })
  },
  customData: {
    hi: 'MINA'
  }
})

视图层(View)

  • 框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。

  • 将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。

  • WXML(WeiXin Markup language) 用于描述页面的结构。

  • WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

  • WXSS(WeiXin Style Sheet) 用于描述页面的样式。

  • 组件(Component)是视图的基本组成单元。

#####

小程序语法

WXML语法

WXML(WeiXin Markup Language)是框架设计的一套标签语言,用来描述小程序页面的结构。

简单绑定

数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于组件中

内容

<!--page.wxml-->
<view>{{ message }}</view>
// page.js
Page({
  data: {
    message: 'Hello MINA!'
  }
})

关键字(需要在双引号之内)

true:boolean 类型的 true,代表真值。 false: boolean 类型的 false,代表假值。

<checkbox checked="{{false}}"></checkbox>

特别注意:不要直接写 checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。

运算

可以在 {{}} 内进行简单的运算,支持的有如下几种方式:

三元运算
<view hidden="{{flag ? true : false}}">Hidden</view>
// page.js
Page({
  data: {
    flag: true
  }
})
算数运算
<view>{{num1 + num2}} + {{num3}} + d</view>
// page.js
Page({
  data: {
    num1: 12,
    num2:18,
    num3:10
  }
})

输出内容:

3 + 3 + d

列表渲染(https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/list.html)

wx:for 在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: [{
      id: '1',
      name:"张三",
    }, {
      id: '2',
      name:"李四",
    }]
  }
})

可以使用 wx:for-item 可以指定数组当前元素的变量名

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

可以使用 wx:for-index 可以指定数组当前下标的变量名:

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

block wx:for 类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:

<block wx:for="{{[1, 2, 3]}}">
  <view>{{index}}:</view>
  <view>{{item}}</view>
</block>

注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

条件渲染(https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/conditional.html)

wx:if 在框架中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块:

<view wx:if="{{condition}}">True</view>

也可以用 wx:elif 和 wx:else 来添加一个 else 块:

<view wx:if="{{length > 5}}">1</view>
<view wx:elif="{{length > 2}}">2</view>
<view wx:else>3</view>

block wx:if 因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

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

wxss使用

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。 WXSS 用来决定 WXML 的组件应该怎么显示。 为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。 与 CSS 相比,WXSS 扩展的特性有:

  • 尺寸单位
  • 样式导入

尺寸单位

​ rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

84969b1586007a386111cd28df8d32a9.png

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。 ps: 为什么是以iPhone6 作为一个屏幕参考机型呢?因为小程序出现前的年代,很多UI设计师都是参考当时流行的机型来进行定义设计稿的尺寸宽度

注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

示例:

样式导入

使用 @import 语句可以导入外联样式表,@import 后跟需要导入的外联样式表的相对路径,用 ; 表示语句结束。

/** app.wxss **/
@import "common.wxss";
.middle-p {
  padding:15px;
}

内联样式

组件上支持使用 style、class 属性来控制组件的样式。

  • style:静态的样式统一写到 class 中。
<view style="color:{{color}};" />

style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。

  • class:用于指定样式规则,使用方式与Web端的 css 效果一样
<view class="normal_view" />

选择器

小程序中的 wxss 支持的样式选择器有如下: 5aa29c613276464d717e6d6163e0bb3f.png

全局样式与局部样式

​ 定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

事件

什么是事件

  • 事件是视图层(wxml)到逻辑层(js)的通讯方式。
  • 事件可以将用户的行为反馈到逻辑层进行处理。
  • 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
  • 事件对象可以携带额外信息,如 id, dataset, touches。

事件的使用方式

  • 在组件中绑定一个事件处理函数。 ​ 如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
<view id="tapTest" data-hi="WeChat" bindtap="tapName">Click me!</view>
  • 在相应的Page定义中写上相应的事件处理函数,参数是event
Page({
  tapName(event) {
    console.log(event)
  }
})

事件分类

事件分为冒泡事件和非冒泡事件:

  1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
  2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

事件冒泡列表: 2fc0b09e3a90e8d1e98dd412e5993184.png

注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如

的submit事件,的input事件,的scroll事件,(详见各个组件)

事件绑定和冒泡

事件绑定的写法同组件的属性,以 key、value 的形式。

  • key 以 bindcatch 开头,然后跟上事件的类型,如bindtap、catchtouchstart。自基础库版本 1.5.0 起,在非原生组件中,bind和catch后可以紧跟一个冒号,其含义不变,如bind:tap、catch:touchstart。
  • value 是一个字符串,需要在对应的 Page 中定义同名的函数。不然当触发事件的时候会报错。

bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。 例如:

<!-- 如下是通过 bind 绑定事件行为,有冒泡行为 -->
 <view bindtap="fatherEvent">
                fatherView
                <view bindtap="sayHello" data-id="12" data-name="张三"
                data-desc-intor="helloWorld"
                >点我
                </view>
</view>
<!-- catch绑定的事件行为,只会在当前组件中产生行为,不会有冒泡行为 -->
<view bindtap="fatherEvent">
                fatherView
                <view catchtap ="sayHello" data-id="12" data-name="张三"
                data-desc-intor="helloWorld"
                >点我
                </view>
</view>

事件对象

  • 如无特殊说明,当组件触发事件时,逻辑层(.js)绑定该事件的处理函数的形参中会收到一个事件对象。

事件属性对象说明

a3ed787f296eb3be1a78eaec75d398a9.png

target 事件产生的类型

timeStamp 页面打开到触发事件所经过的毫秒数

target 触发事件源组件

f3182204f2cbd1ee4e166b9ec123e474.png

currentTarget 事件绑定的当前组件。

2b868d15a53592b63011a7458f7ed1ba.png

target 和 currentTarget 如何区分?可以使用事件冒泡来区别

dataset

​ 在组件中可以定义数据,这些数据将会通过事件传递给注册绑定事件函数中,在组件中的书写方式: 以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写),如data-element-type, 最终在 event.currentTarget.dataset 中会将连字符转成驼峰 elementType。

例如:

汽车品牌列表(案例)

8492887a8a22a1d9613fd716e5a89d03.png

require()使用

  • require(string path)

736de39e82e7cf09e101708e37cd2ee8.png

引入模块。返回模块通过 module.exportsexports 暴露的接口。

// 准备数据
var carList = [

        { path: "/img/car/298.jpg", name: "宇通客车" },
        { path: "/img/car/93.jpg", name: "永源" },
        { path: "/img/car/232.jpg", name: "御捷" },
        { path: "/img/car/94.jpg", name: "众泰" },
        { path: "/img/car/22.jpg", name: "中华" },
        { path: "/img/car/74.jpg", name: "中兴" },
        { path: "/img/car/182.jpg", name: "之诺" },
        { path: "/img/car/206.jpg", name: "知豆" }
];

// 通过 module.exports 导出数据即可
module.exports.brandList = carList
// 通过 require() 方法导入 模块,只支持 相对当前项目的相对路径
var  brandList= require("../../data/cardata.js");
console.log(brandList)

page的setData使用

页面的逻辑层中,可以使用 this.setData() 方法,动态的为 当前页面的初识数据对象data 属性 进行参数赋值

        /**
         * 页面的初始数据
         */
        data: {
                msg:"Hello World"
        },

        /**
         * 生命周期函数--监听页面加载
         */
        onLoad: function (options) {
                     var that=this;
                    // 三秒过后变成中文的你好
                    setTimeout(function(){
                            that.setData({ msg: "你好" })
                    },3000)
              }
        },
    <view>{{msg}}</view> <!--输出你好-->
htmlcss笔记
JSRUN前端笔记, 是针对前端工程师开放的一个笔记分享平台,是前端工程师记录重点、分享经验的一个笔记本。JSRUN前端采用的 MarkDown 语法 (极客专用语法), 这里属于IT工程师。