云開(kāi)發(fā) 頁(yè)面渲染

2020-07-20 11:21 更新

在數(shù)據(jù)綁定章節(jié),我們已經(jīng)掌握如何把data里面的數(shù)據(jù)渲染到頁(yè)面,這一部分我們會(huì)介紹如何通過(guò)點(diǎn)擊組件綁定的事件處理函數(shù)來(lái)修改data里面的數(shù)據(jù),如何把事件處理函數(shù)獲取到的數(shù)據(jù)打印到頁(yè)面。

將變量值渲染到頁(yè)面

還記得我們之前在控制臺(tái)打印的Date對(duì)象、Math對(duì)象、字符串String對(duì)象以及常量么?在第一節(jié)里我們把這些對(duì)象賦值給了一個(gè)變量,然后通過(guò)控制臺(tái)可以把這些值給console.log()打印出來(lái),那這些值可不可以渲染到小程序的頁(yè)面上呢?答案是肯定的。

將變量值渲染到頁(yè)面

使用開(kāi)發(fā)者工具新建一個(gè)頁(yè)面比如data,然后在data.js的Page({})函數(shù)的前面,也就是不寫(xiě)在Page函數(shù)里面,寫(xiě)在data.js的第1行輸入以下代碼:

  1. let lesson = "云開(kāi)發(fā)技術(shù)訓(xùn)練營(yíng)";
  2. let enname = "CloudBase Camp";
  3. let x = 3, y = 4, z = 5.001, a = -3, b = -4, c = -5;
  4. let now = new Date();

注意上面這些是JavaScript函數(shù)的語(yǔ)句,所以用的是分號(hào);分隔,這個(gè)不要和之前的逗號(hào)分隔給弄混了哦。如果語(yǔ)句是換行的,后面的分號(hào);也可以不必寫(xiě)。

然后在data里面添加如下數(shù)據(jù)(注意沒(méi)有雙引號(hào),單雙引號(hào)里的是字符串)

  1. data: {
  2. charat: lesson.charAt(4),
  3. concat: enname.concat(lesson),
  4. uppercase:enname.toUpperCase(),
  5. abs:Math.abs(b),
  6. pow: Math.pow(x, y),
  7. sign:Math.sign(a),
  8. now:now,
  9. fullyear:now.getFullYear(),
  10. date:now.getDate(),
  11. day: now.getDay(),
  12. hours: now.getHours(),
  13. minutes: now.getMinutes(),
  14. seconds: now.getSeconds(),
  15. time: now.getTime()
  16. },

在data.wxml里輸入以下代碼:

  1. <view>"云開(kāi)發(fā)技術(shù)訓(xùn)練營(yíng)"第5個(gè)字符 {{charat}}</view>
  2. <view>兩個(gè)字符串連接后的結(jié)果:{{concat}}</view>
  3. <view>CloudBase Camp字母大寫(xiě):{{uppercase}}</view>
  4. <view>b的絕對(duì)值:{{abs}}</view>
  5. <view>x的y次冪:{{pow}}</view>
  6. <view>返回a是正還是負(fù):{{sign}}</view>
  7. <view>now對(duì)象:{{now}}</view>
  8. <view>{{fullyear}}年</view>
  9. <view>{{date}}日</view>
  10. <view>星期{{day}}</view>
  11. <view>{{hours}}時(shí)</view>
  12. <view>{{minutes}}分</view>
  13. <view>{{seconds}}秒</view>
  14. <view>1970年1月1日至今的毫秒數(shù):{{time}}</view>

因?yàn)閐ata是一個(gè)對(duì)象Object,我們可以通過(guò)冒號(hào):的方式將變量值賦值給data里的各個(gè)屬性,而在數(shù)據(jù)綁定章節(jié),這些數(shù)據(jù)是可以直接渲染到小程序的頁(yè)面的。

toString()方法

我們發(fā)現(xiàn){{now}}渲染的結(jié)果是一個(gè)對(duì)象[object Object],而并沒(méi)有顯示出字符串文本,這個(gè)時(shí)候就需要用到對(duì)象的toString()方法,得到對(duì)象的字符串。將data里now的賦值改為如下:

  1. now:now.toString(),

技術(shù)文檔:toString()方法

響應(yīng)的數(shù)據(jù)綁定

邏輯層js文件里的data數(shù)據(jù),無(wú)論是基礎(chǔ)的字符串、數(shù)組、對(duì)象等,還是通過(guò)變量給賦的值,都可以渲染到頁(yè)面。不僅如此,只要對(duì)邏輯層data里的數(shù)據(jù)進(jìn)行修改,視圖層也會(huì)做相應(yīng)的更新,我們稱(chēng)之為響應(yīng)的數(shù)據(jù)綁定,而這是通過(guò)Page的setData()方法來(lái)實(shí)現(xiàn)的。

