uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 Android、iOS、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
uni-app官网 提供了一个快速体验的页面,编写了一套代码并部署到15个平台,可以到 这里 获取二维码并扫码体验。
以下内容摘抄自 uni-app 官网介绍页面 “uni-app的由来”
uni,读
you ni
,是统一的意思。很多人以为小程序是微信先推出的,其实,DCloud才是这个行业的开创者。
DCloud于2012年开始研发小程序技术,优化webview的功能和性能,并加入W3C和HTML5中国产业联盟,推出了HBuilder开发工具,为后续产业化做准备。
2015年,DCloud正式商用了自己的小程序,产品名为“流应用”,它不是
B/S
模式的轻应用,而是能接近原生功能、性能的App,并且即点即用,第一次使用时可以做到边下载边使用。为将该技术发扬光大,DCloud将技术标准捐献给工信部旗下的HTML5中国产业联盟,并推进各家流量巨头接入该标准,开展小程序业务。
uni-app 是基于 Vue.js
的一个前端开发框架:
学习 uni-app 的基本要求是:已经掌握了HTML、CSS3和JavaScript 的编程。
由于 uni-app 完全继承了 vue 的语法,所以本学期学习的所有页面功能代码,其编程思想都是基于 vue 以及原生 JavaScript 的。
uni-app 官网提供了一篇 “白话uni-app” 的文档帮助具有一定 H5 的基础,但是不熟悉 vue 和小程序的开发者来入门 uni-app。
【阅读须知】:
这篇文档很长,但不难。从这篇文档里可以看到一条比较清晰的 uni-app 学习路线,请不要期望只阅读一遍就能全部掌握,对于初学者来说,这篇文档不仅仅是一篇入门文档,它还是一篇很好的工具文档,在入门学习阶段,这篇文档被查阅的几率很高。
以上两个学习网站推荐大家做为“字典类”资源来使用。
另外,在学习的过程中,编写代码运行后还会遇到一些“错误”,这些信息都会出现在 HX 的调试窗口。当出现调试错误后,可以通过仔细阅读错误提示信息找到问题所在,然后进行纠正即可。当出现阅读不理解,不知如何纠正时,可以将出错信息复制到搜索引擎的窗口,并附带上一些发生错误的具体信息,可以在网络上搜到可行的解决方案。
在 HX 中提供了很多 uni-app 的项目模板,其中:
【说明】:
使用默认模板创建项目后,还要根据实际开发需要从插件市场添加所需的组件,所以请务必保证已经注册了 DCloud 的账号,并在HX使用过程中处于登录状态。
在 HX 中新建一个 uni-app 的默认模板项目,命名为“Unit2-2.1”,建立好之后在 HX 的项目管理器窗口中看到如下图所示的项目目录结构:
是项目运行后用以和用户进行交互的页面,所有的页面布局以及功能逻辑都是写在这里。
是一个 vue 文件,因为 vue 是单页面文件,所有的布局、样式和逻辑都写在一个页面文件里。为了保证 uni-app 项目转换成微信小程序时能够顺利实现,需要给 pages 目录下的每一个 vue 页面文件创建一个同名的目录。这也是为什么 index.vue
文件需要保存在 index 目录下的原因。
这里存放的是项目中需要用到的外界静态资源,例如图片、视频、音频、其他js文件等。为了保证资源浏览方便,最好在 static 目录下创建资源的分类目录,并按类别保存所需的静态资源。例如在 static 目录下建立 images 文件夹用来存放图片,videos 文件夹存放视频…
这是当前项目的配置文件,之前所学习的配置微信小程序的 AppID 就是在这里操作,除此以外,这里还可以配置 uni-app 项目的AppID,这个 ID 值用来在 DCloud 云平台中对项目进行唯一标识。其他更多的配置在涉及到具体需求时再进行描述。
这里是对 pages 目录下的每一个 vue 文件进行配置的总管文件,这个文件还承担了 uni-app 项目运行时,首先从哪个 page 开始进入。所有 page 的配置都是 json 格式的数据,作为 json 数组中的一个元素存放在“pages”
项中。
项目中的其他文件是很重要的,但是本次内容暂时不涉及学习,请不要任意修改内容,防止代码无法运行。
在项目管理器窗口中双击 “index.vue” 页面文件,在 HX 的编辑器窗口中可以看到 index.vue 文件的源码内容。
一个 vue 文件包含三个部分:template、script、style。
template
节点用于写 tag 组件,例如:view
、text
、image
等,这些组件是用于在页面中进行资源展示以及与用户交互的。
【强调】:
template
中有且仅有一个根 view
,所有的内容都要写在这个根 view
下。class
属性就是其中用来指定组件样式的属性。view
中显示文字。不建议在 view
中直接编写文字内容,而应该放在 text 组件中显示。data()
部分的变量的值直接显示在这里。在 script
节点中有一个export default { }
结构,是页面的主要逻辑代码。包括几部分:
data
:template
模板中需要使用的数据。具体另见methods
方法:这里是用户自定义的方法,如按钮点击后的响应、屏幕滚动响应等。【重点】:
视图与逻辑中的数据绑定,详见下图指引。
src
属性前增加了冒号“:”,属性值是在 data
中定义的变量 imgSrc
,依然要求写到双引号中,这种属于数据绑定。data
中增加新的变量时,记得用逗号“,”做间隔。style
的语法与 Web 的 CSS 语法一致,在这里编写具体样式,然后在 template
节点内的组件中进行应用。
备忘录在很多手机都属于自带软件,一般备忘录程序都包含三个页面:列表页、详情页和添加页。
【总结】:
通过以上分析,制作备忘录需要使用大量 uni-ui 扩展组件,为了方便开发,将通过创建 uni-ui 模板项目来实施。
在 HX 中创建 uni-app 的 uni-ui 模板的项目 UniMemo,将其保存在无中文的文件路径下。
相比通过默认模板创建的项目来说,uni-ui 模板多了一个 “uni_modules” 目录,展开该目录可以看到很多用 “uni-” 开头的目录,这些就是 uni-ui 的扩展组件包,只有这里有的组件,在页面开发中才可以直接使用,否则需要去插件市场进行安装后才可以使用。
作为列表页,展示的是备忘录的标题和添加日期,并且是按照日期倒序排列,所以在 script
节点的 data
中增加用于显示列表信息的 json 数组 memos
,具体见如下代码:
<script>
export default {
data() {
return {
memos:[
{
title: 'DCloud账号密码',
date: '2023-9-5'
},
{
title: '移动应用开发上课要求',
date: '2023-9-4'
},
{
title: '考研讲座信息',
date: '2023-9-3'
},
{
title: '教资考试注意事项',
date: '2023-9-2'
}
]
}
},
methods: {
}
}
script>
【说明】:
memos
是一个 json 数组,数据项是 json 数据,每一个 json 数据都包含两个数据项 title
和 date
。memos
中的数据项在组织时,是按照 date
的值倒序编写的。将 template
节点的代码改成如下所示的内容:
<template>
<view class="container">
<uni-list>
<view v-for="(item,index) in memos" :key="index">
<uni-list-item :title="item.title" :note="item.date">uni-list-item>
view>
uni-list>
view>
template>
【说明】:
uni-list
标记通过键入 “uList” 唤起 HX 的代码补齐功能。v-for
是列表的循环渲染语法,代码中第 4 行和第 6 行的 view
节点仅仅用于执行循环输出第 5 行的代码。uni-list-item
不能脱离 uni-list
组件单独使用。在预览中查看页面运行效果如下图所示:
上图的预览效果中,看到 index.vue 页面的顶部标题显示的是 “uni-app”,这是项目创建时自动编写的,通过修改 pages.json 文件中的内容,可以修改页面的标题信息。
在 3.1 的功能分析中得到,除了列表页之外,备忘录小程序还需要详情页面和添加备忘录页面。
如下图所示,在 HX 的项目管理器视图中,“右键单击” pages 目录,在弹出的操作菜单中选择“新建页面( P )”。
【注意】:
一定要在 pages 目录上右键单击,否则会出现很多问题。
接下来,在弹出的窗口中请确认跟下图红色矩形框中标识的位置一致后,再点击“创建”按钮。
【说明】:
这两个页面的创建步骤与(1)一致。
uni-app 项目中存在多个 page 时,通过在 pages.json 文件中设定首次启动的页面是哪一个。
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "我的备忘录"
}
},
{
"path" : "pages/detail/detail",
"style" :{
"navigationBarTitleText": "备忘录详情",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/add/add",
"style" :{
"navigationBarTitleText": "创建新的备忘录",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/edit/edit",
"style" : {
"navigationBarTitleText": "修改备忘录",
"enablePullDownRefresh": false
}
}
],
...
}
【说明】:
pages
项是一个 json 数组,该数组中的第一个元素是 uni-app 项目的启动页。上述代码中 index 页面是启动页。pages
项中每一个 json 数据的 path
项目的值是页面路径,这里主要注意路径中没有“.vue”。index 页面中的每一个列表项应该可以被点击,并且点击之后应该在 detail 页面中看到不同的备忘录详情,具体步骤如下:
goToDetail(memoIndex){
uni.navigateTo({
url:'/pages/detail/detail?memoIndex=' + memoIndex
})
}
【说明】:
goToDetail
函数带有一个 memoIndex
参数,用于标识当前点击的是列表中的哪一项。url
赋值为一个页面地址字符串和 index
参数值的连接结果,其中“+”加号是字符串连接运算符。<uni-list-item
:title="item.title"
:note="item.date"
@click="goToDetail(index)"
link>
uni-list-item>
【说明】:
@click
属性绑定的是列表项被点击后的响应事件,这里是在 methods
中定义的 goToDetail
函数。link
属性用于开启点击反馈,并且在列表项右侧显示箭头。以上代码编写完成后,在预览中的效果如下图所示:
<script>
export default {
data() {
return {
index:0,
memos:[
{
title: 'DCloud账号密码',
date: '2023-9-5',
content: '用户名:[email protected],密码是:123456'
},
{
title: '移动应用开发上课要求',
date: '2023-9-4',
content: '认真听、认真看、认真练'
},
{
title: '考研讲座信息',
date: '2023-9-3',
content: '9月22日 xx:xx:xx , 尚德楼 XXX 教室,著名考研讲师张*峰,主题是:考研的那些事儿'
},
{
title: '教资考试注意事项',
date: '2023-9-2',
content: '2023年教资考试具体要求如下:XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}
]
}
},
onLoad:function(option){
if(option.memoIndex != null) {
this.index = option.memoIndex
}else{
console.log("no memoIndex")
}
},
methods: {
}
}
script>
【说明】:
index
是 detail 页面的变量,默认值是0。memos
数据的内容与 index 页面中的 memos
相比,增加了 content
数据项。onLoad
是页面生命周期中的监听页面加载时的方法,这个方法里的功能根据具体需要有用户自定义编写。【重点】:
onLoad
方法监听了在页面加载时是否捕获到 memoIndex
这个参数,也就是从 index 页面的列表项中执行点击事件时,用于存放哪个列表项被点击的那个参数。?
问号挂接需要传递到目标页面的参数,参数按照 参数名=参数值
的方式表述,多个参数之间用 &
符号连接。option
数据中,option
是一个json数据,通过 .
点运算符访问被传递过来的参数名。this
表示的是当前页面,所有在 export default
中定义的 data
变量,methods
方法都可以通过 this
进行访问。onLoad
方法的作用就是:首先判断页面加载时是否携带了 memoIndex
参数,如果携带,那么将当前页面的 index
变量的值赋值为 memoIndex
参数的值;如果没有携带,那么在控制台打印出错提示。<template>
<view>
<uni-card :title="memos[index].title" :extra="memos[index].date">
{{memos[index].content}}
uni-card>
view>
template>
【说明】:
title
是 uni-card
的标题属性,通过添加冒号前缀,与 data
中 memos
的数据项进行了绑定。memos
是 data
中的 json 数组型数据,数组元素下标通过方括号表述。extra
是 uni-card
的标题额外信息,这里用来显示备忘录的添加日期。uni-card
的主体内容直接写在组件标记对内部即可,如上述代码第 4 行所示。在 pages.json 文件中,为 detail 页面添加标题,仿照3.2.2(3)的内容进行代码修改即可。修改页面标题为“备忘录详情”。
以上代码编写完成后,预览 index 页面,点击相应的列表项后,可以进入 detail 页面查看具体内容,下图是在 index 页面中点击 “移动应用开发课程要求” 一项后看到的具体内容。
【引子】:
在 index 页面和 detail 页面中都有 memos
数据,这两个数据的内容基本相同(数据冗余),而且这些数据项在代码中都是“写死”的,如果想要添加、修改或删除一个备忘录信息,就需要去修改代码,这显然是与功能设计初衷相违背的。
所以,需要考虑一种数据共享机制,这种机制可以实现在 uni-app 项目中,所有页面都能共享数据项,并对这些数据项进行修改。
而这种机制就是 uni-app 的数据缓存机制。
【说明】:
uni.getStorage
和 uni.getStorageSync
。uni.setStorage
和 uni.setStorageSync
。【分析】:
在 index 页面显示(onShow
)时,需要判断缓存中是否有备忘录列表数据:
memos
;memos
变量的值为空,页面显示“空空如也”的提示字样。data() {
return {
flag: false,
tip:'空空如也',
memos:[]
}
},
onShow:function(){
var that = this
uni.getStorage({
key: 'memos',
success:function(res){
that.memos = res.data
if(that.memos.length == 0){
that.flag = true
}else{
that.flag = false
}
},
fail:function(e){
that.flag = true
}
})
},
【说明】:
data
中定了三个变量: flag
用来操控页面显示的内容,tip
是提示信息,memos
用来存放从缓存中获取的数据值。onShow
方法用于监听页面显示的响应过程,这里使用异步方式访问缓存的数据项 memos
:
success:function(res){ }
是成功访问到 memos
缓存项后的回调函数,用于对页面中的变量 memos
赋值。fail:function(e){ }
是未访问到 memos
缓存项后的回调函数。uni.getStorage
方法是异步回调的,所以要访问页面中的变量必须给当前页面建立一个新的拷贝,如上述代码第 9 行所示。memos
缓存项,还是虽然存在 memos
缓存项,但是该缓存数据中的内容是空的,那么都无法在页面中进行列表显示,因此需要根据这些情况来修改 flag
的值,用以控制视图内容的输出。<template>
<view class="container">
<view v-if="flag">
<text>{{ tip }}text>
view>
<view v-else>
<uni-list>
<view v-for="(item,index) in memos" :key="index">
<uni-list-item
:title="item.title"
:note="item.date"
@click="goToDetail(index)"
link>
uni-list-item>
view>
uni-list>
view>
view>
template>
【说明】:
view
的显示与隐藏功能。view
的条件显示:
v-if
的值为“真”时,其包裹的组件被输出显示;v-else
包裹的组件内容显示。<uni-fab @fabClick="goToAdd()" horizontal="left" vertical="bottom">uni-fab>
【说明】:
uni-fab
组件的唤起代码是 uFab。@fabClick
是悬浮按钮被点击后的响应动作,这里是调用了在 methods
中定义的 goToAdd
函数。horizontal
是悬浮按钮在页面中的水平位置,有 left
和 right
两个值。vertical
是悬浮按钮在页面中的垂直位置,有 bottom
和 top
两个值。v-if
、v-else
条件渲染 view
组件外。goToAdd(){
uni.navigateTo({
url: '/pages/add/add'
})
}
【说明】:
methods
中,如果有多个自定义的函数,需要用 ,
逗号间隔,否则会报错。goToAdd
函数没有任何参数,函数体的内容依然是调用了 uni.navigateTo
方法执行页面跳转。以上代码编写完毕后,在预览中看到的效果如下图所示:
add 页面负责提供输入框,供用户填写备忘录的标题、内容,还需要有一个按钮,实现点击后,可以将当前的备忘录信息添加到 uni-app 的数据缓存项 memos
中。
在 add.vue 页面中 view
根节点下输入以下代码
<uni-nav-bar left-icon="list" left-text="备忘录" right-text="完成" @clickRight="addMemo">uni-nav-bar>
【说明】:
left-icon
属性设置导航栏左侧图标,图标依赖 uni-icons
组件,可用的图标类型参考 uni-icons 示例。left-text
属性设置导航栏左侧文字。right-icon
属性设置导航栏右侧图标,right-text
属性设置导航栏右侧文字,但是这二者不可同时使用。@clickRight
是导航栏右侧图标或文字被点击后的响应事件,这里调用了在 methods
中定义的 addMemo
函数。add.vue 中 template
节点的代码入下:
<template>
<view>
<uni-nav-bar left-icon="list" left-text="备忘录" right-text="完成" @clickRight="addMemo">uni-nav-bar>
<view class="container">
<uni-forms ref="form" :rules="rules" :model="memoItem">
<uni-forms-item name="title">
<uni-easyinput v-model="memoItem.title" placeholder="标题" />
uni-forms-item>
<uni-forms-item name="content">
<uni-easyinput type=textarea v-model="memoItem.content" placeholder="内容" />
uni-forms-item>
uni-forms>
view>
view>
template>
add.vue 中 data
部分定义的代码如下:
data() {
return {
memoItem: {
title: '',
content: '',
addTime: ''
},
rules: {
title: {
rules: [
{required: true, errorMessage: '标题不能空'},
{minLength: 3, maxLength: 20, errorMessage: '长度在3~20字符之间'}
]
},
content: {
rules: [
{required: true, errorMessage: '还没有填写内容'},
{minLength: 3, maxLength: 200, errorMessage: '长度在3~200字符之间'}
]
}
}
}
},
【说明】
uni-forms-item
组件的 uni-form
组件。
uni-forms
组件的 :model
用于同 data
中定义的数据进行绑定后执行校验时对数据进行访问。uni-forms
组件的 :rules
属性是必选项,代码中将其与 data
中定义的 rules
变量绑定,用于对表单中的项目进行校验,只有校验符合 data
中定义的 rules
变量中的配置时,才允许表单被提交。uni-forms
组件的 ref
属性是必选项,用于在进行表单验证时识别具体的表单。uni-forms-item
不能脱离 uni-forms
单独使用,且内部只能包含一个表单类组件。
uni-forms-item
的 name
属性值用于同 data
中定义的 rules
数据中的校验项对应,上述代码中 name="title"
,表示该表单项的输入内容要同 data
中 rules.title
定义的规则一致。uni-forms-item
默认创建时会带有 label
属性,该属性用于在表单项前显示提示文字,如果不需要,可删掉该属性。uni-easyinput
组件的 v-model
属性用于和 data
中定义的具体数据项进行双向绑定。uni-forms
绑定的数据和校验规则写在 data
中 。
data
中定义的 memoItem
是一个 json 格式的数据,包含了备忘录信息所需要的具体字段:title
,content
,addTime
data
中定义的 rules
是针对 form
的校验规则,与 uni-forms
的 rules
绑定。
rules
是一个 json 数据,每个数据项对应一个 uni-forms-item
的 name
属性值。rules.title.rules
的值为例,每个项目的校验规则都是一个 json 数组,可以包含多个校验项,这里表示 title
数据是必须的,并且长度限制在3~20个字符。备忘录信息中有一个 addTime
数据用来记录提交的系统时间,为了方便代码重用,考虑将日期时间的处理函数放在外部 js 文件中,然后在需要的地方 import
。
① 在 static 文件夹中创建 mydate.js 文件,并将以下代码保存在该文件中。
export function timeNow(){
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
month >=1 && month <=9 ? (month = "0" + month) : "";
var day = now.getDate() < 10 ? ("0" + now.getDate()) : now.getDate();
var hour = now.getHours() < 10 ? ("0" + now.getHours()) : now.getHours();
var minute = now.getMinutes() < 10 ? ("0" + now.getMinutes()) : now.getMinutes();
var second = now.getSeconds() <10 ? ("0" + now.getSeconds()) : now.getSeconds();
var value = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
return value;
}
【说明】:
这里采用了 ES6 的 module 的 export
和 import
机制,如果要在 vue 文件中 import
一个 js 文件中的方法,首先需要将这个方法在 js 文件中作为 module 进行 export
。
更多的有关 export
和 import
的内容请参考 阮一峰的ES6入门-Module语法。
② 修改 add.vue 的 script
节点的代码如下:
<script>
import {timeNow} from '@/static/mydate.js'; // 引入外部 js 文件中的function
export default {
data() {
return {
... //这里代码在本节(2)中已给出,不再展示
}
},
methods: {
showAndBack(){ // 用于屏幕提示2秒后自动消失并返回上一个页面
uni.showToast({
icon:"success",
title: "添加成功",
duration:2000
});
setTimeout(function(){
uni.navigateBack()
}, 2000);
},
addMemo(){
var that = this //为当前页面创建拷贝,方便在回调中使用
this.$refs.form.validate().then((res)=>{//这里是表单校验成功后的操作
that.memoItem.addTime = timeNow() // 访问外部函数 timeNow 给 addTime 赋值
//以下是先从缓存中访问 memos,根据访问情况执行后续操作
uni.getStorage({
key:'memos',
success:function(res){ //成功从缓存中获取了数据
var mlist = res.data
mlist.splice(0, 0, that.memoItem); // 插入到最前,实现倒序
uni.setStorage({ // 以下把修改后的数据再存放回缓存中
key:'memos',
data: mlist,
success() {
that.showAndBack()
},
fail:function(e){
console.log(e)
}
})
},
fail() {// 缓存中不存在数据,本次新建属于首次在缓存中创建数据
var mlist = [that.memoItem]
uni.setStorage({
key: 'memos',
data: mlist,
success() {
that.showAndBack()
},
fail:function(e){
console.log(e)
}
})
}
})
})
.catch((err)=>{//这里是表单校验失败后的操作
console.log("form invalidate")
})
}
}
}
script>
【说明】:
import
方式引入了在 static 文件夹下的 mydate.js 文件,因为 mydate.js 文件中将 timeNow
函数进行了输出,这里直接将 timeNow
函数名写在 {}
大括号内进行引入,方便后续代码使用。addMemo
函数的整个定义,这个函数从结构上看分成两部分:
then()
中的代码是当前面的 validate()
方法执行后得到期望值时再执行。then()
中执行的回调代码,首先从缓存中访问 memos
数据:
memoItem
的值追加到 memos
数组的最前面。(缓存中的数据只能读和重写,不能直接在缓存中修改,所以当通过 uni.getStorage
的方式获取 memos
后,需要先放到变量 mlist
中,把 memoItem
添加到 mlist
后,再把 mlist
作为要缓存的数据,通过 uni.setStroage
的方式覆盖掉原来的 memos
的值)memos
数据(代码第 42 ~ 54 行),那么表示当前整个备忘录是空的,因此直接把 memoItem
数据作为 memos
的一个数组元素创建到缓存中。catch()
中的代码表示执行 validate()
方法后出错时执行。showAndBack()
函数用于在屏幕上显示一个提示信息,并在2秒后自动消失,页面自动返回到 index 中。
uni.showToast
,这是一种页面交互方式,用于在页面上展示提示信息,并在指定的时间之内消失。uni.navigateBack
方法。【说明】:
上面图片是从 index 页面进入,点击底部悬浮按钮后进入 add 页面进行添加备忘录,成功后返回 index 页面,并在列表上点击后看到的 detail 页面上显示的具体内容。
detail 页面用于显示某个具体的备忘录信息,这个具体的值是从缓存数据 memos
中获取的,因此在 detail 页面的 onLoad
事件中应当执行缓存数据的获取操作,然后根据传入的参数 memoIndex
的值来访问具体的数组元素,并把元素的值渲染在视图中。
<template>
<view>
<uni-card :title="memoItem.title" :extra="memoItem.addTime">
{{memoItem.content}}
uni-card>
view>
template>
<script>
export default {
data() {
return {
index: 0,
memoItem: {
title: '',
content: '',
addTime: ''
}
}
},
onLoad:function(option){
var that = this
if(option.memoIndex != null) {
this.index = option.memoIndex
uni.getStorage({
key: 'memos',
success:function(res){
that.memoItem = res.data[that.index]
},
fail:function(e){
console.log(e)
}
})
}else{
console.log("no memoIndex")
}
},
methods: {
}
}
script>
【说明】:
在 data
中创建与备忘录数据元素相同的 json 格式的数据变量 memoItem
,用以接收从缓存中获取的数据。
edit 页面从组件布局上讲与 add 页面一致,都提供了两个 uni-easyinput
组件和“完成”按钮。
不同的是,add 页面在初始进入时,分别用来填写备忘录标题和内容的两个 uni-easyinput
组件的内容是空的;而 edit 页面上在 uni-easyinput
组件中显示的是需要修改的备忘录的标题和内容。
<template>
<view>
<uni-nav-bar left-icon="trash" right-text="完成" @clickLeft="deleteMemo" @clickRight="editMemo">uni-nav-bar>
<view class="container">
<uni-forms ref="form" :rules="rules" :model="memoItem">
<uni-forms-item name="title">
<uni-easyinput v-model="memoItem.title" placeholder="标题" />
uni-forms-item>
<uni-forms-item name="content">
<uni-easyinput type=textarea v-model="memoItem.content" placeholder="内容" />
uni-forms-item>
uni-forms>
<text>上次编辑时间:{{memoItem.addTime}}text>
view>
view>
template>
【说明】:
将本节的代码与 3.2.9(2)中提供的代码对比来学习:
uni-forms
组件内的代码完全一致。uni-nav-bar
组件部分,edit 页面将 left-icon
的图标换成了 “trash”(垃圾桶),并且为自定义导航栏左侧的点击事件绑定了响应函数deleteMemo
。uni-forms
组件外面添加了提示“上次编辑时间”的 text
组件,用以显示当前备忘录上一次被“添加/修改”的时间。data() {
return {
index: 0,
memos:[],
memoItem: {
title: '',
content: '',
addTime: ''
},
rules: {
title: {
rules: [
{required: true, errorMessage: '标题不能空'},
{minLength: 3, maxLength: 20, errorMessage: '长度在3~20字符之间'}
]
},
content: {
rules: [
{required: true, errorMessage: '还没有填写内容'},
{minLength: 3, maxLength: 200, errorMessage: '长度在3~200字符之间'}
]
}
}
}
},
【说明】:
将本节代码与 3.2.9(2)中提供的 data
部分的代码作对比,可以看出这里增加两个变量:
index
变量用于接收页面传参,标识被修改的备忘录是缓存中的第几条数据。
memos
变量是json数组,初始化时数组元素个数为0。当 edit 页面被加载时,暂存从缓存中拿到的 key
为 memos
的备忘录数组数据。
edit 页面的进入顺序是:index 页面 → detail 页面 → edit 页面。
从 detail 页面进入 edit 页面时,同样需要将当前备忘录的索引值作为参数传递。
edit 页面被加载时首先通过访问缓存,根据传递的参数拿到具体的备忘录信息,然后对视图进行渲染。
onLoad:function(option){
var that = this
if(option.memoIndex != null) {
this.index = option.memoIndex
uni.getStorage({
key: 'memos',
success:function(res){
that.memos = res.data
that.memoItem = res.data[that.index]
},
fail:function(e){
console.log(e)
}
})
}else{
console.log("no memoIndex")
}
},
【说明】:
if
语句,判断页面加载时是否携带了 memoIndex
参数,如果存在,那么执行第 4 ~ 14 行的代码;否则执行第 16 行的控制台打印代码。memoIndex
的值存放在页面变量 index
中,用于备忘录信息修改或者删除时,方便从备忘录数组数据中定位。memos
数据值存放在了页面的变量 that.memos
中(为了区分缓存数据 memos
和页面变量 memos
,这里用that.memos
表示页面变量),这样做的目的是如果用户进行了修改或者删除操作,只需要在 that.memos
中处理后再调用 uni.setStorage
进行缓存的改写即可。memoItem
中,这里的值会直接在视图上进行渲染。editMemo(){
var that = this //为当前页面创建拷贝,方便在回调中使用
this.$refs.form.validate().then((res)=>{//这里是表单校验成功后的操作
that.memoItem.addTime = timeNow()
that.memos.splice(that.index, 1); // 删掉原索引位置的备忘录数据项
that.memos.splice(that.index, 0, that.memoItem); // 在被删掉的位置插入新的备忘录数据项
uni.setStorage({
key: 'memos',
data: that.memos,
success() {
that.backList()
}
})
})
.catch((err)=>{//这里是表单校验失败后的操作
console.log("form invalidate")
})
}
【说明】:
splice
方法。这个方法在 add 页面中创建新的备忘录时用到过,更多用法详见这里。deleteMemo(){
var that = this
uni.showModal({ // 显示模态框询问
content: '确定要删除吗?',
success:function(res){
if(res.confirm){ // 用户点击确定按钮
that.memos.splice(that.index, 1);
uni.setStorage({
key: 'memos',
data: that.memos,
success() {
that.backList()
}
})
}
}
})
}
【说明】:
uni.showModal
,这是 uni-app 的页面交互 API 中的“显示模态框”。这种组件在小程序应用中也十分常见,通常用于在用户执行一些比较危险的操作时(例如删除某条记录等),提示用户是否确认操作。res
中,confirm
数据项的值为 true
res
中,cancel
数据项的值为 true
res.confirm
以及res.cancel
的值是否为真,就可以得到用户点击的是哪个按钮。在 editMemo
和 deleteMemo
自定义函数中,都调用了一个 backList
自定义函数。代码是:
backList(){
uni.showToast({
icon:"success",
title: "操作成功",
duration:2000
});
setTimeout(function(){
uni.redirectTo({
url:'/pages/index/index'
})
}, 2000);
}
【说明】:
backList
自定义函数功能与 3.2.9(3)②中给出的 add 页面的 showAndBack
自定义函数功能基本上相同。不同之处在于这里当2秒钟倒计时结束后,执行的是 uni.redirectTo
方法,用以将当前页面关闭掉,并强制调转到 url
所指定的页面。uni.navigateTo
和 uni.redirectTo
都可以实现从当前页面跳转到 url
指定的页面,但 uni.navigateTo
不会关闭当前页面,而是将其放入“页面栈”中,用户可以通过导航栏的 “<” 按钮返回。而这里显然使用 uni.redirectTo
更合理。UniMemo 项目的完整源码已经部署到码云中,可以自行下载查看并学习。