午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

【微信小程序開發(fā)?系列文章二】視圖層

 A芝蘭之室 2017-10-13


1、頁面文件

App跟Page的關(guān)系是,App在整個小程序中只能有一個,唯一的一個。但這個小程序中可以有多個頁面,就是多個Page,這些頁面相關(guān)的文件都放在根目錄下的pages目錄,每個頁面主要由四類文件組成,分另以頁面名命名,但不同的后綴的文件:xxx.js / xxx.wxml / xxx.wxss / xxx.json,如下圖:
頁面目錄
這個代碼目錄結(jié)構(gòu)是我們這篇文章中要講的一個小例子,pages/article 下面放的是文章相關(guān)的頁面。文件夾article的名字你可以隨便寫,只要自己覺得目錄結(jié)構(gòu)合理就行,但同一個頁面的四類文件,一定要用同一個名字,程序是通過這個名字來找到這個頁面對應(yīng)的各個相關(guān)文件的。這四個文件除了wxml之外都可以不是必須的,至少要有個wxml,想想就知道了,沒有view層的代碼哪知道頁面要長什么樣?js可以沒有,就少些行為、數(shù)據(jù)、邏輯而已;wxss文件也可以沒有,頁面長得丑而已;json文件更可以沒有(這個文件一般都沒有),它的定義字段跟全局的app.json文件是一樣的,它的作用是定義這頁面的一些屬性或者說配置,以覆蓋全局定義的相關(guān)的屬性。

文件夾的層次結(jié)構(gòu)可以隨便定義,甚至你想放到根目錄其實都是可以的,只是同個頁面相關(guān)文件要同名,且放同個目錄。那么問題來了,程序怎么知道你的頁面都放哪呢?

可能有讀者已經(jīng)回想起第一篇文章中講到的 app.json 這個配置文件了。其中有一個pages的屬性,它用來聲明這個程序中到底有哪些頁面的:

[javascript] view plain copy
  1. {  
  2.   "pages":[  
  3.     "pages/index/index",  
  4.     "pages/article/content"  
  5.   ],  
  6. ...  
  7. }  

2、例子簡介

下面我們先來總體分析一下這個小例子。上圖:
demo界面
借用36Kr網(wǎng)站的內(nèi)容來做個很簡單的小程序,新聞列表,點擊查看內(nèi)容。代碼放在:https://github.com/jsongo/weapp-tutorial-2 這里。
本章的內(nèi)容寫死了數(shù)據(jù),下一篇文章中我們會來介紹如何發(fā)起網(wǎng)絡(luò)請求去取數(shù)據(jù)。

3、wxml代碼分析

(1)相關(guān)組件
首先,這里會涉及到三種文件:wxml / wxss 和 js。index.wxml代碼:

  1. <view class="container">  
  2.   <scroll-view scroll-y="true" bindscrolltoupper="upper"  
  3.     bindscrolltolower="lower" bindscroll="scroll" class="scroll-wrapper">  
  4.     <view class="scroll-view-item" wx:for="{{news}}" data-id="{{item.id}}" catchtap="bindItemTap">  
  5.       <image class="item-img" src="{{item.img}}"></image>  
  6.       <view class="detail">  
  7.         <text class="item-name">{{item.title}}</text>  
  8.         <view class="tips">  
  9.           <text class="item-info">文 / {{item.author}} · {{item.time}}</text>  
  10.           <text class="category">{{item.category}}</text>  
  11.         </view>  
  12.       </view>  
  13.     </view>  
  14.   </scroll-view>  
  15. </view>  

