0
点赞
收藏
分享

微信扫一扫

使用小程序的 scroll-view 实现无限滚动

先来些小程序的基础知识开开胃。主要是熟悉熟悉语法,没怎么记住小程序的 API,它的编程套路就运用的不是太熟练,用到的时候在去看文档,又浪费了自己的时间,还得从新开头,有一种方法就是看自己得笔记,忘了回来看几乎一眼秒懂,多看一眼都是浪费。

一、计数器

index.js 文件

Page({
data: {
a : 0
},
add(){
this.setData({
a : this.data.a + 1
})
}
});

index.wxml 文件:

{{a}}
<button type="primary" bindtap="add">按我加一</button>

来看看效果:



这个 data 很明显不是 Vue 得双向绑定,没错就是抄 React 得 state。

bindtap 不能直接函数调用使用小括号往里面传值,所以函数调用传值我们一般使用自定义属性,然后通过 e.target.dataset来获取,相比之前函数调用传值是麻烦不少 :
index.wxml 文件

<button type="primary" bindtap="add" data-id="10">获取ID</button>

index.js 文件:

Page({
add(e){
console.log(e.target.dataset.id);//10
}
});

二、小程序发送 Ajax

wx.request({
url: 'https://www.meimichao.com/bee/uploadHandler',
data: {"city":"123"},
method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
//header: {"Content-Type":"application/x-www-form-urlencoded"}, // 设置请求的 header
success: function(res){
console.log(JSON.stringify(res));
},
fail: function(res) {
console.log(JSON.stringify(res));
},
complete: function() {
// complete接口调用结束的回调函数(调用成功、失败都会执行)
}
});

玩过 Jquery 得人都懂没啥讲的。过过。。。

三、 获取屏幕高度

一共两个方法,特别像 NodeJs 中得 fs 模块,提供同步和异步选择。获取手机屏幕高度有什么用,通常来讲是用来做瀑布流的,我们一般在结合 scroll-view 使用,因为 scroll-y 竖直方向的滚动必须提供一个高度,如果 scroll-view 的高度这时恰好等于屏幕高度,那么整个手机屏幕都是滚动区域了

  1. 异步方法
wx.getSystemInfo({
success (res) {
console.log(res.windowHeight)
}
})

2.同步方法

try {
const res = wx.getSystemInfoSync()
console.log(res.windowHeight)
} catch (e) {
// Do something when catch error
}

四、全局变量

一些通用的变量放置在这里,例如:baseURL
app.js 文件夹里面进行定义,一般来讲字段叫做 globalData(你叫a,b,c,d...都行) 而且 global 都是当作对象来使用,例如:

App({
globalData: {
userInfo: 'Condor Hero'
}
});

任意一个页面的 .js 文件里面都能够通过 getApp() 得到:

const app = getApp();
console.log(app.globalData.userInfo)//Condor Hero
//app.js内部访问
console.log(this.globalData.userInfo);

另一种挂在到全局的方法是:

App.config = {name:'Condor Hero'};
App({});

任意一个页面的 .js 文件里面都能够直接得到:

App.config.name

五、去掉导航栏

把导航栏变成通栏的形式:

去掉之前:



app.json 中加入代码:

"window": {
"navigationStyle": "custom"
}

去掉之后:


六、轮播图

index.js 文件

Page({

/**
* 页面的初始数据
*/
data: {
banners: [
{
'pic': 'b1.jpg'
},
{
'pic': 'b2.jpg'
},
{
'pic': 'b3.jpg'
},
{
'pic': 'b4.jpg'
}
],
indicatorDots: true,//是否显示面板指示
vertical: false,
autoplay: true,
interval: 2000,//滑动方向是否为纵向
duration: 500
}
})

index.wxml

<view>
<view class="swiper">
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
<block wx:for="{{banners}}" wx:key="{{index}}">
<swiper-item>
<view class="swiper-item">
<image src="/images/{{item.pic}}"></image>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>

注意小程序图片标签是 image 不是 img,可以当作单标签使用也可以当作双标签使用,src 支持绝对路径和相对路径,当为绝对路径的时候, 一定要加/前缀,小程序的索引路径一般使用绝对路径,因为如果你要想从项目目录去找图片的 ../../ 好几次把人都给弄乱了,另外当你书写路径 /images/logo.png 默认直接去和 app.js 文件同级的 images 里面去查找,特别像 Vue 脚手架默认 @/assets/logo.png 中 @ 表示 src 目录一个道理。还有就是小程序没有<div>、<ul>、<h1>等所有标签。只有<view>标签。
image 的属性,其中lazy-load 上下三屏,如图示:横着表示手机屏。

index.wxss

.swiper-item image{
width: 750rpx;
height: 448rpx;
}

图片的宽度,在我设置为百分之百,图片的底部没能完全显示出来,所以人为的计算了下,1个屏幕是750rpx,图片宽度就是750rpx。

图片要等比,所以高度是

七、wxs语法

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

