<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                常用設計開發流程 首先,我們對整個小程序整體的產品體驗有一個清晰的規劃和定義,一般會通過交互圖或者手稿描繪小程序的界面交互和界面之間的跳轉關系。 其次,我們優先完成WXML+WXSS還原設計稿,把界面涉及到的元素和視覺細節先調試完成。 最后,我們把按照頁面交互梳理出每個頁面的data部分,填充WXML的模板語法,還有完成JS邏輯部分。 有些時候我們可能在產品交互體驗還不明確的情況下,先完成JS邏輯層一些模塊的工作并做好測試。高效的開發流程有很多種方式,一般是根據整個團隊的工作節奏來選擇和開展。 [TOC] ## 3.1 Flex布局 在小程序開發中,我們需要考慮各種尺寸終端設備上的適配。采用flex布局取代了傳統網頁開發中的盒模型。 采用flex布局的元素,簡稱為“容器”,在代碼示例中以`container`表示容器的類名。容器內的元素簡稱為“項目”,在代碼示例中以`item`表示項目的類名。 ### 3.1.1 container ### 3.1.2 item ## 3.2 界面常見的交互反饋 用戶和小程序上進行交互的時候,某些操作可能比較耗時,我們應該予以及時的反饋以舒緩用戶等待的不良情緒。 ### 3.2.1 觸摸反饋 * hover 小程序的`view`容器組件和`button`組件提供了hover-class屬性,觸摸時會往該組件加上對應的class改變組件的樣式。 * loading 有時候在點擊`button`按鈕處理更耗時的操作時,我們也會使用button組件的loading屬性,在按鈕的文字前邊出現一個Loading,讓用戶明確的感覺到,這個操作會比較耗時,需要等待一小段時間。 * Toast 在完成某個操作成功之后,我們希望告訴用戶這次操作成功并且不打斷用戶接下來的操作。彈出式提示Toast就是用在這樣的場景上,Toast提示默認1.5秒后自動消失。 * 模態(Modal)對話框 一般需要用戶明確知曉操作結果狀態的話,會使用模態對話框來提示,不適合用一閃而過的Toast彈出式提示。 ### 3.2.3 界面滾動 為了讓用戶可以快速刷新當前界面的信息,一般在小程序里會通過下拉整個界面這個操作來觸發。 * **下拉刷新** 宿主環境提供了統一的下拉刷新交互,開發者只需要通過配置開啟當前頁面的下拉刷新,用戶往下拉動界面觸發下拉刷新操作時,Page構造器的onPullDownRefresh回調會被觸發,此時開發者重新拉取新數據進行渲染。 * **上拉觸底** 多數的購物小程序會在首頁展示一個商品列表,用戶滾動到底部的時候,會加載下一頁的商品列表渲染到列表的下方,我們把這個交互操作叫為上拉觸底。宿主環境提供了上拉的配置和操作觸發的回調。 * **可滾動視圖組件** 是頁面中某一小塊區域需要可滾動,此時就要用到宿主環境所提供的`scroll-view`可滾動視圖組件。 ## 3.3 發起HTTPS網絡通信`wx.request` 小程序使用`wx.request`這個API,往服務器傳遞數據或者從服務器拉取信息。 >[info] hy,封裝了JavaScript的XhttpRequest對象?通過Ajax來實現。 ### 3.3.1 wx.request接口 :-: 表4-1 wx.request詳細參數 | 參數名 | 類型 | 必填 | 默認值 | 描述| | --- | ---| --- | --- | --- | | url | String | 是 | | 開發者服務器接口地址| | data | Object/String | 否 | | 請求的參數 | | header | Object | 否 | | 設置請求的 header,header 中不能設置 Referer,默認header['content-type'] = 'application/json' | method | String | 否 | GET | (需大寫)有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT | | dataType | String | 否 | json | 回包的內容格式,如果設為json,會嘗試對返回的數據做一次 JSON解析| | success | Function | 否 | | 收到開發者服務成功返回的回調函數,其參數是一個Object,見表4-2。 | fail | Function | 否 | | 接口調用失敗的回調函數| | complete | Function | 否 | | 接口調用結束的回調函數(調用成功、失敗都會執行)| ### 3.3.2 服務器要求 url參數是當前發起請求的服務器接口地址,小程序宿主環境要求request發起的網絡請求必須是https協議請求,因此開發者服務器必須提供HTTPS服務的接口,同時為了保證小程序不亂用任意域名的服務,wx.request請求的域名需要在小程序管理平臺進行配置[[配置參考]](https://developers.weixin.qq.com/miniprogram/dev/qcloud/qcloud.html#%E5%AF%BC%E5%85%A5-PHP-DEMO-%E5%92%8C%E9%85%8D%E7%BD%AE)( 登錄`mp.weixin.qq.com`,在設置, 開發設置里配置request的服務器域名,同時TLS版本需要支持1.2及以上。),如果小程序正式版使用wx.request請求未配置的域名,在控制臺會有相應的報錯。 一般我們在開發階段時,處于開發階段的服務器接口還沒部署到現網的域名下,經常會通過另一個域名來進行開發調試,考慮到這一點,為了方便開發者進行開發調試,開發者工具、小程序的開發版和小程序的體驗版在某些情況下允許`wx.request`(開發者工具需要勾選不校驗可信域名;小程序開發版和體驗版需要打開調試模式。)請求任意域名。 ### 3.3.3 請求參數 通過wx.request這個API,有兩種方法把數據傳遞到服務器: * 通過url上的參數 url是有長度限制的,其最大長度是1024字節,同時url上的參數需要拼接到字符串里,參數的值還需要做一次urlEncode。 * 通過data參數 兩種實現方式在HTTP GET請求的情況下表現幾乎是一樣的。但向服務端發送的數據超過1024字節時,就要采用HTTPPOST的形式,此時傳遞的數據就必須要使用data參數,基于這個情況,一般建議需要傳遞數據時,使用data參數來傳遞。 需要傳一些比較復雜的數據結構到后臺的時候,用JSON格式會更加合適。此時可以在wx.request的`header`參數設置content-type頭部為application/json,小程序發起的請求的包體內容就是data參數對應的JSON字符串。 ### 3.3.4 收到回包 通過wx.request發送請求后,服務器處理請求并返回HTTP包,小程序端收到回包后會觸發success回調,同時回調會帶上一個Object信息,詳細參數表4-2所示。 :-: 表4-2 wx.request的success返回參數 | 參數名 | 類型 | 描述 | | --- | --- | --- | | data | Object/String | 開發者服務器返回的數據 | | statusCode | Number | 開發者服務器返回的 HTTP 狀態碼 | | header | Object | 開發者服務器返回的 HTTP Response Header | >[danger] 只要成功收到服務器返回,無論HTTP狀態碼是多少都會進入success回調。因此開發者需要自己通過對回包的返回碼進行判斷后再執行后續的業務邏輯。 success回調的參數data字段類型是根據header\['content-type']決定的,默認`header['content-type']是'application/json'`,在觸發success回調前,小程序宿主環境會對data字段的值做JSON解析,如果解析成功,那么data字段的值會被設置成解析后的Object對象,其他情況data字段都是String類型,其值為HTTP回包包體。 ### 3.3.5 一般使用技巧 1. **設置超時時間** 小程序request默認超時時間是60秒,一般來說,可能在等待3秒后還沒收到回包就需要給用戶一個明確的服務不可用的提示。在小程序項目根目錄里邊的app.json可以指定request的超時時間。 2. **請求前后的狀態處理** 大部分場景可能是這樣的,用戶點擊一個按鈕,界面出現“加載中...”的Loading界面,然后發送一個請求到后臺,后臺返回成功直接進入下一個業務邏輯處理,后臺返回失敗或者網絡異常等情況則顯示一個“系統錯誤”的Toast,同時一開始的Loading界面會消失。 為了防止用戶極快速度觸發兩次tap回調,我們還加了一個hasClick的“鎖”,在開始請求前檢查是否已經發起過請求,如果沒有才發起這次請求,等到請求返回之后再把鎖的狀態恢復回去。 ### 3.3.6 排查異常的方法 在使用wx.request接口我們會經常遇到無法發起請求或者服務器無法收到請求的情況,我們羅列排查這個問題的一般方法: 1. 檢查手機網絡狀態以及wifi連接點是否工作正常。 2. 檢查小程序是否為開發版或者體驗版,因為開發版和體驗版的小程序不會校驗域名。 3. 檢查對應請求的HTTPS證書是否有效,同時TLS的版本必須支持1.2及以上版本,可以在開發者工具的console面板輸入showRequestInfo()查看相關信息。 4. 域名不要使用IP地址或者localhost,并且不能帶端口號,同時域名需要經過ICP備案。 5. 檢查app.json配置的超時時間配置是否太短,超時時間太短會導致還沒收到回報就觸發fail回調。 6. 檢查發出去的請求是否302到其他域名的接口,這種302的情況會被視為請求別的域名接口導致無法發起請求。 ## 3.4 微信登錄 微信登錄的整個過程,如圖4-22所示。 ![微信登錄的整個過程](https://box.kancloud.cn/1a733d375a542ff206919f05f8a9b8c3_775x441.JPG) :-: 圖4-22 微信登錄的整個過程 ### 3.4.1 獲取微信登錄憑證code 在`wx.login`調用時,會先在微信后臺生成一張臨時的身份證,其有效時間僅為5分鐘 。然后把這個臨時身份證返回給小程序方,這個臨時的身份證我們把它稱為微信登錄憑證code。 ### 3.4.2 發送code到開發者服務器 在wx.login的success回調中拿到微信登錄憑證,緊接著會通過`wx.request`把code傳到開發者服務器,為了后續可以換取微信用戶身份id(注意id不是指微信用戶的微信號/密碼等隱私信息,可以理解為id是微信用戶在服務器的一個編號)。如果當前微信用戶還沒有綁定當前小程序業務的用戶身份,那在這次請求應該順便把用戶輸入的帳號密碼(是用戶在業務側的帳號密碼,而不是其微信的帳號密碼)一起傳到后臺,然后開發者服務器就可以校驗賬號密碼之后再和微信用戶id進行綁定。 ### 3.4.3 到微信服務器換取微信用戶身份id 開發者的后臺就拿到了前邊wx.login()所生成的微信登錄憑證code,此時就可以拿這個code到微信服務器換取微信用戶身份。 開發者服務器通過HTTPS協議,向微信服務器發起請求換取微信用戶身份。微信服務器提供的接口地址是: `https://api.weixin.qq.com/sns/jscode2session?appid=<AppId>&secret=<AppSecret>&js_code=<code>&grant_type=authorization_code` AppId和AppSecret是微信鑒別開發者身份的重要信息: `AppId`是公開信息,泄露AppId不會帶來安全風險,但是`AppSecret`是開發者的隱私數據不應該泄露,如果發現泄露需要到小程序管理平臺進行重置AppSecret,而code在成功換取一次信息之后也會立即失效,即便憑證code生成時間還沒過期。 URL的query部分的參數中 \<AppId>, \<AppSecret>, \<code> 就是前文所提到的三個信息,請求參數合法的話,接口會返回以下字段。 :-: 表4-3 jscode2session接口返回字段 | 字段 | 描述 | | --- | --- | | openid | 微信用戶的唯一標識 | | session_key | 會話密鑰 | | unionid | 用戶在微信開放平臺的唯一標識符。本字段在滿足一定條件的情況下才返回。| `openid`就是前文一直提到的微信用戶id,可以用這個id來區分不同的微信用戶。 `session_key`則是微信服務器給開發者服務器頒發的身份憑證,開發者可以用session_key請求微信服務器其他接口來獲取一些其他信息,由此可以看到,session_key不應該泄露或者下發到小程序前端。 設計session_key的原因:如果我們每次都通過小程序前端wx.login()生成微信登錄憑證code去微信服務器請求信息,步驟太多造成整體耗時比較嚴重,因此對于一個比較可信的服務端,給開發者服務器頒發一個時效性更長的會話密鑰就顯得很有必要了。session_key也存在過期時間,具體內容可以參考小程序的官方文檔關于session_key的相關介紹。 ### 3.4.4 綁定微信用戶身份id和業務用戶身份 業務側用戶如果還沒綁定微信側身份時,會讓用戶填寫業務側的用戶名密碼,這兩個值會和微信登錄憑證一起請求開發者服務器的登錄接口,此時開發者后臺通過校驗用戶名密碼就拿到了`業務側的用戶身份id`,通過code到微信服務器獲取`微信側的用戶身份openid`。微信會建議開發者把這兩個信息的對應關系存起來,我們把這個對應關系稱之為“綁定”。 有了這個綁定信息,小程序在下次需要用戶登錄的時候就可以不需要輸入賬號密碼,因為通過wx.login()獲取到code之后,可以拿到用戶的微信身份openid,通過綁定信息就可以查出業務側的用戶身份id,這樣靜默授權的登錄方式顯得非常便捷。 ### 3.4.5 業務登錄憑證SessionId `session_key`:是微信側返回的,開發者服務器和微信服務器之間的會話密鑰; `SessionId`:是開發者服務器返回的,開發者服務器和開發者的小程序之間的會話密鑰。 >[info] hy:使用http協議,因為http協議是無狀態協議,可以前端(browser)和后端(server)通過Session會話機制免去每次通信時的3次握手,從而提高通信效率。 > session_key中,前端:開發者服務器;后端:微信服務器 > SessionId中,前端:開發者的小程序;后端:開發者服務器 用戶登錄成功之后,開發者服務器需要生成會話密鑰SessionId,在服務端保持SessionId對應的用戶身份信息,同時把SessionId返回給小程序。小程序后續發起的請求中攜帶上SessionId,開發者服務器就可以通過服務器端的Session信息查詢到當前登錄用戶的身份,這樣我們就不需要每次都重新獲取code,省去了很多通信消耗。我們在4.6.4還會提到如何利用本地數據緩存的能力把SessionId存儲起來,以便在它還沒過期的時候能重復利用,以提高通信的性能。 ## 3.5 本地數據緩存 本地數據緩存是小程序存儲在當前設備硬盤上的數據,本地數據緩存有非常多的用途: * 存儲用戶在小程序上產生的操作,在用戶關閉小程序重新打開時可以恢復之前的狀態。 * 緩存一些服務端非實時的數據提高小程序獲取數據的速度,在特定的場景下可以提高頁面的渲染速度,減少用戶的等待時間。 ### 3.5.1 讀寫本地數據緩存 小程序提供了讀寫本地數據緩存的接口, `wx.getStorage/wx.getStorageSync`讀取本地緩存 `wx.setStorage/wx.setStorageSync`寫數據到緩存 其中Sync后綴的接口表示是同步接口,執行完畢之后會立馬返回。 :-: 表4-4 wx.getStorage/wx.getStorageSync詳細參數 | 參數名 | 類型 | 必填 | 描述 | | --- | --- | --- | --- | | key | String | 是 | 本地緩存中指定的 key | | success | Function | 否 | 異步接口調用成功的回調函數,回調參數格式: {data: key對應的內容} | | fail | Function | 否 | 異步接口調用失敗的回調函數 | | complete | Function | 否 | 異步接口調用結束的回調函數(調用成功、失敗都會執行) | :-: 表4-5 wx.setStorage/wx.setStorageSync詳細參數 | 參數名 | 類型 | 必填 | 描述 | | --- | --- | --- | --- | | key | String | 是 | 本地緩存中指定的 key | | data | Object/String | 是 | 需要存儲的內容 | | success | Function | 否 | 異步接口調用成功的回調函數 | | fail | Function | 否 | 異步接口調用失敗的回調函數 | | complete | Function | 否 | 異步接口調用結束的回調函數(調用成功、失敗都會執行) | ### 3.5.2 緩存限制和隔離 小程序宿主環境會管理不同小程序的數據緩存,不同小程序的本地緩存空間是分開的,每個小程序的緩存空間上限為10MB,如果當前緩存已經達到10MB,再通過wx.setStorage寫入緩存會觸發fail回調。 小程序的本地緩存不僅僅通過小程序這個維度來隔離空間,考慮到同一個設備可以登錄不同微信用戶,宿主環境還對不同用戶的緩存進行了隔離,避免用戶間的數據隱私泄露。 由于本地緩存是存放在當前設備,用戶換設備之后無法從另一個設備讀取到當前設備數據,因此用戶的關鍵信息不建議只存在本地緩存,應該把數據放到服務器端進行持久化存儲。 ### 3.5.3 利用本地緩存提前渲染界面 * **界面渲染** 討論一個需求:我們要實現一個購物商城的小程序,首頁是展示一堆商品的列表。一般的實現方法就是在頁面onLoad回調之后通過wx.request向服務器發起一個請求去拉取首頁的商品列表數據,等待wx.request的success回調之后把數據通過setData渲染到界面上 當用戶退出小程序再進來,界面仍然會有白屏現象,因為我們需要等待拉取商品列表的請求回來才能渲染商品列表。當然我們還可以再做一些體驗上的優化,例如在發請求前,可能我們會在界面上顯示一個Loading提示用戶在加載中,但是并沒有解決這個延遲渲染的現象,這個時候我們可以利用本地緩存來提前渲染界面。 * **提前渲染界面** 在拉取商品列表后把列表存在本地緩存里,在onLoad發起請求前,先檢查是否有緩存過列表,如果有的話直接渲染界面,然后等到wx.request的success回調之后再覆蓋本地緩存重新渲染新的列表 這種做法可以讓用戶體驗你的小程序時感覺加載非常快,但是你還要留意這個做法的缺點,如果小程序對渲染的數據實時性要求非常高的話,用戶看到一個舊數據的界面會非常困惑。因此一般在對數據實時性/一致性要求不高的頁面采用這個方法來做提前渲染,用以優化小程序體驗。 ### 3.5.4 緩存用戶登錄態SessionId 通常用戶在沒有主動退出登錄前,用戶的登錄態會一直保持一段時間(這段時間由開發者根據自己的業務情況定義,為了安全,這段時間不宜設置太長),就無需用戶頻繁地輸入賬號密碼。如果我們把SessionId記錄在Javascript中某個內存變量,當用戶關閉小程序再進來小程序時,之前內存的SessionId已經丟失,此時我們就需要利用本地緩存的能力來持久化存儲SessionId。 在重新打開小程序的時候,我們把上一次存儲的SessionId內容取出來,恢復到內存。 ## 3.6 設備能力 小程序的宿主環境提供了非常多的操作設備能力來幫助用戶在特定場景下做高效的輸入,例如:掃碼、操控藍牙等等能力。當然也有很多設備能力不是為了解決輸入低效問題而設計的,它們更多的是解決用戶側一些體驗問題,例如:獲取設備網絡狀態;調整屏幕亮度等等, ### 3.6.1 利用微信掃碼能力`wx.scanCode` 為了讓用戶減少輸入,我們可以把復雜的信息編碼成一個二維碼,利用宿主環境wx.scanCode這個API調起微信掃一掃,用戶掃碼之后,wx.scanCode的success回調會收到這個二維碼所對應的字符串信息。 應用場景: 1. 通過掃商品上的二維碼做一個商品展示的小程序 2. 通過掃共享單車上的二維碼去開啟單車 3. 餐廳點餐的小程序,我們給餐廳中每個餐桌編號1-100號,把這個數字編碼到二維碼(也可以把其他信息編碼進來,如餐桌人數限制,或者燈光調節等等,為了避免復雜,我們這里只考慮餐桌號)中,掃碼獲得編號之后,就可以知道是哪一桌點的菜,大大提高點餐體驗和效率。 ### 3.6.2 獲取網絡狀態`wx.getNetworkType` 我們知道手機連接到互聯網有幾種方式:Wifi、2G、3G、4G,包括很快到來的5G,每種方式的上傳速度和下載速度差異很大,它們的計費方式的差異也導致用戶在使用互聯網服務的時候有不同的使用習慣。 通過小程序提供的獲取網絡狀態的能力,做一些更友好的體驗提示。 ### 3.6.3 動態監聽網絡狀態變化`wx.onNetworkStatusChange` 某些情況下,我們的手機連接到網絡的方式會動態變化,例如手機設備連接到一個信號不穩定的Wifi熱點,導致手機會經常從Wifi切換到移動數據網絡。小程序宿主環境也提供了一個可以動態監聽網絡狀態變化的接口`wx.onNetworkStatusChange`,讓開發者可以及時根據網絡狀況去調整小程序的體驗,wx.onNetworkStatusChange這個接口的使用場景留給讀者來思考。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看