view元素就相當于HTML中的<div>元素。重點介紹一下scroll-view組件,點擊查看官網(wǎng)文檔。它用來定義一個可滾動的視圖區(qū)域,相當于ios開發(fā)中的UIScrollView。里面的內(nèi)容如果超過這個區(qū)域的寬或高時,就會出現(xiàn)滾動條。上面定義的class為scroll-view-item的view就是一個36Kr的新聞項,一條新聞,布局很直觀,左側(cè)一個image,右側(cè)一個新聞標題的<text>,加上補充信息。<text>相當于<p>標簽,用來包裹文本內(nèi)容。<image>就是圖片元素,相當于HTML中的<img>標簽。scroll-view有一些屬性,重點介紹幾個,它默認是不允許滾動的,用scroll-x來設(shè)置橫向滾動(默認false),scroll-y設(shè)置豎直滾動(默認false)。bindscrolltoupper,這個屬性用來設(shè)置滾動到頂部/左邊時,觸發(fā) scrolltoupper 事件,用這個來做刷新。bindscrolltolower用來設(shè)置滾動到底部/右邊時,觸發(fā) scrolltolower 事件,可以用來做加載更多的操作。本例子中沒有用到這兩個,不過加到代碼中用來做使用說明。bindscroll用來綁定滾動時觸發(fā),這個可以用來做用戶手勢的判斷等。其它屬性,讀者可以參數(shù)官方文檔。

(2)數(shù)據(jù)綁定
數(shù)據(jù)綁定,在wxml文件里通過{{…}} 兩層大括號來定義,里面的內(nèi)容會被解析成js代碼,并把相關(guān)的變量綁定到相應(yīng)的地方。
下面介紹下數(shù)據(jù)綁定。wxml代碼就上面這么短,沒有其它了,那它怎么做出整個完整的滾動列表這么多內(nèi)容的?其實列表數(shù)據(jù)就定義在js文件里面:

[javascript] view plain copy
  1. Page({  
  2.   data: { // 當前頁面的數(shù)據(jù)定義在這里  
  3.     news: [  
  4.       {  
  5.         id: 1,  
  6.         title: '蘋果在華首家研發(fā)中心成立,能拯救大中華區(qū)的業(yè)績嗎?',  
  7.         author: '盧曉明',  
  8.         time: '12分鐘前',  
  9.         img: 'https://pic./avatar/201609/29013641/t87v7fekz7c3najy.jpg!feature',  
  10.         category: '明星公司'  
  11.       }  
  12.     ]  
  13.   },  
  14.   ...  
  15. })  

data字段,用來定義當前頁面的所有的數(shù)據(jù),可以理解為數(shù)據(jù)層,剛剛的wxml是view層,而Page({…})里的其它地方就是邏輯層。一個完整的MVC模型就很好理解了。

wxml里有個語法:wx:for,它會解析后面news這個數(shù)組,循環(huán),一個個取出數(shù)據(jù),并賦給item變量,里面就可以通過{{item.xxx}}來引用這些數(shù)據(jù)了。所以代碼寫起來非常簡潔。類似wx:for的還有wx:if等等,wx:if用來定義一個條件判斷,如果成立,就會解析當前標簽及其子標簽。{{…}}這里面除了以上提到的用法外,還可以做四則運算、三目運算、邏輯大小判斷、字符串相加等,甚至可以定義成一個json對象,如:{{a: 1, b: 2}}。還可以使用es6的語法,如{{...myJson}} ,用…把myJson這個對象解包展開平鋪到這個地方。相關(guān)的官方文檔。

有wx:if,那就應(yīng)該有wx:else了。這里給個官方的例子,看下就明白了:

  1. <view wx:if="{{length > 5}}"> 1 </view>  
  2. <view wx:elif="{{length > 2}}"> 2 </view>  
  3. <view wx:else> 3 </view>  

文檔除了介紹if之外,還講了另一個類似功能的 hidden,使用:<view hidden="{{flag ? true : false}}"> ... </view>當flag為true的時候,這個標簽及其子標簽會被隱藏,正好跟if相反,if是為true是解析、顯示。另外hidden作用的表述跟上面說到wx:if時的表述是有區(qū)別的,wx:if是條件為真時才會去解析,而hidden是無論如何都會去解析代碼,只是不顯示這些標簽而已。