使用開(kāi)發(fā)者工具在data.wxml里輸入:

  1. <view style="background-color:{{bgcolor}};width:400rpx;height:300rpx;"></view>
  2. <button bindtap="redTap">讓背景變紅</button>
  3. <button bindtap="yellowTap">讓背景變黃</button>

然后在data.js里添加一個(gè)數(shù)據(jù)

  1. bgcolor:"#000000",

然后在js里添加兩個(gè)button綁定的事件處理函數(shù)redTap和yellowTap:

  1. redTap:function(){
  2. this.setData({
  3. bgcolor: "#cd584a"
  4. })
  5. },
  6. yellowTap:function(){
  7. this.setData({
  8. bgcolor: "#f8ce5f"
  9. })
  10. },

點(diǎn)擊button,原來(lái)view組件的背景顏色由黑色變成了其他顏色,這是因?yàn)辄c(diǎn)擊組件觸發(fā)事件處理函數(shù),調(diào)用了Page的setData()方法修改了data里與之相應(yīng)的屬性的值(重復(fù)賦值就是修改),bgcolor由原來(lái)的”#000000″,變成了其他數(shù)據(jù)。

小任務(wù):通過(guò)以往的學(xué)習(xí)我們了解到無(wú)論是組件的樣式,圖片、鏈接的路徑,數(shù)組、對(duì)象里的數(shù)據(jù),他們都是可以進(jìn)行數(shù)據(jù)分離寫(xiě)到data里面的,這也就意味著,我們通過(guò)點(diǎn)擊事件改變data里面的數(shù)據(jù)可以達(dá)到很多意想不到的效果,請(qǐng)發(fā)揮你的想象力做一些有意思的案例出來(lái)。

響應(yīng)的布爾操作

在前面我們已經(jīng)了解到,有些組件的私有屬性的數(shù)據(jù)類(lèi)型為Boolean布爾值,比如視頻、Swiper輪播組件是否自動(dòng)播放、是否輪播,視頻組件是否顯示播放按鈕等等,這些我們都可以使用setData將true改為false,false改為true來(lái)達(dá)到控制的目的。

在交互方面,響應(yīng)的布爾操作可以用于單一屬性true與false的切換,比如顯示與隱藏、展開(kāi)與折疊、聚焦與失焦、選中與不選中。

我們來(lái)看一個(gè)案例,使用開(kāi)發(fā)者工具在data.wxml里輸入以下代碼:

  1. <video id="daxueVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" rel="external nofollow" autoplay loop muted="{{muted}}" initial-time="100" controls event-model="bubble">
  2. </video>
  3. <button bindtap="changeMuted">靜音和取消靜音</button>

然后給在data.js的data里新增

  1. muted: true,

然后添加changeMuted事件處理函數(shù)

  1. changeMuted: function (e) {
  2. this.setData({
  3. muted: !this.data.muted
  4. })
  5. },

在開(kāi)發(fā)者工具的模擬器里點(diǎn)擊按鈕,我們發(fā)現(xiàn)靜音和取消靜音都是這個(gè)按鈕。這里的感嘆號(hào) !是邏輯非的意思,可以理解為not。

this.setData和 this.data都用到了一個(gè)關(guān)鍵字 this。 this和中文里的“這個(gè)的”有類(lèi)似的指代作用,在方法中, this 指代該方法所屬的對(duì)象,比如這里的是Page對(duì)象, this.data就是指Page函數(shù)對(duì)象里的data對(duì)象。

響應(yīng)的數(shù)組操作

結(jié)合點(diǎn)擊事件以及數(shù)組操作的知識(shí),我們?cè)賮?lái)看下面這個(gè)案例,了解如何通過(guò)點(diǎn)擊按鈕新增數(shù)組里的數(shù)據(jù)和刪除數(shù)組里的數(shù)據(jù)。

使用開(kāi)發(fā)者工具在data.wxml里輸入以下代碼,注意這里視圖層只有一個(gè){{text}},也就是說(shuō)我們之后會(huì)把所有的數(shù)據(jù)都賦值給data里的text。

  1. <view>{{text}}</view>
  2. <button bindtap="addLine">新增一行</button>
  3. <button bindtap="removeLine">刪掉最后一行</button>

