使用小程序的 scroll-view 實現(xiàn)無限滾動

先來些小程序的基礎知識開開胃挪圾。主要是熟悉熟悉語法浅萧,沒怎么記住小程序的 API,它的編程套路就運用的不是太熟練哲思,用到的時候在去看文檔洼畅,又浪費了自己的時間,還得從新開頭棚赔,有一種方法就是看自己得筆記帝簇,忘了回來看幾乎一眼秒懂徘郭,多看一眼都是浪費。

一丧肴、計數(shù)器

index.js 文件

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

index.wxml 文件:

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

來看看效果:


計數(shù)器

這個 data 很明顯不是 Vue 得雙向綁定残揉,沒錯就是抄 React 得 state。

bindtap 不能直接函數(shù)調(diào)用使用小括號往里面?zhèn)髦涤蟾。院瘮?shù)調(diào)用傳值我們一般使用自定義屬性冲甘,然后通過 e.target.dataset來獲取,相比之前函數(shù)調(diào)用傳值是麻煩不少 :
index.wxml 文件

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

index.js 文件:

Page({
  add(e){
    console.log(e.target.dataset.id);//10
  }
});
自定義屬性獲取標簽得值

二途样、小程序發(fā)送 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接口調(diào)用結(jié)束的回調(diào)函數(shù)(調(diào)用成功江醇、失敗都會執(zhí)行)
    }
});

玩過 Jquery 得人都懂沒啥講的。過過何暇。陶夜。。

三裆站、 獲取屏幕高度

一共兩個方法条辟,特別像 NodeJs 中得 fs 模塊,提供同步和異步選擇宏胯。獲取手機屏幕高度有什么用羽嫡,通常來講是用來做瀑布流的,我們一般在結(jié)合 scroll-view 使用肩袍,因為 scroll-y 豎直方向的滾動必須提供一個高度杭棵,如果 scroll-view 的高度這時恰好等于屏幕高度,那么整個手機屏幕都是滾動區(qū)域了

  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內(nèi)部訪問
console.log(this.globalData.userInfo);

另一種掛在到全局的方法是:

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

任意一個頁面的 .js 文件里面都能夠直接得到:

App.config.name

五滓侍、去掉導航欄

把導航欄變成通欄的形式:

去掉之前:



app.json 中加入代碼:

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

去掉之后:


六、輪播圖

輪播圖

index.js 文件

Page({

  /**
   * 頁面的初始數(shù)據(jù)
   */
  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 的屬性蚁阳,其中l(wèi)azy-load 上下三屏铃绒,如圖示:橫著表示手機屏。

index.wxss

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

圖片的寬度螺捐,在我設置為百分之百颠悬,圖片的底部沒能完全顯示出來,所以人為的計算了下定血,1個屏幕是750rpx赔癌,圖片寬度就是750rpx。

圖片參數(shù)

圖片要等比澜沟,所以高度是

七灾票、wxs語法

WXS(WeiXin Script)是小程序的一套腳本語言,結(jié)合 WXML茫虽,可以構(gòu)建出頁面的結(jié)構(gòu)刊苍。可以簡單理解為就是 JavaScript濒析。

兩者實在太像了:

  • JavaScript 的代碼是寫在 <script></script> 標簽里面正什,文件后綴名為.js
  • WXS 代碼可以編寫在 wxml 文件中的 <wxs> 標簽內(nèi)号杏,或以 .wxs 為后綴名的文件內(nèi)婴氮。

但是 wxs 又有模塊的概念,每個模塊都有自己獨立的作用域馒索。即在一個模塊里面定義的變量與函數(shù)莹妒,默認為私有的,對其他模塊不可見绰上。

一個模塊要想對外暴露其內(nèi)部的私有變量與函數(shù),只能通過 module.exports 實現(xiàn)渠驼。

更加需要注意的是:

WXS 不依賴于運行時的基礎庫版本蜈块,可以在所有版本的小程序中運行。
WXS 與 JavaScript 是不同的語言迷扇,有自己的語法百揭,并不和 JavaScript 一致。所有ES6的新內(nèi)容一律不能用蜓席,let器一、const、includes厨内、對象k-v一致省略v祈秕、箭頭函數(shù)都不能用渺贤。
WXS 的運行環(huán)境和其他 JavaScript 代碼是隔離的,WXS 中不能調(diào)用其他 JavaScript 文件中定義的函數(shù)请毛,也不能調(diào)用小程序提供的API志鞍。 wxs中定義的函數(shù)必須是純函數(shù)。這個函數(shù)不能改變?nèi)魏瓮獠康闹捣椒拢荒芊祷匦碌淖痔枴?br> WXS 函數(shù)不能作為組件的事件回調(diào)固棚。
由于運行環(huán)境的差異,在 iOS 設備上小程序內(nèi)的 WXS 會比 JavaScript 代碼快 2 ~ 20 倍仙蚜。在 android 設備上二者運行效率無差異此洲。

定義一個 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就是命名空間委粉,所有的函數(shù)必須打點調(diào)用黍翎。
一定記住,在 wxs 中艳丛,函數(shù)只看得見它的參數(shù)匣掸,看不見外部任何量,尤其是 data 里面的變量氮双,要想使用 data 里面的變量碰酝,需要把 data 當做參數(shù)傳進去,而不是在函數(shù)中直接this.data.a戴差。

同時要記住送爸,小程序不能像 Vue 一樣在結(jié)構(gòu)層 wxml 中直接調(diào)用函數(shù),例如:

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

雖然并不報錯暖释,但是也沒任何的效果袭厂。

總結(jié):

小程序得 {{}} 不能調(diào)用除 wxs 之外的一切函數(shù):
小程序禁止:{{add()}}

小程序中不能調(diào)用除 wxs 之外的一切函數(shù):

到此可以模仿一個小程序 軍人體能成績計算器

軍人體能成績計算器*

八、模板(template)

模板(template)
定義模板:使用 name 屬性球匕,作為模板的名字纹磺。

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

調(diào)用模板:使用 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 語法橄杨,來動態(tài)決定具體需要渲染哪個模板。

模板引用當把 template 單獨創(chuàng)立成一個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 豆腐屑的右上角添加文本

小程序在選擇完訂單的時候故慈,一般會出現(xiàn)提醒用戶一共選了多少個板熊。



主要代碼: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',
    })
  },

