Bootstrap

2.7 可移动容器及可移动区域介绍:如何实现单条消息左滑删除功能?(二)

视频链接:

2.7 可移动容器及可移动区域介绍:如何实现单条消息左滑删除功能?(二)

片1

 

上节课我们学习movable-view与movable-area这两个组件的基础内容,了解了元素如何定位,以及如何自实现一个左滑删除效果。这节课我们继续学习这两个组件,看看在这个左滑效果的实现上,怎么添加一个自动恢复的效果。

 

使用 npm 安装项目模块

片2

 

上节课的那个示例,是一个粗糙的实现,缺乏按钮操作区域的回弹效果。具体来讲在效果上,我们需要在滑动不超过一半的时候,让它自动弹回去,然后在滑动超过一半的时候,让它自动弹出来。

 

 

cd miniprogram

npm init -y

npm install --save miniprogram-slide-view

 

{

"usingComponents": {

"slide-view": "miniprogram-slide-view"

}

}

 

<slide-view class="slide" width="750" height="100" slideWidth="300">

<view class="left" slot="left">这里是插入到组内容 2view>

<view class="right" slot="right">

<view class="read">已读view>

<view class="delete">删除view>

view>

slide-view>

“Component is not found in path”

片3

 

有一个开源小程序组件实现了这个效果,并且也是基于可移动组件实现的(地址见上方),我们看一下它的使用方法与实现机制是怎样的。

 

考虑到目前小程序已经支持了 npm,我们可以用 npm 安装这个组件的模块。

 

那么,怎么安装呢?

 

第一步,首先,我们使用 cd miniprogram 指令,在终端里切换到,我们的小程序源码目录。这里不是指项目的根目录,因为项目的根目录下还有云开发目录,而是与 cloudfunctions 平级的 miniprogram 这个目录。

 

第二步,然后,执行 npm 初始化,指令是 npm init -y(见上方代码)。这一步呢,是为了完成项目初始化,完成以后,目录下将自动生成一个 package.json 的文件。我们接下来安装的所有模块及版本信息,在这个文件里都有描述。

 

如果没有初始化这一步,下一步在选择菜单构建 npm 时,软件会提示找不到 npm 包的错误。

 

有时候,还会遇到这样的错误,“Component is not found in path”,这就要检查一下,是不是在小程序的源码目录下初始化 npm 模块的。在项目文件 project.config.json 中,配置字段 miniprogramRoot 指定的目录,才是我们选择 npm 初始化的目录。

 

第三步,接着,我们用npm install这个指令,开始安装上面提到的小程序组件,也就是 miniprogram-slide-view。安装完成以后,在小程序项目目录下,会多出一个 node_modules 目录。这个目录是本地存放模块的目录,以后所有下载的模块,都会被放在这个目录里。

 

但现在还不能马上使用。还需要在微信开发者工具中,选择菜单:工具->构建 npm。这一步是微信开发者工具干的活,它将小程序编译时需要的文件——仅仅是编译时需要的文件,并不包括所有,从 node_modules 目录下移动到 miniprogram_npm 这个目录下。

 

第一次执行这个菜单时,这个目录是不存在的,微信开发者工具会帮助我们自动创建。

 

第四步,最后,我们在小程序页面的 json 配置文件里面,使用 usingComponents这个配置,添加对组件的引用(见上面代码)。

 

完成配置以后,就可以在 wxml 代码中,使用这个组件了(代码及运行效果见上面)。

 

(可以从本课视频中查看示例及运行效果,左侧删除2)

 

以扩展声明的方式,使用 weui 组件库

片4

 

 

  • kbone: 

  • weui: 

 

"useExtendedLib": {

"weui": true

}

 

/* @import '/miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss'; */

<mp-slideview buttons="{{slideButtons}}" icon="{{true}}" bindbuttontap="slideButtonTap">

<view class="weui-slidecell">

左滑可以删除(图标 Button)

view>

mp-slideview>

片5

刚才实现的侧滑删除效果,已经有了自动反弹的效果,可以说已经很不错了。但微信团队有一个更好的实现。

 

我们知道weui是一个样式库,很多开发者都用过它。后来,微信团队基于这个样式库,又开发了一套组件库,被称之为 weui 组件库(github 网址见上方)。

 