然后在data.js的Page()之前聲明變量,這里聲明extraLine為一個(gè)空數(shù)組,我們之后會(huì)往這個(gè)數(shù)組里添加和刪除數(shù)據(jù)。

  1. let initData = '只有一行原始數(shù)據(jù)'
  2. let extraLine = [];

然后再在Page的data里添加一條數(shù)據(jù),

  1. text: initData,

我們先來(lái)看沒(méi)有事件處理函數(shù)時(shí),數(shù)據(jù)渲染的邏輯,首先我們把initData變量值賦值給text,這時(shí)渲染的結(jié)果只有initData里的數(shù)據(jù),所以頁(yè)面顯示的是“只有一行原始數(shù)據(jù)”,而extraLine和text沒(méi)有什么關(guān)系。

我們?cè)賮?lái)在Page里添加addLine和removeLine的事件處理函數(shù):

  1. addLine: function (e) {
  2. extraLine.push('新增的內(nèi)容')
  3. this.setData({
  4. text: initData + '\n' + extraLine.join('\n')
  5. })
  6. },
  7. removeLine: function (e) {
  8. if (extraLine.length > 0) {
  9. extraLine.pop()
  10. this.setData({
  11. text: initData + '\n' + extraLine.join('\n')
  12. })
  13. }
  14. },

首先回顧一下之前的數(shù)組操作知識(shí),push為往數(shù)組的末尾新增數(shù)據(jù),而pop則刪除數(shù)組末尾一行的數(shù)據(jù),join為數(shù)組數(shù)據(jù)之前的連接符。

點(diǎn)擊按鈕新增一行,觸發(fā)綁定的事件處理函數(shù)addLine,首先會(huì)執(zhí)行extraLine數(shù)組新增一條數(shù)據(jù)“新增的內(nèi)容”,但是這時(shí)extraLine和text還沒(méi)有關(guān)系,這時(shí)在setData()函數(shù)里將initData和extraLine進(jìn)行拼接(注意extraLine本來(lái)是一個(gè)數(shù)組,但是調(diào)用join方法后返回的是數(shù)組的值拼接好的字符串)。點(diǎn)擊按鈕刪除最后一行,會(huì)先刪除extraLine數(shù)組里最后一行的數(shù)據(jù)。

小任務(wù):新增內(nèi)容過(guò)于單一,我們可以給它后面添加一個(gè)隨機(jī)數(shù),將 extraLine.push('新增的內(nèi)容')改成 extraLine.push('新增的內(nèi)容'+Math.random()),再來(lái)看看新增數(shù)據(jù)的效果,關(guān)于Math.random()大家可以自行去MDN查閱。大家也可以把拼接的連接符由 \n換成其他字符。

函數(shù)與調(diào)用函數(shù)

函數(shù)的作用,可以寫(xiě)一次代碼,然后反復(fù)地重用這個(gè)代碼。JavaScript的函數(shù)本身也是對(duì)象,因此可以把函數(shù)賦值給變量,或者作為參數(shù)傳遞給其他函數(shù)。

函數(shù)的定義和結(jié)構(gòu)

我們可以使用function關(guān)鍵詞來(lái)定義一個(gè)函數(shù),括號(hào)()里為函數(shù)的參數(shù),參數(shù)可以有很多個(gè),使用逗號(hào),隔開(kāi);函數(shù)要執(zhí)行的代碼(語(yǔ)句)使用大括號(hào){}包?。?/p>

  1. function 函數(shù)(參數(shù) 1, 參數(shù) 2, 參數(shù) 3) {
  2. 代碼塊內(nèi)要執(zhí)行的語(yǔ)句
  3. }

不帶參數(shù)的函數(shù)

比如,我們使用開(kāi)發(fā)者工具在data.js的Page()函數(shù)前,添加如下代碼:

  1. function greet() {
  2. console.log("你好,歡迎來(lái)到云開(kāi)發(fā)訓(xùn)練營(yíng)");
  3. };
  4. greet(); //調(diào)用greet()函數(shù)

保存之后,我們可以在控制臺(tái)看到函數(shù)打印的字符串。定義一個(gè)函數(shù)并不會(huì)自動(dòng)的執(zhí)行它。定義了函數(shù)僅僅是賦予函數(shù)以名稱(chēng)并明確函數(shù)被調(diào)用時(shí)該做些什么。調(diào)用函數(shù)才會(huì)以給定的參數(shù)真正執(zhí)行這些動(dòng)作。greet()函數(shù)沒(méi)有參數(shù),調(diào)用函數(shù)時(shí),直接寫(xiě)函數(shù)名+括號(hào)即可。