小程序動態(tài)隱藏底部的 tabbar:

微信小程序可以使用:wx.hideTabBar();來隱藏
uni-app 可以使用 uni.hideTabBar() 來隱藏克婶。

給有右上角的小按鈕增加一個點擊事件來隱藏底部 tabbar 欄筒严。


小程序動態(tài)隱藏底部的 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>關(guān)曉彤</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;
}

實現(xiàn)效果:



接下去就是讓按鈕和滾動區(qū)產(chǎn)生關(guān)系。先看兩個API


scroll-into-view

scroll-with-animation

滾動實現(xiàn):scroll.wxml
<view class="view">
  <view class="btn">
    <button bindtap="changName" data-id="yangmi">楊冪</button>
    <button bindtap="changName" data-id="guanxiaotong">關(guān)曉彤</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">關(guān)曉彤</button>
    <button class="{{who==='jindong'?'cur':''}}" bindtap="changName" data-id="jindong">靳東</button>
    <button class="{{who==='yiyangqianxi'?'cur':''}}" bindtap="changName" data-id="yiyangqianxi">易烊千璽</button>

按鈕上完色的效果:


按鈕上完色

最后一步了红符,上面演示的都是按鈕控制視圖青柄,現(xiàn)在滾動滾動區(qū)的時候按鈕自動變化。先來看一個滾動事件的API說明:


bindscroll

思路到這里就清晰了预侯,我們只需要算出五張楊冪的照片的高度致开,算出來的高度正好映射一個按鈕。現(xiàn)在我們在算一張圖片的高度萎馅。
使用下面的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節(jié)點的上邊界坐標
    res[1].scrollTop // 顯示區(qū)域的豎直滾動位置
    console.log(res);
  })
}

點擊圖片打印出來一個數(shù)據(jù),數(shù)組的第一項里面就有 DOM 元素的寬和高:


最后求出來的值為 137.3249969482422 我們四舍五入取 137 就行校坑。注意如果你不想點擊圖片在計算拣技,可以使用圖片的加載事件 bindload。改寫如下:

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

現(xiàn)在每張圖片高為 137 耍目,一個明星一共有五張,一個明星按鈕對應的高度為 137 * 5 = 685徐绑,數(shù)據(jù)得到了現(xiàn)在就可以碼代碼了邪驮。改寫 scrolling 事件。增加相應的條件判斷傲茄。
scroll.js 的 scrolling 函數(shù):

  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端的樓層導航。

最后的成果圖

代碼優(yōu)化:

  1. 上面 scrolling 函數(shù)里面一直用到了喻粹,this.setData({})蟆融,我們可以使用一個函數(shù)來替代。條件判斷的數(shù)值守呜,萬一改變了去代碼里面改多麻煩型酥,可以考慮用一個數(shù)組來替換,數(shù)組放在本文件的最上面查乒。
  2. 每一個明星弥喉,應該對應一個數(shù)組,用數(shù)組來管理圖片玛迄,這樣在 wxml 里面就能使用 wx:for 了由境,同時 for 循環(huán)應該尋的是 template,template 里面也用 for 循環(huán)蓖议。

完虏杰,2019年12月11日23點29分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市勒虾,隨后出現(xiàn)的幾起案子纺阔,更是在濱河造成了極大的恐慌,老刑警劉巖从撼,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件州弟,死亡現(xiàn)場離奇詭異,居然都是意外死亡低零,警方通過查閱死者的電腦和手機婆翔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掏婶,“玉大人啃奴,你說我怎么就攤上這事⌒弁祝” “怎么了最蕾?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長老厌。 經(jīng)常有香客問我瘟则,道長,這世上最難降的妖魔是什么枝秤? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任醋拧,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丹壕。我一直安慰自己庆械,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布菌赖。 她就那樣靜靜地躺著缭乘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琉用。 梳的紋絲不亂的頭發(fā)上堕绩,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音辕羽,去河邊找鬼逛尚。 笑死,一個胖子當著我的面吹牛刁愿,可吹牛的內(nèi)容都是我干的绰寞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼铣口,長吁一口氣:“原來是場噩夢啊……” “哼滤钱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脑题,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤件缸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叔遂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體他炊,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年已艰,在試婚紗的時候發(fā)現(xiàn)自己被綠了痊末。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡哩掺,死狀恐怖凿叠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嚼吞,我是刑警寧澤盒件,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站舱禽,受9級特大地震影響炒刁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜誊稚,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一切心、第九天 我趴在偏房一處隱蔽的房頂上張望飒筑。 院中可真熱鬧片吊,春花似錦绽昏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爷贫,卻和暖如春认然,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漫萄。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工卷员, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腾务。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓毕骡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親岩瘦。 傳聞我的和親對象是個殘疾皇子未巫,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容