这个weui 组件库,现在也可以在小程序项目中使用了,它包含了很多实用的组件,是官方正式组件的一个补充。使用 weui 组件库的好处,是显而易见的,它的 UI 风格与原生 UI 非常接近,可以让小程序获得与微信基本一致的视觉体验。

 

另外,这个 weui 组件库,与另外一个组件库——多端统一开发框架 kbone,是小程序唯一的两个扩展库。这两个扩展库,可以采用扩展声明的方式,直接在小程序中使用,并且还不占用小程序本来就有限的代码包大小。目前小程序所有分包大小不能超过 12M。

 

weui 组件库可以采用 npm 安装的方式使用——这个方法方法上面我们介绍过了,也可以通过扩展声明的方式使用,考虑到后者不占用代码包大小,我们优先选择后面这种方式。

 

那么,如何通过扩展声明的方式使用呢?

 

在小程序的配置文件 app.json 里面,通过useExtendedLib这个配置字段,添加对 weui 的引用(见上方代码)。添加后,别忘了选择微信开发者工具的菜单:工具->构建 npm,构建一下。构建以后,这样就完成了 weui 组件库的引入配置。

 

如果是 npm 安装,需要在 app.wxss 文件中添加对 weui.wxss 全局样式的引用(见上面代码),但如果是扩展声明,这句引用代码也可以省略了。

 

配置完成之后,如何使用呢?

 

在 json 文件中,使用 usingComponents 添加对 mp-slideview 组件的引用声明,然后就可以在 wxml 代码里使用这个组件了(代码示例及运行效果见上方)。

 

weui组件slideview源码:weui-miniprogram/src/slideview

 

<wxs module="handler" src="./slideview.wxs">wxs>

<view ....>

<view ...class="weui-slideview__left left" style="width:100%;">

<slot>slot>

view>

<view class="weui-slideview__right right">

...

view>

view>

片6

 

从weui组件库的slideview源码来看(见上面地址),这个组件并没有使用今天我们讲的movable-view与movable-area组件,它完全就是基于view实现的,并且关于视图的操作部分,也是在视图中使用wxs脚本写的。由于减少了视图层与逻辑层的通讯,在体验上也具有优势。所以,在小程序中实现左滑删除功能,第一推荐的方案,还是weui组件库里的slideview组件。

 

(可以从本课视频中查看示例代码及运行效果,左侧删除3)

 

关于页面未注册错误

片7

 

"xxx" has not been registered yet.

片8

 

有时候我们会遇到这样的错误,在Console面板里面,提示“页面未注册”,但是检测一下Page页面的地址,确实已经包括在app.json这个配置文件里了。

 

这里的未注册,并不是真的未注册,而是未注册成功。原因很有可能是页面中包括错误,例如引用了不存在的js文件等等。这个时候,我们只需要把新添加页面中的错误处理掉,这个未注册的错误自然就消失了。

 

课后作业

片9

 

下面我们看一下课后作业:在上节课我们留了一个问题,使用 Painter 组件,在小程序中生成一张自己的海报。相关示例在上节课的源码中都有,相信你看了之后就知道怎么用了。

 

其实除了使用 Painter 组件之外,在今天我们引用了 weui 组件库之后,还有一种更好的方式,将视图转为海报图片。

 

npm install --save wxml-to-canvas

片10

上面是 weui 组件库的文档地址,里面有一个 wxml-to-canvas 组件,它有绘制 canvas、导出图片的功能。实现的原理,大家可以看一下源码,与 Painter 是大同小异的。

 

做为扩展组件,它没有被包含进weui组件库中,即使我们已经对weui添加了扩展声明,也需要手动通过 npm 的方式再安装一下。

 

(可以从本课视频中查看运行效果)

 

关于 Canvas Api 错误:createImage fail: http://tmp/xxx....png

片11

 

错误:createImage fail: http://tmp/xxx....png

 

data: {

use2dCanvas: false

}

 

const use2dCanvas = false //compareVersion(SDKVersion, '2.9.2') >= 0

 

img = ` `

 

const isNetworkFile = /^https?:\/\//.test(img)