只有一個(gè)參數(shù)的函數(shù)

下面定義了一個(gè)簡(jiǎn)單的平方函數(shù)square(),square為函數(shù)名,number為函數(shù)的參數(shù)(名稱(chēng)可以自定義),使用return語(yǔ)句確定函數(shù)的返回值。我們繼續(xù)在data.js的Page()函數(shù)前,輸入以下代碼:

  1. function square(number) {
  2. return number * number;
  3. };
  4. square(5);

square(5),就是把5賦值給變量number,然后執(zhí)行numbernumber,也就是55,然后返回return這個(gè)值。

這里的number被稱(chēng)之為形參,而5被稱(chēng)之為實(shí)參。大家可以結(jié)合案例就能大致了解形參和實(shí)參的意思。

  • 形參是在定義函數(shù)時(shí)使用的參數(shù),目的是用來(lái)接收調(diào)用該函數(shù)時(shí)傳進(jìn)來(lái)的實(shí)際參數(shù)。

  • 實(shí)參是在調(diào)用時(shí)傳遞給函數(shù)的參數(shù)

JavaScript允許傳入任意個(gè)參數(shù)而不影響調(diào)用,因此傳入的參數(shù)可以比定義的參數(shù)多,但是不能少。也就是說(shuō)實(shí)參的數(shù)量可以多于形參但是不能少于形參。

對(duì)象的方法

在小程序里我們會(huì)經(jīng)常將一個(gè)匿名函數(shù)賦值給對(duì)象的一個(gè)屬性,而這個(gè)屬性我們可以稱(chēng)之為對(duì)象的方法。

匿名函數(shù)

函數(shù)聲明function在語(yǔ)法上是一個(gè)語(yǔ)句,但函數(shù)也可以由函數(shù)表達(dá)式創(chuàng)建,這樣的函數(shù)沒(méi)有函數(shù)名稱(chēng)(匿名)。

使用開(kāi)發(fā)者工具在data.js的Page()函數(shù)前,輸入以下代碼:

  1. let square = function(number) {
  2. return number * number
  3. };
  4. console.log(square(4))//使用console.log()輸出變量square

執(zhí)行后,可以在控制臺(tái)看到輸出的結(jié)果為16。上面這個(gè)function函數(shù)沒(méi)有函數(shù)名,相當(dāng)于是把函數(shù)的返回值賦值給了變量square。

箭頭函數(shù)

為什么叫箭頭函數(shù)(Arrow Function),因?yàn)樗x一個(gè)函數(shù)用的就是一個(gè)箭頭=>,我們來(lái)看兩個(gè)例子,在data.js的Page()函數(shù)前輸入以下代碼:

  1. const multiply = (x, y) => {
  2. return x * y;
  3. }
  4. const sum= (x, y) => x + y;//連{}和return語(yǔ)句都可以省掉
  5. console.log(multiply(20, 4));
  6. console.log(sum(20, 4));

在控制臺(tái)我們可以看到箭頭函數(shù)打印的結(jié)果。箭頭函數(shù)相當(dāng)于匿名函數(shù),它沒(méi)有函數(shù)名,而且也簡(jiǎn)化了函數(shù)定義。箭頭函數(shù)可以只包含一個(gè)表達(dá)式,甚至連{ … }和return都可以省略掉。大家可以先只需要了解這個(gè)寫(xiě)法就可以了,以后碰到不至于比較迷惑,見(jiàn)多了也試著嘗試多寫(xiě)一下。

調(diào)用對(duì)象的方法

可以使用點(diǎn)表示法來(lái)調(diào)用對(duì)象的方法,這個(gè)和訪問(wèn)對(duì)象的屬性沒(méi)有區(qū)別。而調(diào)用對(duì)象的方法和調(diào)用一個(gè)函數(shù)也是大同小異。

調(diào)用對(duì)象的方法我們?cè)谇懊婢鸵呀?jīng)接觸過(guò)大量的案例了,在前面我們已經(jīng)說(shuō)過(guò),wx是小程序的全局對(duì)象,而在第一節(jié)我們打印的很多API,就是調(diào)用了wx對(duì)象里的方法。

JavaScript函數(shù)的寫(xiě)法

在點(diǎn)擊事件章節(jié)里,我們創(chuàng)建的事件點(diǎn)擊處理函數(shù)的寫(xiě)法如下:

  1. scrollToPosition() {
  2. },

而在這一節(jié)我們創(chuàng)建的事件點(diǎn)擊函數(shù)的寫(xiě)法為:

  1. yellowTap:function(){
  2. },

