微信小程序系列--【VXML语法、VMSS样式、条件渲染、列表渲染、模板、引用、组件、事件系统】

一、小程序逻辑层

getCurrentPages

获取当前的页面栈,页面栈是一个数组,记录小城序走过那些页面,方便页面返回。

获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。

不要尝试修改页面栈,会导致路由以及页面状态错误。

不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成

小程序的生命周期

img

1.模块化

模块化的概述

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

模块化的好处

有利于提高开发效率。

有利于协作开发。

避免变量污染。

模块化的规范

ES6规范:

多用于前端

分别暴露
var name="zhangsan"

const say=()=>{

  console.log("swk")

}

export {

  name,

  say

}

使用

import {name,say} from "../../utils/tool"

console.log(name);

say()
默认暴露
var name="zhangsan"

const say=()=>{

  console.log("swk")

}

export default {

  name,

  say

}

使用

import Tool from "../../utils/tool"

console.log(Tool.name)

Tool.say()

commonJs规范:

多用于后端

暴露
var name="zhangsan"

const say=()=>{

  console.log("swk")

}



module.exports={

  name,

  say

}

使用

const Tool=require("../../utils/tool")

console.log(Tool.name)

Tool.say()

小程序既支持es6规范,也支持commonjs规范

二、视图层概述

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

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

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

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

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

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

三、WXML语法

1.wxml概述及作用

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件事件系统,可以构建出页面的结构。

2.数据绑定

数据绑定

<view>姓名:{{name}}</view>

<view>年龄:{{age}}</view>

{{arr[0]}}{{student.room}}

绑定属性

<view data-title="{{title}}">年龄:{{age}}</view>

关键字的处理

小程序的关键字有两个true和false,使用{{}}引起来

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

运算

算术运算

      • /%
<view data-title="{{title}}">年龄:{{age+1}}</view>

逻辑运算

<checkbox checked="{{age>3}}"></checkbox>

字符串运算

<view>姓名:{{name+"li"}}</view>

路径运算

<view>{{arr[1]}}</view>
<view>{{student.room}}</view>

三元运算符

<view style="background:{{age<18?'red':'blue'}}">ddd</view>

总结:小程序wxml中只要有js代码,就使用{{}}。wxml中渲染数据时不能使用函数(过滤器)

3.列表渲染wx:for

<view>--------------列表渲染--------</view>

<view wx:for="{{arr}}" wx:key="*this">

{{index}}----{{item}}

</view>



<view wx:for="{{arr}}" wx:for-index="k" wx:for-item="v" wx:key="*this">

{{k}}----{{v}}

</view>



<view wx:for="{{student}}" wx:key="*this">

{{index}}----{{item}}

</view>



<view wx:for="{{name}}" wx:key="*this">

{{index}}----{{item}}

</view>



<view wx:for="{{goods}}" wx:key="*this">

{{index}}----{{item.id}}----{{item.name}}

</view>

block是包裹元素

<block  wx:for="{{goods}}" wx:key="*this">
    <view>商品id:{{item.id}}</view>
    <view>商品name:{{item.name}}</view>
</block>

tips:不要在block上面添加属性,样式

wx:key

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。

wx:key 的值以两种形式提供

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