两者实在太像了:

  • JavaScript 的代码是写在 <script></script> 标签里面,文件后缀名为.js
  • WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内,或以 .wxs 为后缀名的文件内。

但是 wxs 又有模块的概念,每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。

一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。

更加需要注意的是:

定义一个 tool.wxs 文件:

function mianji(n) {
return n * n;
}
module.exports = {
mianji: mianji
}

wxml页面中,这样引入刚刚的代码片段:

<view>
<wxs src="./tool.wxs" module="tool"></wxs>
<view>
{{tool.mianji(3)}}
</view>
</view>

module就是命名空间,所有的函数必须打点调用。
一定记住,在 wxs 中,函数只看得见它的参数,看不见外部任何量,尤其是 data 里面的变量,要想使用 data 里面的变量,需要把 data 当做参数传进去,而不是在函数中直接this.data.a

同时要记住,小程序不能像 Vue 一样在结构层 wxml 中直接调用函数,例如:

<view>{{add()}}</view>

虽然并不报错,但是也没任何的效果。

总结:

小程序中不能调用除 wxs 之外的一切函数:

到此可以模仿一个小程序 军人体能成绩计算器

八、模板(template)

模板(template)
定义模板:使用 name 属性,作为模板的名字。

    <template name="moban">
<view>
我喜欢{{dongwu}}
</view>
</template>

调用模板:使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入

    <view class="content">
<scroll-view height="500px">
<template is="moban" data="{{dongwu:'兔子'}}"></template>
<template is="moban" data="{{dongwu:'河马'}}"></template>
</scroll-view>
</view>

is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板。

模板引用当把 template 单独创立成一个WXML。提供两种文件引用方式 import 和 include。

<import src="tool.wxml"/>
<include src="tool.wxml"/>
  • import 的作用域
    如:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的template,但是C不能使用A定义的template
  • 相当于是把模板拷贝到 include 位置

九、tabBar 豆腐屑的右上角添加文本

小程序在选择完订单的时候,一般会出现提醒用户一共选了多少个。



主要代码:app.js 文件

  "tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "/images/icon1.png",
"text": "首页"
},
{
"pagePath": "pages/scroll/scroll",
"iconPath": "/images/icon2.png",
"text": "日志"
}
]
},

设置 tabbar 角标为:

  • index:tabBar 的哪一项,从左边算起,第一个为零
  • text:显示的文本,超过 4 个字符则显示成...
  onLoad: function (options) {
wx.setTabBarBadge({
index: 1,
text: '1',
})
},

小程序动态隐藏底部的 tabbar:

微信小程序可以使用:wx.hideTabBar();来隐藏
uni-app 可以使用 uni.hideTabBar() 来隐藏。

给有右上角的小按钮增加一个点击事件来隐藏底部 tabbar 栏。


十、scroll-view 无穷滚动 (infinite scroll)

终于来到无穷滚动了,这个常用来做无限下拉滚动效果,利用使用竖向滚动时,必须要给 scroll-view 一个固定高度,一般为屏幕高(wh)。下面这个东西就是利用这个标签做的,你一定见过这种效果:


项目目录:


看看小程序的一个目录,你仔细想想是不是就是 Vue 或 React 的一个组件啊。还有一个放图片的目录:


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


我放图片的时候如果使用 image 标签直接显示是这样的:


使用 cover-image 后:


不用讲了吧,以后图片标签就是用 cover-image 标签。

基本布局:
scroll.wxml

<view class="view">
<view class="btn">
<button>杨幂</button>
<button>关晓彤</button>
<button>靳东</button>
<button>易烊千玺</button>
</view>
<scroll-view
style="height: 900rpx;border: 2px solid #ff66cc;"
scroll-y="true"
class="scroll"
>

<view id="yangmi">
<view class="pic">
<cover-image src="/images/yangmi/1.jpg"></cover-image>
<cover-image src="/images/yangmi/2.jpg"></cover-image>
<cover-image src="/images/yangmi/3.jpg"></cover-image>
<cover-image src="/images/yangmi/4.jpg"></cover-image>
<cover-image src="/images/yangmi/5.jpg"></cover-image>
</view>
</view>
<view id="guanxiaotong">
<view class="pic">
<cover-image src="/images/guanxiaotong/1.jpg"></cover-image>
<cover-image src="/images/guanxiaotong/2.jpg"></cover-image>
<cover-image src="/images/guanxiaotong/3.jpg"></cover-image>
<cover-image src="/images/guanxiaotong/4.jpg"></cover-image>
<cover-image src="/images/guanxiaotong/5.jpg"></cover-image>
</view>
</view>
<view id="jindong">
<view class="pic">
<cover-image src="/images/jindong/1.jpg"></cover-image>
<cover-image src="/images/jindong/2.jpg"></cover-image>
<cover-image src="/images/jindong/3.jpg"></cover-image>
<cover-image src="/images/jindong/4.jpg"></cover-image>
<cover-image src="/images/jindong/5.jpg"></cover-image>
</view>
</view>
<view id="yiyangqianxi">
<view class="pic">
<cover-image src="/images/yiyangqianxi/1.jpg"></cover-image>
<cover-image src="/images/yiyangqianxi/2.jpg"></cover-image>
<cover-image src="/images/yiyangqianxi/3.jpg"></cover-image>
<cover-image src="/images/yiyangqianxi/4.jpg"></cover-image>
<cover-image src="/images/yiyangqianxi/5.jpg"></cover-image>
</view>
</view>
</scroll-view>
</view>