const isTempFile = /^wxfile:\/\//.test(img)

const isTempFile = true

片12

 

在使用这个组件时,现在会遇到一个“createImage fail”的错误(见上方文本)。

 

小程序从 2.9.0 基础库开始,已经支持了一套 Canvas 2D 新接口,使用的时候需要将 canvas 组件的 type 这个属性设置为“2d”。新接口支持同层渲染,并且旧接口官方声称也不再维护了,那么我们有充分的理由使用新接口。但是,从旧代码向新接口升级时,可能会有各种问题,上面这个错误就是由于使用新接口导致的。

 

如果我们将项目切回至 2.8.3 版本的基础库,同样的代码再次运行一下,就没问题。看来这个问题确实与版本有关系,接下来我们看看问题具体出在哪里。

 

通过查看wxml-to-canvas 组件的源码 ,在index.js 这个文件中,有一个数据变量 use2dCanvas(见上方 data 对象中),它用于标识是否使用 Canvas 2d 新接口。

 

我们看到,在组件周期函数 attached 里面,通过 wx.getSystemInfoSync 拿到当前的基础库版本号,然后与 Canvas 2d 新接口要求的最低版本号作比对,如果大于等于 2.9.2,则使用新接口,不然就使用旧接口。

 

从测试结果来看,是使用新接口时出了问题,因为我们把基础库切回到 2.8.3时,问题就不存在了。我们只需要将 use2dCanvas 变量硬编码为 false(见上方代码),这个 bug 就可以解决。

 

那么这个问题的原因是什么呢?它是怎么产生的呢?

 

在同一个文件里有一个 Draw 对象,这个对象有一个 drawImage 方法,在这里我们看到,如果 use2dCanvas 为 true的话,则使用 canvas.createImage 创建一个 HtmlElementImage 图片对象,并在这个图片 onload 以后再往画布上绘制图像。从代码来看,这个逻辑没有问题。

 

那么,问题到底出在哪里呢?

 

这时候我们注意到,在错误消息中,出问题的图片 url 是一个带有 tmp 标识的临时 url,如果我们将这个 url 硬编码为我们真正的外网 url(见上方代码),错误又没有了。

 

那问题的原因,就很有可能出在这个临时 url 上。

 

再继续翻源码,我们发现有两个正则判断了 url 的类型(见上方代码)。如果是临时 url,则直接创建 Image 对象绘制画布;如果是网络图片,则先用 wx.downloadFile 将图片下载到本地,换成临时 url,再绘制。问题就出在这里。

 

在小程序中,如果是在微信开发者工具中,临时 url 是以“http://tmp”开头的,如果是在手机设备上,临时 url 是以“wxfile://”开头的。这里的正则判断,没有考虑在开发者工具中的情况。

 

那我们怎么解决呢?

 

方法也很简单,直接将 isTempFile 这个变量改为 true(见上方代码),跳过图片下载。这时候仍然使用的是 canvas 2d 新接口,但也可以正常绘制与下载了。

 

但在测试时,发现还有一个问题,canvas 不随页面滚动。在页面不滚动时显示还正常,有滚动的时侯canvas 的位置显示就不正确了。

 

对于我们生成海报这个场景,可以将 canvas 设置为不显示,因为我们的目的,只是为了导出和保存图片,隐藏canvas并不会造成影响。

 

在使用了 canvas 2d 新接口以后,虽然支持了同层渲染,渲染效率提高了,但是代码升级时总有一些问题。在当前阶段,直接使用旧接口还是比较稳妥一些,新接口待等官方更新稳定了,我们再用也不迟。

 

(可从本课视频中查看示例及运行效果)

 

这节课也给你留一个作业:在本课示例中,在使用 mp-slideview 组件时,当在内部复用 mp-cell 组件的时候,我们看到,主要的内容文字没有上下居中显示。在引用weui组件时,如何在组件外面,控制它内部的样式效果呢?你能否控制示例中的文本,让它居中显示呢?

 

好,这节课就讲到这里。这节课主要介绍了可移动容器和可移动区域组件,以及元素如何定位,如何实现侧滑删除功能等等,下节课我们开始一起学习可滚动组件 scroll-view。

2020 年 5 月 22 日