1 uni-app 介绍
1.1 什么是uni-app
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到Android、iOS、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
uni-app官网 提供了一个快速体验的页面,编写了一套代码并部署到15个平台,可以到 这里 获取二维码并扫码体验。
1.2 uni-app 的由来
以下内容摘抄自 uni-app 官网介绍页面 “uni-app的由来”
uni,读
you ni
,是统一的意思。很多人以为小程序是微信先推出的,其实,DCloud才是这个行业的开创者。
DCloud于2012年开始研发小程序技术,优化webview的功能和性能,并加入W3C和HTML5中国产业联盟,推出了HBuilder开发工具,为后续产业化做准备。
2015年,DCloud正式商用了自己的小程序,产品名为“流应用”,它不是
B/S
模式的轻应用,而是能接近原生功能、性能的App,并且即点即用,第一次使用时可以做到边下载边使用。为将该技术发扬光大,DCloud将技术标准捐献给工信部旗下的HTML5中国产业联盟,并推进各家流量巨头接入该标准,开展小程序业务。
1.3 如何学习
1.3.1 学前须知
uni-app 是基于 Vue.js 的一个前端开发框架:
学习uni-app的基本要求是:已经掌握了HTML、CSS3和JavaScript的编程。
由于 uni-app 完全继承了 vue 的语法,所以本学期学习的所有页面功能代码,其编程思想都是基于 vue 以及原生 JavaScript 的。
1.3.2 入门文档
uni-app官网提供了一篇 “白话uni-app” 的文档帮助具有一定 H5 的基础,但是不熟悉 vue 和小程序的开发者来入门uni-app。
【阅读须知】:
这篇文档很长,但不难。从这篇文档里可以看到一条比较清晰的uni-app学习路线,请不要期望只阅读一遍就能全部掌握,对于初学者来说,这篇文档不仅仅是一篇入门文档,它还是一篇很好的工具文档,在入门学习阶段,这篇文档被查阅的几率很高。
1.3.3 参考资源
- uni-app 的官方教程
- 菜鸟教程的 学习 Vue.js
以上两个学习网站推荐大家做为“字典类”资源来使用。
另外,在学习的过程中,编写代码运行后还会遇到一些“错误”,这些信息都会出现在 HX 的调试窗口。当出现调试错误后,可以通过仔细阅读错误提示信息找到问题所在,然后进行纠正即可。当出现阅读不理解,不知如何纠正时,可以将出错信息复制到搜索引擎的窗口,并附带上一些发生错误的具体信息,可以在网络上搜到可行的解决方案。
1.3.4 关于uni-app项目模板
在 HX 中提供了很多 uni-app 的项目模板,其中:
- 默认模板:是uni-app最简单的模板,不包含扩展组件,适合创建自定义功能的项目。
- Hello uni-app 模板:是演示uni-app框架的组件、接口使用情况的模板,官网上体验的二维码扫描后看到的界面功能就是这个模板创建的。
- uni-ui 模板:是包含所有uni-app内置组件和扩展组件的模板,基于该模板创建的项目,可以自由使用所有的组件而无需安装和配置。由于这个模板里包含了所有的组件,所以容量比较大,不利于日常代码的版本管理,建议在实际项目的生产阶段不选择该模板。
【说明】:
使用默认模板创建项目后,还要根据实际开发需要从插件市场添加所需的组件,所以请务必保证已经注册了DCloud的账号,并在HX使用过程中处于登录状态。
2、从默认模板开始学习uni-app
2.1 了解uni-app项目的目录结构
在 HX 中新建一个 uni-app 的默认模板项目,命名为“Unit2-2.1”,建立好之后在 HX 的项目管理器窗口中看到如下图所示的项目目录结构:
2.1.1 pages目录
是项目运行后用以和用户进行交互的页面,所有的页面布局以及功能逻辑都是写在这里。
2.1.2 index.vue文件
是一个vue文件,因为vue是单页面文件,所有的布局、样式和逻辑都写在一个页面文件里。为了保证uni-app项目转换成微信小程序时能够顺利实现,需要给pages目录下的每一个vue页面文件创建一个同名的目录。这也是为什么 index.vue 文件需要保存在 index 目录下的原因。
2.1.3 static目录
这里存放的是项目中需要用到的外界静态资源,例如图片、视频、音频、其他js文件等。为了保证资源浏览方便,最好在static目录下创建资源的分类目录,并按类别保存所需的静态资源。例如在static目录下建立 images 文件夹用来存放图片,videos文件夹存放视频…
2.1.4 manifest.json 文件
这是当前项目的配置文件,之前所学习的配置微信小程序的AppID就是在这里操作,除此以外,这里还可以配置uni-app项目的AppID,这个ID值用来在DCloud云平台中对项目进行唯一标识。其他更多的配置在涉及到具体需求时再进行描述。
2.1.5 pages.json 文件
这里是对pages目录下的每一个 vue 文件进行配置的总管文件,这个文件还承担了uni-app项目运行时,首先从哪个page开始进入。所有page的配置都是json格式的数据,作为json数组中的一个元素存放在“pages”项中。
2.1.6 其他
项目中的其他文件是很重要的,但是本次内容暂时不涉及学习,请不要任意修改内容,防止代码无法运行。
2.2 从index.vue入手学习页面结构
在项目管理器窗口中双击“index.vue”页面文件,在 HX 的编辑器窗口中可以看到 index.vue 文件的源码内容。
一个 vue 文件包含三个部分:template、script、style。
2.2.1 template
template节点用于写 tag 组件,例如:view、text、image等,这些组件是用于在页面中进行资源展示以及与用户交互的。
【强调】:
- template 中有且仅有一个根 view,所有的内容都要写在这个根 view 下。
- 组件公共属性:template 中的所有组件都有共同的属性。其中 class 属性就是其中用来指定组件样式的属性。
- image组件:在 vue 中用于显示图片。
- text组件:用于在 view 中显示文字。不建议在 view 中直接编写文字内容,而应该放在 text 组件中显示。
- {{ 变量名 }}:这个是 vue 的模板语法,等同于把定义在 data() 部分的变量的值直接显示在这里。
2.2.2 script
在 script 节点中有一个 export default { } 结构,是页面的主要逻辑代码。包括几部分:
- data:template模板中需要使用的数据。具体另见
- 页面生命周期:如页面加载、隐藏、关闭,具体另见
- methods方法:这里是用户自定义的方法,如按钮点击后的响应、屏幕滚动响应等。
【重点】:
视图与逻辑中的数据绑定,详见下图指引。
- 上图中第3行的 src 属性前增加了冒号“:”,属性值是在 data 中定义的变量 imgSrc,依然要求写到双引号中,这种属于数据绑定。
- 在 data 中增加新的变量时,记得用逗号“,”做间隔。
2.2.3 style
style的语法与Web的CSS语法一致,在这里编写具体样式,然后在template节点内的组件中进行应用。
3 案例-单机版备忘录
3.1 功能分析
备忘录在很多手机都属于自带软件,一般备忘录程序都包含三个页面:列表页、详情页和添加页。
- 列表页:主要是按照时间倒序罗列备忘录的标题和添加时间。除此之外,还有一个增加新的备忘录的指示按钮,点击后可以进入添加备忘录的页面。
- 详情页:显示备忘录的具体内容,包括标题、内容、添加时间等。在这个页面上可以浏览内容,也可以进行备忘录内容的修改和删除。
- 添加页:这个页面上会有一些输入框,供用户输入备忘录的标题和内容等信息,还要提供一个“保存”或者“添加”按钮,用以将当前新增加的备忘录信息保存,并可以在列表页中看到新增的备忘录标题。
【总结】:
通过以上分析,制作备忘录需要使用大量uni-ui扩展组件,为了方便开发,将通过创建 uni-ui 模板项目来实施。
3.2 开发步骤
3.2.1 创建 UniMemo 项目
在 HX 中创建 uni-app 的 uni-ui 模板的项目UniMemo,将其保存在无中文的文件路径下。
相比通过默认模板创建的项目来说,uni-ui模板多了一个“uni_modules”目录,展开该目录可以看到很多用“uni_”开头的目录,这些就是uni-ui的扩展组件包,只有这里有的组件,在页面开发中才可以直接使用,否则需要去插件市场进行安装后才可以使用。
3.2.2 将 index 页面作为列表页进行设计
(1)为列表项准备数据
作为列表页,展示的是备忘录的标题和添加日期,并且是按照日期倒序排列,所以在 script 节点的 data 中增加用于显示列表信息的数组 “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 的值倒序编写的。
(2)在 view 根节点中添加 uni-list 组件
将 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 组件单独使用。
在预览中查看页面运行效果如下图所示:
(3)更改 index 页面的标题
上图的预览效果中,看到index.vue页面的顶部标题显示的是 “uni-app”,这是项目创建时自动编写的,通过修改pages.json文件中的内容,可以修改页面的标题信息。
3.2.3 创建新的页面
在3.1的功能分析中得到,除了列表页之外,备忘录小程序还需要详情页面和添加备忘录页面。
(1)创建详情页面 detail 页面
如下图所示,在 HX 的项目管理器视图中,“右键单击” pages 目录,在弹出的操作菜单中选择“新建页面§”。
【注意】:
一定要在 pages 目录上右键单击,否则会出现很多问题。
接下来,在弹出的窗口中请确认跟下图红色矩形框中标识的位置一致后,再点击“创建”按钮。
【说明】:
- 新创建的页面名称只需要写detail即可,不需要写detail.vue 。
- 创建同名目录:必须勾选。这样会在
pages
目录下增加一个与页面文件同名的目录,这样做的目的是为了和小程序开发的目录要求一致。 - 默认模板:初次学习如何编写一个page,选择这个模板就行。
- 在pages.json中注册:必须勾选。在
pages.json
文件中注册页面是为了和小程序开发要求一致。
(2)创建添加备忘录页面 add页面
步骤与(1)一致。
(3)pages.json 说明
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
}
}
],
...
}
【说明】:
- pages 项是一个 json 数组,该数组中的第一个元素是 uni-app 项目的启动页。上述代码中 index 页面是启动页。
- pages 项中每一个 json 数据的 path 项目的值是页面路径,这里主要注意路径中没有“.vue”。
- 如果在新建页面时,忘了勾选“在pages.json中注册”前的复选框,可以按照这个代码编写格式自行添加。
3.2.4 在index页面建立detail页面的访问途径
index页面中的每一个列表项应该可以被点击,并且点击之后应该在 detail 页面中看到不同的备忘录详情,具体步骤如下:
(1)在 method 中创建自定义函数 goToDetail。
goToDetail(memoIndex){
uni.navigateTo({
url:'/pages/detail/detail?memoIndex=' + memoIndex
})
}
【说明】:
- goToDetail函数带有一个 memoIndex 参数,用于标识当前点击的是列表中的哪一项。
- 函数体中用到了uni-app 的页面路由方法 uni.navigateTo ,用于进行uni-app项目内的页面跳转。
- url 赋值为一个页面地址字符串和index参数值的连接结果,其中“+”加号是字符串连接运算符。
(2)给 uni-list-item 增加访问链接属性。
<uni-list-item
:title="item.title"
:note="item.date"
@click="goToDetail(index)"
link>
</uni-list-item>
【说明】:
- 上面的代码结构一行一个属性,这种方式便于查看。
- @click属性绑定的是列表项被点击后的响应事件,这里是在method中定义的goToDetail函数。
- link 属性用于开启点击反馈,并且在列表项右侧显示箭头。
(3)预览效果
以上代码编写完成后,在预览中的效果如下图所示:
3.2.5 编写 detail 页面功能代码
(1)在 detail 页面的 script 节点的 data 中增加 index和memos 数据。
<script>
export default {
data() {
return {
index:0,
memos:[
{
title: 'DCloud账号密码',
date: '2023-9-5',
content: '用户名:abcdefg@126.com,密码是: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 页面的列表项中执行点击事件时,用于存放哪个列表项被点击的那个参数。
- uni-app 项目中,所有页面之间通过显式方式传递参数的方法是在页面路径后通过“?”问号挂接需要传递到目标页面的参数,参数按照 “参数名=参数值”的方式表述,多个参数之间用“&”符号连接。
- 目标页面在被加载时,所有从前一个页面传递过来的参数都存放在 option 数据中,option 是一个json数据,通过“.”点运算符访问被传递过来的参数名。
- 上述代码第32行中的 “this.index” 中的 “this” 表示的是当前页面,所有在 export default 中定义的 data 变量,method方法都可以通过 this 进行访问。
- 整个 onLoad 方法的作用就是:首先判断页面加载时是否携带了 memoIndex 参数,如果携带,那么将当前页面的 index 变量的值赋值为 memoIndex 参数的值;如果没有携带,那么在控制台打印出错提示。
(2)使用 uni-card 组件显示信息。
<template>
<view>
<uni-card :title="memos[index].title" :extra="memos[index].date">
{{memos[index].content}}
</uni-card>
</view>
</template>
【说明】:
- uni-card 组件的唤起代码是 uCard。
- title 是 uni-card 的标题属性,通过添加冒号前缀,与 data 中 memos 的数据项进行了绑定。
- memos 是 data 中的 json 数组型数据,数组元素下标通过方括号表述。
- extra 是 uni-card 的标题额外信息,这里用来显示备忘录的添加日期。
- uni-card 的主体内容直接写在组件标记对内部即可,如上述代码第4行所示。
(3)添加页面标题
在 pages.json 文件中,为 detail 页面添加标题,仿照3.2.2(3)的内容进行代码修改即可。修改页面标题为“备忘录详情”。
(4)预览效果
以上代码编写完成后,预览 index 页面,点击相应的列表项后,可以进入 detail 页面查看具体内容,下图是在 index 页面中点击 “移动应用开发课程要求” 一项后看到的具体内容。
3.2.6 uni-app 的缓存机制
【引子】:
在 index 页面和 detail 页面中都有 memos 数据,这两个数据的内容基本相同(数据冗余),而且这些数据项在代码中都是“写死”的,如果想要添加、修改或删除一个备忘录信息,就需要去修改代码,这显然是与功能设计初衷相违背的。
所以,需要考虑一种数据共享机制,这种机制可以实现在 uni-app 项目中,所有页面都能共享数据项,并对这些数据项进行修改。
而这种机制就是 uni-app 的数据缓存机制。
【说明】:
- uni-app 项目中的数据缓存可以理解为一个“全局文件”。
- 在这个全局文件中,用户可以将自己需要共享的数据以 json 的格式存放在其中。
- 获取缓存数据的方法是 uni.getStorage 和 uni.getStorageSync。
- 添加缓存数据的方法是 uni.setStorage 和 uni.setStorageSync。
3.2.7 在 index 页面中获取缓存数据
【分析】:
在 index 页面显示(onShow)时,需要判断缓存中是否有备忘录列表数据:
- 如果有,将缓存中的数据项赋值给 index 页面中的变量 memos;
- 如果没有,保持 index 页面中的 memos 变量的值为空,页面显示“空空如也”的提示字样。
(1)使用 onShow 访问缓存数据
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) 是成功访问到 memo 缓存项后的回调函数,用于对页面中的变量 memos 赋值。
- fail:function(e) 是未访问到 memos 缓存项后的回调函数。
- 因为整个 uni.getStorage 方法是异步回调的,所以要访问页面中的变量必须给当前页面建立一个新的拷贝,如上述代码第9行所示。
- 无论是不存在 memos 缓存项,还是虽然存在 memos 缓存项,但是该缓存数据中的内容是空的,那么都无法在页面中进行列表显示,因此需要根据这些情况来修改 flag 的值,用以控制视图内容的输出。
(2)使用 v-if v-else 控制视图输出
<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>
【说明】:
- 代码第3、5、6和17行,共同构成了一个 view 的显示与隐藏功能。
- v-if 和 v-else 用于渲染 view 的条件显示:
- 当 v-if 的值为“真”时,其包裹的组件被输出显示;
- 否则 v-else 包裹的组件内容显示。
3.2.8 在 index 页面建立 add 页面的访问途径
(1)悬浮按钮
<uni-fab @fabClick="goToAdd()" horizontal="left" vertical="bottom"></uni-fab>
【说明】:
- uni-fab 组件的唤起代码是 uFab。
- @fabClick 是悬浮按钮被点击后的响应动作,这里是调用了在 method 中定义的 goToAdd 函数。
- horizontal 是悬浮按钮在页面中的水平位置,有 left 和 right 两个值。
- vertical 是悬浮按钮在页面中的垂直位置,有 bottom 和 top 两个值。
- 以上代码请写在 index 页面中 v-if 、v-else 条件渲染 view 组件外。
(2)添加访问函数
goToAdd(){
uni.navigateTo({
url: '/pages/add/add'
})
}
【说明】:
- 以上代码要写在 method 中,在method中如果有多个自定义的函数,需要用“,”逗号间隔,否则会报错。
- goToAdd 函数没有任何参数,函数体的内容依然是调用了 uni.navigateTo 方法执行页面跳转。
(3)预览效果
以上代码编写完毕后,在预览中看到的效果如下图所示:
3.2.9 编写 add 页面功能代码
add页面负责提供输入框,供用户填写备忘录的标题、内容,还需要有一个按钮,实现点击后,可以将当前的备忘录信息添加到 uni-app 的数据缓存项 memos 中。
(1)使用 uni-nav-bar 和 uni-icons 设计自定义导航栏
在 add.vue 页面中 view 根节点下输入以下代码
<uni-nav-bar left-icon="list" left-text="备忘录" right-text="完成" @clickRight="addMemo"></uni-nav-bar>
【说明】:
- uni-nav-bar 的唤起代码是 uNavBar。
- left-icon 属性设置导航栏左侧图标,图标依赖 uni-icons 组件,可用的图标类型参考 uni-icons 示例。
- left-text 属性设置导航栏左侧文字。
- right-icon 属性设置导航栏右侧图标,right-text 属性设置导航栏右侧文字,但是这二者不可同时使用。
- @clickRight 是导航栏右侧图标或文字被点击后的响应事件,这里调用了在 method 中定义的 addMemo 函数。
- 导航栏的其他属性请参考 uni-nav-bar 组件属性 。
(2)使用 uni-forms 、uni-easyinput 组件设计备忘录添加表单
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 的唤起代码是 uForms,代码补全后自动创建带有一个 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个字符。
(3)为 add 页面编写新建备忘录功能
备忘录信息中有一个 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>
【说明】:
- 第 2 行使用 import 方式引入了在 static 文件夹下的 mydate.js 文件,因为 mydate.js 文件中将 timeNow 函数进行了输出,这里直接将 timeNow 函数名写在 {} 大括号内进行引入,方便后续代码使用。
- 第 21 ~ 60 行是 addMemo 函数的整个定义,这个函数从结构上看分成两部分:
- var that = this
- this.$refs.form.validate().then().catch()
- 这是一个 JS 中的 Promise,其中 then() 中的代码是当前面的 validate() 方法执行后得到期望值时再执行。
- 代码中第 24 ~ 56 行是 then() 中执行的回调代码,首先从缓存中访问 memos 数据:
- 如果找到了(代码第 28 ~ 41 行),就把 memoItem 的值追加到 memos 数组的最前面。(缓存中的数据只能读和重写,不能直接在缓存中修改,所以当通过 uni.getStorage 的方式获取 memos 后,需要先放到变量 mlist 中,把 memoItem 添加到 mlist 后,再把 mlist 作为要缓存的数据,通过 uni.setStroage 的方式覆盖掉原来的 memos 的值)
- 如果在缓存中未访问到 memos 数据(代码第 42 ~ 54 行),那么表示当前整个备忘录是空的,因此直接把 memoItem 数据作为 memos 的一个数组元素创建到缓存中。
- catch() 中的代码表示执行 validate() 方法后出错时执行。
- showAndBack() 函数用于在屏幕上显示一个提示信息,并在2秒后自动消失,页面自动返回到 index 中。
- 这里调用的 uni.showToast,这是一种页面交互方式,用于在页面上展示提示信息,并在指定的时间之内消失。
- setTimeout() 方法是 js 原生库中针对 window 的方法,这里的 window 表示的是运行小程序的窗体,它用于在指定的毫秒后调用函数或表达式。代码中第 17 ~ 19 行表示 2 秒后执行 uni.navigateBack 方法。
(4)在微信开发者工具中运行效果
【说明】:
上面图片是从 index 页面进入,点击底部悬浮按钮后进入 add 页面进行添加备忘录,成功后返回 index 页面,并在列表上点击后看到的 detail 页面上显示的具体内容。
3.2.10 改写 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 页面的样式。
- edit 页面 与 add 页面不同之处在于 edit 页面中的表单项有初始值,初始数据通过页面传递索引参数后,在数据缓存中获取,并与表单项进行双向绑定。
- edit 页面中可以利用自定义导航栏的 left-icon,选择垃圾桶图标,并定义 @clickLeft 事件用于从缓存数据中删除一个元素。
- edit 页面中的 @clickRight 事件应该是将缓存数据 memos 中原索引位置的值删掉,把表单中的绑定的数据 memoItem 插入到之前被删除的元素的位置即可。
- UniMemo 项目的完整源码已经部署到码云中,可以自行下载查看并学习。