<block>標簽。這是一個不會顯示出來的輔助標簽,在wx:if時,如果你想作用于幾個并列在一起的標簽,那就可以用block把它們包起來。同樣,如果你在用wx:for時,遇到?jīng)]有外層標簽的情況,只有幾個標簽并排著,這時也可以用block把它們包起來。

  1. <block wx:if="{{true}}">  
  2.   <view> view1 </view>  
  3.   <view> view2 </view>  
  4. </block>  
  5. <block wx:for="{{[1, 2, 3]}}">  
  6.   <view> {{index}}: </view>  
  7.   <view> {{item}} </view>  
  8. </block>  

(3)事件綁定

列表中每個item都有一個事件的綁定,catchtap="bindItemTap",綁定在用戶點擊時做頁面的切換。

組件的事件有很多種,每個組件都有自己定義的組件,如<input>有input事件,<form>有submit事件等,詳見各組件。不過有一些大部分組件都共同的事件,主要有:touchstart、touchmove、touchend、touchcancel、longtap、tap。前三個都很熟悉了,其它幾個,touchcancel指的是用戶的觸摸事件被其它東西打斷,比如突然彈窗,或者突然有個電話進來。longtap就是長按事件,微信官網(wǎng)解釋是指超過350ms的touch。tap就類似于pc瀏覽器上的click點擊事件。

這六個事件都是會冒泡的事件,如果沒有js基礎(chǔ)的朋友不太理解冒泡,這里幫你們找了些文章來理解這個
解析Javascript事件冒泡機制
javascript 的事件冒泡與捕獲及冒泡優(yōu)勢

除了這六個事件之外 ,其它事件都是非冒泡事件。事件綁定的方式就是用bind或catch這兩個詞,再加上事件的名稱(全小寫)就可以了。如bindtap, catchtap。他們的差別是,bind允許冒泡傳遞,而catch會阻止冒泡,就是把所有的事件都變成非冒泡事件。每個事件的響應(yīng)函數(shù)一般會有個event參數(shù),事件對象,這個參數(shù)的event.targe指向觸發(fā)事件的組件,里面有它的一些屬性值,而event.currentTarget則指向當前事件所在的組件,currentTarget是因為事件冒泡機制而設(shè)置的,它指向事件當前指向的組件,不一定是我們設(shè)置bindtap屬性的那個組件,而target就永遠都是指向這個綁定的原組件。

接下來講下MINA設(shè)置的一個很有意思的屬性集,event.dataset,這是一個event.target指向的組件里定義的data-xxx的屬性數(shù)據(jù)的json對象,可以用event.dataset.xxx來引用,比如最上面我們本文demo的wxml代碼中,在catchtap綁定的事件的標簽里,有一個data-id屬性,那么可以用event.dataset.id來引用這個id值。如果data-xxx里有大寫,這里都會轉(zhuǎn)化成小寫,如data-myDemo,這時要用event.dataset.mydemo來引用;如果是類似data-abc-def這種格式的屬性,則會變成abcDef,-減號后面的第一個字母會被大寫。事件相關(guān)的官方文檔在這。

所以,講到這里,希望讀者能再回去讀一下最開始的那個index.wxml代碼,會有很多收獲的。

4、js代碼分析

上面提到的data不是一個普通的字段,它和用戶界面綁定,改變它的值,界面里相應(yīng)的地方也會自動跟著變。這模式是不是跟react很像?目測微信小程序內(nèi)部包裝了react的核心算法和思想。data里的值 ,跟react中的state一樣,不要去直接用等號給它賦值或改變它的值,直接修改它是無效的,要調(diào)用setData(newObj)來修改,才能觸發(fā)綁定的界面更新。傳入的參數(shù),定義你要改變的那個字段就行,比如data為{a: 1, b: 2, c: 3},要修改a的值,可以這樣調(diào)用:this.setData({a: 11}),這時界面中綁定a變量的值就會立馬跟著變化。

react帶來的一個很大的思想變革就是,不希望你通過id或class去取得或設(shè)置一個頁面dom元素的值,這也是我很喜歡react的原因,其實做前端開發(fā)的朋友平時最痛苦的事情之一就是,獲取dom節(jié)點然后做相應(yīng)的界面更新,然后,當頁面重構(gòu)師把頁面結(jié)構(gòu)改掉的時候,前端開發(fā)的js代碼就到處冒煙了。前端另一個比較推薦的框架是angular.js,它通過事件綁定的方式來減少dom操作,更新界面。(扯遠了。)