scroll.wxss

.view{
display: flex;
}
.scroll{
flex:2;
}
.btn{
flex:1;
}
.btn>button{
height: 20rpx;
width: 110px;
font-size: 14px;
margin: 20rpx 0;
border: 1px solid orange;
}

实现效果:



接下去就是让按钮和滚动区产生关系。先看两个API




滚动实现:scroll.wxml
<view class="view">
<view class="btn">
<button bindtap="changName" data-id="yangmi">杨幂</button>
<button bindtap="changName" data-id="guanxiaotong">关晓彤</button>
<button bindtap="changName" data-id="jindong">靳东</button>
<button bindtap="changName" data-id="yiyangqianxi">易烊千玺</button>
</view>
<scroll-view
style="height: 900rpx;border: 2px solid #ff66cc;"
scroll-y="true"
class="scroll"
scroll-into-view="{{who}}"
scroll-with-animation="true"
>
...
</scroll-view>
</view>

scroll.js

Page({
data: {
who: "yangmi"
},
changName(e){
this.setData({
who:e.target.dataset.id
})
}
});

给按钮上色标记位置:
scroll.wxss 加上以下代码:

button.cur{
background-color: red;
}

同时改写 scroll.wxml 按钮位置代码:

    <button class="{{who==='yangmi'?'cur':''}}" bindtap="changName" data-id="yangmi">杨幂</button>
<button class="{{who==='guanxiaotong'?'cur':''}}" bindtap="changName" data-id="guanxiaotong">关晓彤</button>
<button class="{{who==='jindong'?'cur':''}}" bindtap="changName" data-id="jindong">靳东</button>
<button class="{{who==='yiyangqianxi'?'cur':''}}" bindtap="changName" data-id="yiyangqianxi">易烊千玺</button>

按钮上完色的效果:



最后一步了,上面演示的都是按钮控制视图,现在滚动滚动区的时候按钮自动变化。先来看一个滚动事件的API说明:



思路到这里就清晰了,我们只需要算出五张杨幂的照片的高度,算出来的高度正好映射一个按钮。现在我们在算一张图片的高度。
使用下面的API:


scroll.wxml 文件给第一张杨幂的照片添加 一个 id 和 一个点击事件。

<cover-image bindtap="computedSize" id="imgHeight" src="/images/yangmi/1.jpg"></cover-image>

同时 scroll.js 文件添加对应的事件:

computedSize(){
const query = wx.createSelectorQuery();
query.select('#imgHeight').boundingClientRect();
query.selectViewport().scrollOffset();
query.exec(function (res) {
res[0].top // #imgHeight节点的上边界坐标
res[1].scrollTop // 显示区域的竖直滚动位置
console.log(res);
})
}

点击图片打印出来一个数据,数组的第一项里面就有 DOM 元素的宽和高:


最后求出来的值为 137.3249969482422 我们四舍五入取 137 就行。注意如果你不想点击图片在计算,可以使用图片的加载事件 bindload。改写如下:

<cover-image bindload="computedSize" id="imgHeight" src="/images/yangmi/1.jpg"></cover-image>

现在每张图片高为 137 ,一个明星一共有五张,一个明星按钮对应的高度为 137 * 5 = 685,数据得到了现在就可以码代码了。改写 scrolling 事件。增加相应的条件判断。
scroll.js 的 scrolling 函数:

  scrolling(e){
const { scrollTop } = e.detail;
if (scrollTop < 685 && this.data.who !== 'yangmi'){
this.setData({
who:'yangmi'
});
} else if (scrollTop > 685 && scrollTop < 1370 && this.data.who !== 'guanxiaotong'){
this.setData({
who: 'guanxiaotong'
});
} else if (scrollTop > 1370 && scrollTop < 2055 && this.data.who !== 'jindong') {
this.setData({
who: 'jindong'
});
} else if (scrollTop > 2055 && scrollTop < 2740 && this.data.who !== 'yiyangqianxi') {
this.setData({
who: 'yiyangqianxi'
});
}
}

修改完我们要的效果就做好了,一个小程序商城导航,效果如下:效果类似web端的楼层导航。


代码优化:

  1. 上面 scrolling 函数里面一直用到了,this.setData({}),我们可以使用一个函数来替代。条件判断的数值,万一改变了去代码里面改多麻烦,可以考虑用一个数组来替换,数组放在本文件的最上面。
  2. 每一个明星,应该对应一个数组,用数组来管理图片,这样在 wxml 里面就能使用 wx:for 了,同时 for 循环应该寻的是 template,template 里面也用 for 循环。

完,2019年12月11日23点29分

举报

相关推荐

0 条评论