這兩種寫(xiě)法都是可以執(zhí)行的,大家可以把這兩種寫(xiě)法互相修改一下試試看~

currentTarget事件對(duì)象

在前面的列表渲染里,我們知道點(diǎn)擊電影列表里的某一部電影,要進(jìn)行頁(yè)面跳轉(zhuǎn)顯示該電影的詳情,我們需要給該電影創(chuàng)建一個(gè)頁(yè)面,那如果要顯示數(shù)千部的電影的詳情,一一創(chuàng)建電影詳情頁(yè)顯然不合適,畢竟所有電影的詳情頁(yè)都是同一一個(gè)結(jié)構(gòu),有沒(méi)有辦法所有電影詳情都共用一個(gè)頁(yè)面,但是根據(jù)點(diǎn)擊的鏈接的不同,渲染相應(yīng)的數(shù)據(jù)?答案是肯定的,要解決這個(gè)問(wèn)題,首先我們要了解鏈接組件的點(diǎn)擊信息。

當(dāng)點(diǎn)擊組件觸發(fā)事件時(shí),邏輯層綁定該事件的處理函數(shù)會(huì)收到一個(gè)事件對(duì)象,通過(guò) event 對(duì)象可以獲取事件觸發(fā)時(shí)候的一些信息,比如時(shí)間戳、 detail 以及當(dāng)前組件的一些屬性值集合,尤其是事件源組件的id。

currentTarget是事件對(duì)象的一個(gè)屬性,表示的是事件綁定的當(dāng)前組件。使用開(kāi)發(fā)者工具在data.wxml里輸入以下代碼

  1. <view class="weui-navbar">
  2. <block wx:for="{{tabs}}" wx:key="index">
  3. <view id="{{index}}" class="weui-navbar__item {{activeIndex == index ? 'weui-bar__item_on' : ''}}" bindtap="tabClick">
  4. <view class="weui-navbar__title">{{item}}</view>
  5. </view>
  6. </block>
  7. </view>
  8. <view class="weui-tab__panel">
  9. <view hidden="{{activeIndex != 0}}">帝都</view>
  10. <view hidden="{{activeIndex != 1}}">魔都</view>
  11. <view hidden="{{activeIndex != 2}}">妖都</view>
  12. <view hidden="{{activeIndex != 3}}">漁村</view>
  13. </view>

然后再往data.js的data里添加以下數(shù)據(jù):

  1. tabs: ["北京", "上海", "廣州", "深圳"],
  2. activeIndex:0,

然后再添加事件處理函數(shù)tabClick。

  1. tabClick: function (e) {
  2. console.log(e)
  3. this.setData({
  4. activeIndex: e.currentTarget.id
  5. });
  6. },

編譯之后在模擬器里預(yù)覽。當(dāng)我們點(diǎn)擊上面的tab時(shí),觸發(fā)tabClick事件處理函數(shù),這時(shí)候事件處理函數(shù)會(huì)收到一個(gè)事件對(duì)象e,我們可以看一下控制臺(tái)打印的e對(duì)象的內(nèi)容,關(guān)于e對(duì)象具體屬性的解釋可以看技術(shù)文檔。

技術(shù)文檔:事件對(duì)象

currentTarget就是事件對(duì)象的一個(gè)屬性,我們可以使用點(diǎn)表示法獲取到點(diǎn)擊的組件的Id,并將其賦值給activeIndex,所謂active就是激活的意思,也就是我們點(diǎn)擊哪個(gè)tab,哪個(gè)tab就激活。

  • 當(dāng)點(diǎn)擊的id為0,也就是第一個(gè)tab時(shí),activeIndex的值被事件處理函數(shù)修改為0;

  • activeIndex == index相同的tab,也就是激活的tab就會(huì)有weui-bar__item_on的class,也就顯示為綠色

  • !=是不等于操作符,activeIndex != 0顯然不成立條件為false,也就是組件hidden為false,即為顯示;而activeIndex != 1,2,3則都會(huì)true,hidden生效,組件不顯示,于是tab的效果就有了。

當(dāng)我們對(duì)字符串、Math對(duì)象、Date對(duì)象、數(shù)組對(duì)象、函數(shù)對(duì)象、事件對(duì)象所包含的信息不了解時(shí),把他們打印出來(lái)即可。打印出來(lái)的結(jié)果基本都是字符串、列表、對(duì)象,而在前面我們已經(jīng)掌握如何操作它們。通過(guò)實(shí)戰(zhàn),通過(guò)打印日志,既有利于我們調(diào)試代碼,也加強(qiáng)我們對(duì)邏輯的理解。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)