MINA框架其實幫開發(fā)者做了非常多的事情,包括剛剛提到的數(shù)據(jù)綁定、界面更新的邏輯,還有頁面切換的邏輯,它內(nèi)部幫我們管理了整個小程序的頁面路由(Page()函數(shù)什么時候調(diào)用?跳轉(zhuǎn)的時候為什么不用new頁面?),整個頁面的生命周期(下面介紹)等等,開發(fā)者只需要把數(shù)據(jù)注入到框架中,并在相應(yīng)的生命周期函數(shù)中填寫相關(guān)的邏輯代碼就可以了。

剛提到的頁面切換方式,順便介紹下鏈接跳轉(zhuǎn)的方式,跟HTML不同的地方是,它不是用類似<a>標簽來實現(xiàn)的,而是通過事件來做的。頁面跳轉(zhuǎn),通過 wx.navigateTo 這個接口來實現(xiàn),點擊進入官網(wǎng)api的說明。navigateTo會保留當前頁面的條件下,切換到新頁面,可以用wx.navigateBack 返回。然而還有另一個跳轉(zhuǎn)的api,wx.redirectTo,它則不保留當前頁面,會關(guān)閉它,官網(wǎng)沒有提供這個跳轉(zhuǎn)方式返回的api,或許這時候,要想回到之前的這個頁面,就得去新建了。

兩個跳轉(zhuǎn)函數(shù)的參數(shù)都是一個object,格式如下:

[javascript] view plain copy
  1. {  
  2.     url: '',  
  3.     success: callback, // 可選  
  4.     fail: callback, // 可選  
  5.     complete: callback // 可選,無論調(diào)用成功失敗,都會執(zhí)行  
  6. }  

一般帶上一個url就可以了。url格式:'../article/content' 是個相對地址,指向新頁面的位置,注意不要寫后綴。

5、Page函數(shù)

跟介紹App函數(shù)一樣,先來理解一下Page的生命周期。

->頁面渲染完onReady->頁面顯示onShow  
->頁面隱藏onHide->頁面卸載onUnload

數(shù)據(jù)可以隨便定義在Page({ … })里成為一個屬性,類似于react的props,而data屬性里定義的數(shù)據(jù)就要注意些,它類似于react的state,用來實際綁定界面數(shù)據(jù)用的,它是一個json格式的數(shù)據(jù)。
onLoad、onReady、onShow這幾個回調(diào)的關(guān)系相對比較復雜,后面會有一篇文章專門用來分析程序生命周期的文章,這里就先不多說了。后面寫完后,會把鏈接貼過來。
事件的綁定函數(shù),也是定義在Page里,成為它的一個“成員函數(shù)”。比如,上面我用曾定義了一個catchtap="bindItemTap",這里的bindItemTap定義在這里:

[javascript] view plain copy
  1. var app = getApp()  
  2. Page({  
  3. …  
  4. …  
  5.   //事件處理函數(shù)  
  6.   bindItemTap: function(event) {  
  7.     var id = event.currentTarget.dataset.id, // 當前id  
  8.       article = null;  
  9.     // 找出當時點擊的那一項的詳細信息  
  10.     for(var d of this.data.news) {  
  11.       if(d.id == id) {  
  12.         article = d;  
  13.         break;  
  14.       }  
  15.     }  
  16.     console.log(article);  
  17.     if(!article) {  
  18.       console.log('系統(tǒng)出錯');  
  19.       return;  
  20.     }  
  21.     // 設(shè)置到全局變量中去,讓下個頁面可以訪問  
  22.     app.globalData.curArticle = article;  
  23.     // 切換頁面  
  24.     wx.navigateTo({  
  25.       url: '../article/content'  
  26.     });  
  27.   },  
  28. …  
  29. })  

這樣就可以了,微信會幫我們把這個函數(shù)跟我們在wxml里定義的綁定關(guān)聯(lián)起來。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多