tips:遍历数组时不要在“ {{ 之间加空格,否则得不到想要的结果。

4.条件渲染

<view wx:if="{{age>=18}}">成年</view>


<view wx:if="{{age>=18}}">成年</view>
<view wx:else>未成年</view>



<view wx:if="{{age<18}}">未成年</view>
<view wx:elif="{{age<=45}}">壮年</view>
<view wx:else="{{age<=45}}">老年</view>

hidden属性

<view hidden="{{true}}">hello</view>

wx:if vs hidden

因为 `wx:if` 之中的模板也可能包含数据绑定,所以当 `wx:if` 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。

同时 `wx:if` 也是**惰性的**,如果在初始渲染条件为 `false`,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。

相比之下,`hidden` 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。

一般来说,`wx:if` 有更高的切换消耗而 `hidden` 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 `hidden` 更好,如果在运行时条件不大可能改变则 `wx:if` 较好。

tips:条件渲染可以使用block元素。

5.模板

定义模板

<template name="temp1">
    <view>我的名字是:张三</view>
    <view>我的年龄是:18</view>
</template>

使用模板

使用模板并且向模板中传值

<template name="temp1">

  <view>我的名字是:{{user.name}}</view>

  <view>我的年龄是:{{user.age}}</view>

</template>

模板的作用域

模板拥有自己的作用域,只能使用 data 传入的数据以及模板定义文件中定义的 <wxs /> 模块

6.引用

我们可以将模板放到外部的文件中取使用引用引入进来

import

<import src="/templates/template.wxml" />

include

<include src="/templates/template.wxml" />

import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。

include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置

四、WXSS样式

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

WXSS 用来决定 WXML 的组件应该怎么显示。

为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

与 CSS 相比,WXSS 扩展的特性有:

  • 尺寸单位
  • 样式导入

1.新特性

尺寸单位

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

设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。

样式导入

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

@import "../../common/common.wxss";

内联样式

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

  • style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
<view style="color:{{color}};" />
  • class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
<view class="normal_view" />

选择器

选择器 样例 样例描述
.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 组件前边插入内容

2.全局样式/局部样式

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

3wxss使用背景图片

小程序中不能使用本地的图片作为背景图,可以使用网络图片,也可以使用base64的图片格式

4.字体图标

安装步骤:
(1)进入阿里巴巴矢量图标库https://www.iconfont.cn/
(2)选择自己的图标,添加到购物车
(3)进入购物车,点击下载代码到本地,进行解压(里面有字体文件iconfont.ttf,也有图标转化好的base64格式的文件iconfont.css),如果没有转好base64格式字体,我们只能自己转了,https://transfonter.org
(4)page.wxml页面进行使用
<view class="iconfont 你的图标类"></view>

代码案例:

<view class="iconfont iconok" style="color:red"></view>

五、事件系统

1.概念

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

2.事件绑定

使用bind+事件名=“函数名称”或者使用catch+事件名称=“函数名称”

<view bindtap="_fn1">事件1</view>

<view catchtap="_fn2">事件2</view>
 _fn1:function(){
​    console.log(this,"fn1")
  },
  _fn2(){
​    console.log(this,"fn2")
  },

3.事件分类

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

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

冒泡事件

类型 触发条件 最低版本
touchstart 手指触摸动作开始
touchmove 手指触摸后移动
touchcancel 手指触摸动作被打断,如来电提醒,弹窗
touchend 手指触摸动作结束
tap 手指触摸后马上离开
longpress 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 1.5.0
longtap 手指触摸后,超过350ms再离开(推荐使用longpress事件代替)
transitionend 会在 WXSS transition 或 wx.createAnimation 动画结束后触发
animationstart 会在一个 WXSS animation 动画开始时触发
animationiteration 会在一个 WXSS animation 一次迭代结束时触发
animationend 会在一个 WXSS animation 动画完成时触发
touchforcechange 在支持 3D Touch 的 iPhone 设备,重按时会触发

非冒泡事件

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

使用bind绑定的事件不会阻止冒泡,使用catch绑定的事件能阻止冒泡。

4.事件对象

属性 类型 说明 基础库版本
type String 事件类型
timeStamp Integer 事件生成时的时间戳
target Object 触发事件的组件的一些属性值集合
currentTarget Object 当前组件的一些属性值集合
mark Object 事件标记数据

5.传参接参

传递参数

​ 可以在组件上将传递的参数放到组件的id上,通过事件对象获取。e.currentTarget.id或者使用e.target.id(不推荐,知识巧妙使用id)

​ 可以在组件上使用 data-属性名=“传递的值”传参,在事件对象中能获取到传递的参数,属性名称会被转成小驼峰。

  • data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType

  • data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype

    <view data-name="zhangsan" data-age="18" data-user-sex="1" class="father" bindtap="_fn1">
    
      <view class="son" catchtap="_fn2"></view>
    
    </view>
    
    _fn2(e){
    
    ​    console.log(e.currentTarget.dataset)
    
     },
    

传递参数时可以传递多个参数,也可以传递一个对象。

总结:

事件对象中target和currentTarge区别

currentTarget:代表的是绑定事件的元素

target:代表是触发事件的元素。

事件绑定在哪个元素上,就在哪个元素传参,统一使用currentTarget去取。

六、WXS脚本语法

类似vue的过滤器功能

wxs中最好不好使用最新Es6的语法格式,wxs对新的语法支持的不是很好.

1.WXS脚本概述

WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。

WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。

WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。

WXS 函数不能作为组件的事件回调。

由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异

2.WXS 模块

WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内,或以 .wxs 为后缀名的文件内。

1遵循CommonJS 模块化规范

module对象

每个 wxs 模块均有一个内置的 module 对象。

module.exports

可以通过module.exports 暴露本模块的私有变量与函数,以便对外共享本模块

require

可以引入别的wxs文件里的内容。

2<wxs> 标签

<view>我的名字是{{m1.say("wangwu")}}</view>

<wxs module="m1">

  var name="lisi"

  var say=function(data){

​    return data.substring(0,3)

  }

  module.exports={

​    name:name,

​    say:say

  }

</wxs>

3.wxs 文件

test.wxs文件

var str="hello,world"

module.exports={

  str:str

}

wxtest.wxs文件

var tool=require("./test.wxs")
var name="lisi"
var say=function(data){
    return data.substring(0,3)
}
var eating=function(){
    return tool.str
}
module.exports={
    name:name,
    say:say,
    eating:eating
}

在wxml中使用

<view>{{m1.eating()}}</view>
<wxs src="./wxstest.wxs" module="m1"></wxs>

4反转字符串示例

<view>{{m1.reverse(name)}}</view>
<wxs module="m1">
    var reverse=function(str){
        return str.split("").reverse().join("")
    }
    module.exports={
        reverse:reverse
    }
</wxs>

七、常用的组件

1.基础组件

组件的概念

框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。

什么是组件:

  • 组件是视图层的基本组成单元。
  • 组件自带一些功能与微信风格一致的样式。
  • 一个组件通常包括 开始标签结束标签属性 用来修饰这个组件,内容 在两个标签之内。
<tagname property="value">
Content goes here ...
</tagname>

注意:所有组件与属性都是小写,以连字符-连接

公共属性

任何一个组件上都可以写的属性

属性名 类型 描述 注解
id String 组件的唯一标示 保持整个页面唯一
class String 组件的样式类 在对应的 WXSS 中定义的样式类
style String 组件的内联样式 可以动态设置的内联样式
hidden Boolean 组件是否显示 所有组件默认显示
data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数
bind* / catch* EventHandler 组件的事件 详见事件

特殊属性

几乎所有组件都有各自定义的属性,可以对该组件的功能或样式进行修饰

属性取值类型

类型 描述 注解
Boolean 布尔值 组件写上该属性,不管是什么值都被当作 true;只有组件上没有该属性时,属性值才为false。 如果属性值为变量,变量的值会被转换为Boolean类型
Number 数字 1, 2.5
String 字符串 "string"
Array 数组 [ 1, "string" ]
Object 对象 { key: value }
EventHandler 事件处理函数名 "handlerName"Page 中定义的事件处理函数名

text组件

类似h5中的span元素(行内元素)

<text user-select="{{true}}" space="emsp" decode="{{true}}">&lt;呐喊&gt;鲁迅</text>

view组件

类似h5中的div,(块状元素)

<view class="father" hover-class="red">

  <view hover-stop-propagation="{{true}}" class="son" hover-class="green"></view>

</view>

image组件

<image src="/static/erha1.jpg" lazy-load="{{true}}" bindload="_load"></image>

八、视图容器组件

1.swiper/swiper-item滑块视图容器

<swiper 
autoplay="{{true}}"
indicator-dots="{{true}}"
interval="2000"
circular="{{true}}"
bindchange="_changeImg"
>
    <swiper-item>
        <image src="/static/banners/1.jpg" />
    </swiper-item>
    <swiper-item>
        <image src="/static/banners/2.jpg" />
    </swiper-item>
    <swiper-item>
        <image src="/static/banners/3.jpg" />
    </swiper-item>
</swiper>

自定义指示点

wxml

<view class="container">

<swiper

autoplay="{{true}}"

interval="1000"

circular="{{true}}"

bindchange="_changeImg"

>

  <swiper-item wx:for="{{banner}}" wx:key="*this">

​    <image class="img" src="/static/banners/{{item}}" />

  </swiper-item>

</swiper>

<view class="dots">

  <text class="{{index==currentIndex?'active':''}}" wx:for="{{banner}}" wx:key="*this"></text>

</view>

</view>

wxss代码

.img{

   100%;

}

.container{

  position: relative;

}

.dots{

  position: absolute;

  bottom: 30rpx;

   100%;

  text-align: center;

}

.dots text{

  display: inline-block;

  30rpx;

  height:15rpx;

  background-color: #ccc;

  margin: 10rpx;

}

.dots .active{

  background-color: blue;

}

js代码

_changeImg:function(e){

​    this.setData({

​      currentIndex:e.detail.current

​    })

  },

2.scroll-view可滚动视图区域

wxml代码

<scroll-view class="scroll-x" scroll-x="{{true}}">
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
</scroll-view>

<scroll-view class="scroll-y" scroll-y="{{true}}" scroll-into-view="aa">
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view id="aa">导航12</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
    <view>导航1</view>
</scroll-view>

wxss代码

/* pages/scroll/scroll.wxss */

.scroll-x{

  white-space: nowrap;

}

.scroll-x view{

  display: inline-block;

  background-color: #ccc;

  margin:0rpx 10rpx;

  padding: 10rpx;

}

.scroll-y{

  400rpx;

  height:600rpx;

}

.scroll-y view{

  height:100rpx;

  line-height: 100rpx;

  text-align: center;

  background-color: #ccc;

  margin-bottom: 10rpx;

}

3.原生组件native-component

原生组件的概念

小程序中的部分组件是由客户端创建的原生组件,这些组件有:

原生组件的层级是最高的,所以页面中的其他组件无论设置 z-index 为多少,都无法盖在原生组件上。

  • 后插入的原生组件可以覆盖之前的原生组件。

原生组件还无法在 picker-view 中使用。

部分CSS样式无法应用于原生组件,例如:

  • 无法对原生组件设置 CSS 动画
  • 无法定义原生组件为 position: fixed
  • 不能在父级节点使用 overflow: hidden 来裁剪原生组件的显示区域

4.cover-view覆盖在原生组件之上的文本视图

<map>

  <view bindtap="_fn1" class="cover"></view>

</map> 

事件不会触发,_fn1不会执行,因为现在支持同层渲染,所以我们看到的好像是view放置在map的上面,但是map组件是放置view组件的上面,所以点击时不会触发事件,我们可以使用cover-view进行代替
<map>

  <cover-view bindtap="_fn1" class="cover"></cover-view>

</map>

5.cover-image覆盖在原生组件之上的图片视图

<map>
    <cover-image bindtap="_fn1" src="/static/banners/1.jpg"></cover-image>
</map>
原文地址:https://www.cnblogs.com/chenhaiyun/p/14872939.html