一、overflow实现横向滑动
在上次的静态页面项目中,提到了如何实现100个数据项横向滑动。当时是使用了list组件,主要是在查找官方开发文档时,显示overflow:scroll只支持纵向滑动。
其实依然可以使用overflow:scroll来实现,这里我们可以在block循环外加一个div并添加样式,因为我们要实现的只是这个循环内数据可以横向滑动,所以没有必要在全局的container样式中实现滑动。具体代码如下:
js代码:
export default {
data: {
//js中的数组是用[]表示,动态数组 Java数组{},new表示 定长
arrs:[],
},
onInit(){
for(let i = 0 ; i< 100 ; i++){
this.arrs.push("第"+i+"项");
}
}
}
hml代码:
<div class="container">
<div class="topview">
<block for="{{arrs}}">
<div class="boxview">
<text>{{$item}}</text>
</div>
</block>
</div>
</div>
Css样式:
.container {
display: flex;
flex-direction: row;/*默认是按行的*/
height: 100%;
/* overflow: scroll;*/
}
.boxview{
display: flex;
justify-content: center;
align-items: center;
width: 30%;
height: 20%;
border: 1vp solid black;
margin: 20vp;
}
.topview{
display: flex;
height: 40%;
border-bottom: 1vp solid black;
overflow: scroll;
justify-content: center;
align-items: center;
}
具体实现效果:
注意点:样式中将全局container样式中的overflow:scroll转移到新创建的样式中。再添加一些弹性布局即可实现。
这里在学习过程中,也可以切换设备。除了在项目创建时可以选择设备,在具体项目中,我们也可以自定义展示设备。
例如:在config.json中设置:
手表展示如下:
二、轮播图及横向滑动图片展示
在实现轮播图之前,我们可以在string.json中设置我们的页面标题,具体文件位置如图:
- 首先将需要展示的图片下载到本地文件夹中
在js中写好数组,数组主要存储图片地址:
export default {
data: {
swiperdatas:["common/images/huang.jpg","common/images/jici.jpg","common/images/kuiying.jpg"],
imagedatas:["common/images/1.png","common/images/2.png","common/images/3.png",
"common/images/4.png","common/images/5.png","common/images/6.png","common/images/7.png",
"common/images/8.png","common/images/9.png"]
}
}
在hml中我们将页面结构完成,先使用swiper组件实现轮播图,autoplay属性是自动播放,indicator属性true是为了开启轮播图导航点。
<div class="container">
<div class="topview">
<swiper class="swiperview" autoplay="true" indicator="true">
<block for="{{swiperdatas}}">
<div class="box">
<image src="{{$item}}"></image>
</div>
</block>
</swiper>
</div>
<div class="twoview">
<block for="{{imagedatas}}">
<div class="hbox">
<image class="imgview" src="{{$item}}"></image>
</div>
</block>
</div>
</div>
Css样式如下:
.container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: greenyellow;
}
.topview{
width: 100%;
height: 30%;
border-bottom: 2vp solid black;
}
.twoview{
/* width: 100%;*/
height: 22%;
border-bottom: 2vp solid black;
display: flex;
overflow: scroll;
}
.swiperview{
width: 100%;
height: 100%;
}
.box{
width: 100%;
height: 100%;
/* margin: 10vp;*/
}
.hbox{
width: 32%;
height: 100%;
/* border: 1vp solid black;*/
margin: 12vp;
/* border-radius: 10vp;*/
}
.imgview{
width: 100%;
height: 100%;
border-radius: 10vp;
}
实现效果为:
三、基于鸿蒙的滚动视图的增删改查的练习
1.数组是个有序的数据结构,下标确定值的数据结构,在data中定义数组,并且在初始页面加载数组数据,使用for循环输出。
data: {
arrdatas:[]
},
onInit(){
for (let i = 0; i <= 20; i++) {
this.arrdatas.push("第"+i+"项");
}
},
2.在页面的上方设置两个按钮,绑定点击事件
<div class="btnview" onclick="add"><text>增加</text></div>
<div class="btnview" onclick="delall"><text>全部删除</text></div>
3.并且在两个按钮下方使用for循环展示具体数据,并且在每一项数据后面增加单个删除功能的按钮,返回的idx是选中的数据项的下标,返回给js
<block for="{{arrdatas}}">
<div class="boxview">
<text>{{$item}}</text>
<button class="btnview" type="text" onclick="delitem({{$idx}})">删除</button>
</div>
</block>
4.删除所有数据的方法,当点击全部删除按钮后,将arrdatas数组重新赋值为空来实现全部删除操作。在js导入prompt模块,是为了在用户点击删除按钮时对操作者有个安全操作的提示,例如弹出对话框提醒。
5.增加功能的实现,添加的是随机生成的0-10之间的数据项。使用Math.random*数值,来获取随机数。这里的“*数值”表示取值范围是[0,数值),那个数值是取不到的。但这时候取到的值是带小数的,我们不需要小数就要对随机数进行取整,使用parseInt()来实现。我们可以使用typeof查看event对象的类型,两次都为number。
add(){
//添加 随机数 使用javascript随机数
// *数值表示:范围是0-数值 [0,数值) 数值取不到
//js查看数据类型的关键字:typeof
let rv = parseInt(Math.random()*11);
console.log("随机数为:"+rv);
console.log(typeof rv);
//数据模型会自动驱动视图变化(渲染)
this.arrdatas.push("随机数项为:"+rv+"项");
},
6.单个数据项删除的实现,我们需要获取到选择项的下标,所以在onclick点击事件中,将数据下标idx传给js中的delitem方法。
<button class="btnview" type="text" onclick="delitem({{$idx}})">删除</button>
7.这里主体方法和上面的全部删除一样,都是设置点击后弹出对话框,提醒用户这是删除操作。对话框中title设置的是对话框的标题,message设置对话框的内容,buttons最少要有两个,text是按钮内容,color设置颜色。如果用户选择删除,则使用this.arradtas.splice(index,1)来删除index这一项,index参数表示要删除的数据下标,1表示要删除的个数。
delitem(index){
console.log("点击删除的项目索引是:"+index);
//在执行删除和更新的时候,应该对操作者有个安全操作的提示
//操作严谨性
//执行删除 规避责任
//会弹出对话框
prompt.showDialog({
title:"操作提示",
message:"你确定要删除吗?",
buttons:[{"text":"确认","color":"#000000"},{"text":"取消","color":"#000000"}],
success:(event)=>{
console.log(event);
console.log(typeof event);
console.log(JSON.stringify(event));//把object转换成字符串类型
if(event.index == 0){
this.arrdatas.splice(index , 1);
}
if(event.index == 1){
//提示框
prompt.showToast({
message:"你取消了删除操作",
duration:6000
})
}
}
});
}
实现效果图:
四、js的数据类型和typeof关键字
查询数据类型可以使用typeof通过console输出,数值型数据在这里是number类型;并且单引号和双引号都属于string类型,不同于Java的字符和字符串类型;true和false还是boolean类型;未定义数据数据类型为undefine;数组为object类型;用[]表示的是数组,用{}表示的是类似于键值对的key-value的object类型,比如“name”:“zhangsan”。
export default {
data: {
a1:10,
a2:"10",
a3:'10',
a4:true,
a6:[], //数组
a7:{} //key-value的object类型 "name":"张三"
},
onInit(){
console.log("a1的值为:"+this.a1);
console.log("a1的数据类型为:"+ typeof this.a1);//number
console.log("a2的值为:"+this.a2);
console.log("a2的数据类型为:"+ typeof this.a2); //string
console.log("a3的值为:"+this.a3);
console.log("a3的数据类型为:"+ typeof this.a3); //string
console.log("a4的值为:"+this.a4);
console.log("a4的数据类型为:"+ typeof this.a4); //boolean
let a5;
console.log("a5的值为:"+a5);
console.log("a5的数据类型为:"+ typeof a5); //undefined
console.log("a6的值为:"+this.a6);
console.log("a6的数据类型为:"+ typeof this.a6); //object
console.log("a7的值为:"+this.a7);
console.log("a7的数据类型为:"+ typeof this.a7); //object
}
}
五、实现对多项数据的分页
1.将整个页面划分为数据显示区和下方的显示更多按钮。
<div class="container">
<div class="contentview">
<block for="{{listdata}}">
<div class="lineview">
<text>{{$item}}</text>
</div>
</block>
</div>
<div class="operatorview" onclick="loadmore" disabled="{{flag}}">
<text>{{loadtext}}</text>
</div>
</div>
2.先设置每一页的数据条数,在js全局变量中设置PAGE_NUM=10,表示每页显示10条数据。再在data数据中创建两个数组,一个用来存放全部数据项,一个用来存放每一页的数据条数。设置初始页码为1。
data: {
arrdatas:[],
listdata:[], //每次存放10条数据
currentpage:1,
loadtext:"加载更多",
flag:false
},
3.在数据初始化onInit中,先把所有数据用循环输出,然后使用使用JavaScript原生API方法:slice(startnum,endnum)将总数据的数组(arrdatas)截取到目标数组中去(listdatas)并展示。Slice的用法是:前一个参数表示截取的开始位置,后一个参数用初始页码1*每页条数10得到前10项。这就是初始界面,展示了全部数据的前10条。
onInit(){
//初始化数据 100条数据
//为什么分页? 1. 100条数据一次性加载,会影响页面渲染的性能
// 2. 用户可能只需要前20条 站在用户的角度
for (let i = 0; i < 50; i++) {
this.arrdatas.push("第"+i+"项");
}
//使用JavaScript原生API方法:slice(startnum,endnum)
//slice截取,并没有删除
this.listdata = this.arrdatas.slice(0,this.currentpage*PAGE_NUM);
console.log(this.listdata);
console.log(this.arrdatas);
},
4.接下来处理loadmore点击事件,每一次点击加载数据时,都将页码currentpage自增1,用以接下来的数据展示。
this.currentpage++;
5.点击加载数据时,设置了一个提示框告诉用户展示到了第几页。
prompt.showToast({
message:"加载的是第"+this.currentpage+"页",
});
6.接下来要实现的就是点击一次,显示下一页。先获取到总的页数,用总的数据条数/每页的条数=页数。但是会出现一个问题,可能总的数据条数/每页条数得到的是个小数,可页码只能是整数。这时可以将原来式子的“/”改为“%”,并使用三元运算符判断是否要取整,使用三元运算符的目的为了提高程序的健壮性。
let maxSize = this.arrdatas.length%PAGE_NUM == 0 ?
this.arrdatas.length/PAGE_NUM : parseInt(this.arrdatas.length/PAGE_NUM)+1;
console.log("总共的页数:"+maxSize);
这里取整还是使用的parseInt(),多出来的数据可以将页码+1来展示。
7.最后判断当前的页码是不是到了最后一页,为了防止提示的页码超出最大页码,当this.currentpage > maxSize时,弹出提示信息“数据已加载完毕”,并且将按钮显示的内容改为“数据已加载完毕”,同时将flag标记改为true,这个标记的作用是让用户点击到最后一页时,不能够再点击数据加载。
if (this.currentpage > maxSize) {
prompt.showToast({
message:"数据已加载完毕"
});
this.loadtext = "数据已加载完毕";
this.flag = true;
}
这里的flag在loadmore点击事件中加了个属性,disable获取到flag的值,如果为初始化的false则点击事件正常运行,如果flag的值变为true,说明页码超过了最大页码,点击事件停止,用户不能再点击加载数据按钮。
<div class="operatorview" onclick="loadmore" disabled="{{flag}}">
<text>{{loadtext}}</text>
</div>
如果currentpage < maxSize时,就正常展示currentpage++后的数据。同样使用slice截取0到currentpage++页的全部数据。
else{
this.listdata = this.arrdatas.slice(0,this.currentpage*PAGE_NUM);
}
这里老师提出了一个需求,就是当前情况下是每点击一次加载数据,从0到当前页的数据会全部展示,现在要想实现只显示当前页的数据。其实只需要将slice的前一个参数改为当前页的第一个数据。例如:this.listdata = this.arrdatas.slice((this.currentpage-1)*PAGE_NUM,this.currentpage*PAGE_NUM);
具体实现效果如下: