微信小程式豆瓣電影項目的改造過程經驗分享

来源:http://www.cnblogs.com/wuhuacong/archive/2017/09/10/7501496.html
-Advertisement-
Play Games

在學習微信小程式開發過程中,一部分的難點是前端邏輯的處理,也就是對前端JS的代碼編輯;一部分的難點是前端界面的設計展示;本篇隨筆基於一個豆瓣電影介面的小程式開源項目進行重新調整,把其中遇到的相關難點和改進的地方進行討論介紹,希望給大家提供一個參考的思路,本篇隨筆是基於前人小程式的項目基礎上進行的改進... ...


在學習微信小程式開發過程中,一部分的難點是前端邏輯的處理,也就是對前端JS的代碼編輯;一部分的難點是前端界面的設計展示;本篇隨筆基於一個豆瓣電影介面的小程式開源項目進行重新調整,把其中遇到的相關難點和改進的地方進行討論介紹,希望給大家提供一個參考的思路,本篇隨筆是基於前人小程式的項目基礎上進行的改進,因此在開篇之前首先對原作者的辛勞致敬及感謝。

1、豆瓣電影介面的小程式項目情況

豆瓣電影介面提供了很多相關的介面給我們使用,豆瓣電影介面的API地址如下所示:https://developers.douban.com/wiki/?title=movie_v2

在GitHub的開源庫裡面,可以搜索到很多關於豆瓣電影介面的小程式,我本篇隨筆是基於 weapp-douban-movie 這個小程式進行的改造處理,後來找到了原作者的項目地址:wechat-weapp-movie,原作者對版本做了一次升級,後來我對照我的調整和作者最新版本的源碼,發現有些地方改造的思路有些類似,如對於URL地址外放到統一的配置文件中的處理,不過還是有很多地方改造不同。

本篇隨筆的改造方案是基於小程式項目 weapp-douban-movie 的,因此對比的代碼也是和這個進行比較,不知道這個版本是不是原作者的舊版本,不過這個版本對文件目錄的區分已經顯得非常乾凈利落了,對電影信息的展示也統一到了模板裡面,進行多次的重覆利用,整體的佈局和代碼都做的比較好,看得出是花了不少功夫進行整理優化的了。

小程式主界面效果如下所示:

小程式源碼目錄結構如下所示:

不過每個人都有不同的經驗和看法,對於開發小程式來說,我側重於使用配置文件減少硬編碼的常量,使用Promise來優化JS代碼的使用,將獲取和提交JSON數據的方法封裝到輔助類,以及使用地理位置介面動態獲取當前城市名稱和坐標等等。

本篇隨筆下麵的部分就是介紹使用這些內容進行代碼優化的處理過程。

1、使用配置文件定義常量內容

我們在使用任何代碼開發程式的時候,我們都是非常註意一些變數或常量的使用,如果能夠統一定義那就統一定義好了,這種在小程式的JS代碼裡面也是一樣,我們儘可能抽取一些如URL,固定參數等信息到獨立的配置文件中,這樣在JS代碼引入文件,使用變數來代替

例如原來的config.js文件裡面,只是定義了一個地址和頁面數量的大小常量,如下所示

module.exports = {
    city: '杭州',
    count: 20
}

原來的小程式代碼在獲取待映的電影內容時候,部分源碼如下所示

其他頁面JS代碼也和這個類似,頭部依舊有很多類似這樣URL地址,這個是我希望統一到config.js文件的地方,另外這個調用的函數是使用回調函數的處理方式,如下所示。

douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)

其實我認為這裡面既然是定義的外部函數,那麼這裡面的url, city, config.city, config.cout都不需要這裡,在封裝函數內部使用這些常量即可,因此可以對他們進行改造,如下我們統一抽取各個文件裡面的URL,以及一些常見變數到config.js裡面。

下麵代碼是我優化整理後的配置參數信息。

module.exports = {
    city: '',
    location:'0,0',
    count: 20,

    coming_soon_url: 'https://api.douban.com/v2/movie/coming_soon',
    in_theaters_url: 'https://api.douban.com/v2/movie/in_theaters',
    top_url: 'https://api.douban.com/v2/movie/top250',
    search_url: 'https://api.douban.com/v2/movie/search?tag=',
    detail_url: 'https://api.douban.com/v2/movie/subject/', //?id=
    celebrity_url: 'https://api.douban.com/v2/movie/celebrity/',
    baidu_ak:'6473aa8cbc349933ed841467bf45e46b',
    baidu_movie:'https://api.map.baidu.com/telematics/v3/movie',

    hotKeyword: ['功夫熊貓', '烈日灼心', '擺渡人', '長城', '我不是潘金蓮', '這個殺手不太冷', '驢得水', '海賊王之黃金城', '西游伏妖片', '我在故宮修文物', '你的名字'],
    hotTag: ['動作', '喜劇', '愛情', '懸疑'],
}

上面的配置文件config.js裡面,我統一抽取了各個頁面的URL地址、關鍵詞和標簽(hotKeyword和hotTag)、城市及地址(city和location後面動態獲取)、頁面數量count等參數信息。

另外由於部分參數統一通過config.js獲取,就不需要再次在調用的時候傳入了,因此簡化調用代碼的參數傳入,如下代碼所示。

douban.fetchComming(that, that.data.start)

對於原先的代碼

douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)

簡化的雖然不多,但是儘可能的保持乾凈簡單的介面是我們的目標,而且這裡把常規的URL等參數提取到函數裡面,更加符合我們編碼的習慣。

這裡定義的douban.fetchComming(that, that.data.start) 使用了Promise來簡化代碼,傳入的that參數是因為需要在函數體裡面設置該頁面裡面的Data等處理。

 關於Promise的相關處理,我們在下麵進行介紹。

 

2、使用Promise來優化JS代碼

關於Promise的好處和如何使用Promise插件介紹,我在隨筆《在微信小程式的JS腳本中使用Promise來優化函數處理》中已有介紹,我很喜歡使用這種Promise的風格代碼,而且可以定義一些常用的輔助類來提高代碼的重用。在我參考的這個豆瓣電影小程式還是使用常規回調的函數,對比原作者最新版本的 wechat-weapp-movie 小程式,也依舊使用回調函數模式來處理,有點奇怪為什麼不引入Promise插件來開發。

原來的小程式,電影介面的相關處理,統一在fetch.js裡面進行處理,這裡封裝對各種豆瓣API介面的調用。

這裡我們來看看原來程式沒有採用Promise的回調函數處理代碼

var config = require('./config.js')
var message = require('../../component/message/message')

module.exports = {
    fetchFilms: function(url, city, start, count, cb) {
      var that = this
      if (that.data.hasMore) {
        wx.request({
          url: url,
          data: {
            city: config.city,
            start: start,
            count: count
          },
          method: 'GET', 
          header: {
            "Content-Type": "application/json,application/json"
          },
          success: function(res){
            if(res.data.subjects.length === 0){
              that.setData({
                hasMore: false,
              })
            }else{
              that.setData({
                films: that.data.films.concat(res.data.subjects),
                start: that.data.start + res.data.subjects.length,
                showLoading: false
              })
            }
            wx.stopPullDownRefresh()
            typeof cb == 'function' && cb(res.data)
          },
          fail: function() {
            that.setData({
                showLoading: false
            })
            message.show.call(that,{
              content: '網路開小差了',
              icon: 'warning',
              duration: 3000
            })
          }
        })
      }
    },

這個函數是一個通用的函數,用來獲取待映、熱映、top250口碑的記錄信息,不過它把參數拋給調用者傳入,因此顯得調用比較複雜一些,我們經過使用Promise優化代碼處理,並對介面的參數進行簡化,代碼改造如下所示。

var config = require('./config.js')
var message = require('../../component/message/message')
var app = getApp()//獲取應用實例

module.exports = {
    //待映
    fetchComming : function(page, start) {
      return this.fetchFilms(page, config.coming_soon_url, config.city, start, config.count);
    },
    //熱映
    fetchPopular : function(page, start) {
      return this.fetchFilms(page, config.in_theaters_url, config.city, start, config.count);
    },
    //top250口碑
    fetchTop : function(page, start) {
      return this.fetchFilms(page, config.top_url, config.city, start, config.count);
    },

    //通用的熱映、待映的獲取方式
    fetchFilms: function(page, url, city, start, count) {
      return new Promise((resolve, reject) => {
        var that = page;
        var json = {city: city, start: start, count: count };
        var type = "json";//特殊設置,預設是application/json
        if (that.data.hasMore) {
          app.utils.get(url, json, type).then(res => {
              if(res.subjects.length === 0){
                that.setData({
                  hasMore: false,
                })
              }else{
                that.setData({
                  films: that.data.films.concat(res.subjects),
                  start: that.data.start + res.subjects.length,
                  showLoading: false
                })
              }
              wx.stopPullDownRefresh();

              resolve(res);            
          })
        }
      })
    },

最終的請求介面參數只有兩個,一個是頁面對象,一個是請求的起始位置,如下代碼所示

function(page, start)

另外我們使用了代碼

app.utils.get(url, json, type)

來對wx.request方法的統一封裝,直接使用工具類裡面的方法即可獲取結果,不需要反覆的、臃腫的處理代碼。這就是我們使用Promise來優化JS,並抽取常用代碼到工具類裡面的做法。

我們再來對比一下獲取電影詳細信息的介面函數封裝,原來代碼如下所示。

    fetchFilmDetail: function(url, id, cb) {
      var that = this;
      wx.request({
        url: url + id,
        method: 'GET',
        header: {
          "Content-Type": "application/json,application/json"
        },
        success: function(res){
          that.setData({
            filmDetail: res.data,
            showLoading: false,
            showContent: true
          })
          wx.setNavigationBarTitle({
              title: res.data.title
          })
          wx.stopPullDownRefresh()
          typeof cb == 'function' && cb(res.data)
        },
        fail: function() {
          that.setData({
              showLoading: false
          })
          message.show.call(that,{
            content: '網路開小差了',
            icon: 'warning',
            duration: 3000
          })
        }
      })
    },

我改造後的函數代碼如下所示。

    //獲取電影詳細信息
    fetchFilmDetail: function(page, id) {      
      return new Promise((resolve, reject) => {
        var that = page;
        var url = config.detail_url + id;
        var type = "json";//特殊設置,預設是application/json
        app.utils.get(url, {}, type).then(res => {
            that.setData({
              filmDetail: res,
              showLoading: false,
              showContent: true
            });

            wx.setNavigationBarTitle({
                title: res.title
            });
            wx.stopPullDownRefresh(); 
            
            resolve(res);   
        });
      })
    },

通過對fetch.js函數代碼的改造處理,可以看到調用的JS代碼參數減少了很多,而且頁面也不用保留那麼多連接等參數常量信息了。

    onLoad: function() {
        var that = this
        douban.fetchComming(that, that.data.start)
    },

 

3、使用地理位置介面動態獲取當前城市名稱和坐標

原來程式使用硬編碼的方式設置當前城市,如下腳本所示

module.exports = {
    city: '杭州',
    count: 20
}

不過我們不同地方的人員使用的時候,這個城市名稱肯定需要變化的,因此可以使用微信的地理位置介面動態獲取當前位置信息,然後寫入到配置文件裡面即可。

//獲取當前位置信息
function getLocation (type) {
  return new Promise((resolve, reject) => {
    wx.getLocation({ type: type, success: resolve, fail: reject })
  })
}

//根據坐標獲取城市名稱
function getCityName (latitude = 39.90403, longitude = 116.407526) {
  var data = { location: `${latitude},${longitude}`, output: 'json', ak: '6473aa8cbc349933ed841467bf45e46b' };
  var url =  'https://api.map.baidu.com/' + 'geocoder/v2/';
  var type = 'json';
  
  return this.get(url, data, type).then(res => res.result.addressComponent.city);
}

然後我們在app.js裡面編寫代碼,在app啟動的時候,動態獲取城市名稱、坐標信息然後寫入配置文件即可,這裡使用的還是Promise的函數調用實現。

const utils  = require('./comm/script/util.js')
const config = require('./comm/script/config.js')

App({
  onLaunch: function() { 
    utils.getLocation()
    .then(res=>{
      const { latitude, longitude } = res;
      config.location = `${longitude},${latitude}`;//當前坐標
      console.log(`currentLocation : ${config.location}`);

      return utils.getCityName(latitude, longitude)
    })
    .then(name=>{
        config.city = name.replace('市', ''); //當前城市名稱
        console.log(`currentCity : ${config.city}`)
    })
    .catch(err => {
      config.city = '廣州'
      console.error(err)
    })
  },
...

最後呈上改造過代碼的運行界面,還是保留原來的功能正常使用。

以上就是我對這個小程式進行不同方面的調整思路和經驗總結,希望大家有所收益或者建議,感謝閱讀支持。 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果js屬於剛剛入門階段,不建議抱著書一直看下去,因為這樣你不容易明白這些定義和概念的用法.看著看著就會很迷惑的。建議先試著用原生JS寫一些小項目和小程式,然後試著寫博客做些筆記,把遇到的困惑寫下來,帶著疑問去學習。 如果有一定的js基礎或者用JQuery等一些庫做過一些小東西的話,可以先看《Jav ...
  • bootstrap前端開發工具 柵格系統 版心 .container 柵格佈局 (一行分為12格,響應式佈局) .row .col md 12 .col sm 12 .col xs 12 排版 文本對齊: .text center; .text left; .text right; 塊標簽對齊: . ...
  • html文件 ...
  • 1 if (!Object.keys) { 2 Object.keys = (function () { 3 var hasOwnProperty = Object.prototype.hasOwnProperty, //原型上的方法,只取自身有的屬性; 4 hasDontEnumBug = !({... ...
  • 1.註釋: html的註釋:<!--我是註釋--> CSS的註釋:/*我是註釋*/ JS的註釋://我是註釋 2.變數: 變數要先聲明再賦值,如下: var mychar; mychar="javascript"; var mynum = 6; 變數可以重覆賦值,如下: var mychar; my ...
  • 任務 1.在第27行處補充完整,實現當點擊"全選"按鈕時,將選中所有的覆選項。 提示:document.getElementsByTagName("input")獲取的是所有input標簽,包括覆選項和按鈕,所以要判斷是否是覆選項,如是選中。 2.在第33行處補充完整,實現當點擊"全不選"按鈕時,將 ...
  • JavaScript正則表達式入門 ===================== 常常用戶在一個網頁里登錄註冊帳號時,要輸入用戶名、手機號、郵箱地址、設置密碼等項目。而對於用戶輸入的用戶名是否規範,輸入的是否是郵箱地址、密碼強度如何等等都可以通過一 正則表達式 制定相應的規則來驗證校檢,來實現一個非常 ...
  • 前面的話 本文將通過多種方式實現紋理文本的效果 背景裁切 對於實現紋理文本的效果,腦海中最直接能想到的辦法可能是背景裁切background-clip 使用線性漸變來填充文本背景 下麵使用一張楓葉的背景,來製作紋理文本 當然了,放一張動態gif圖,也是沒問題的 如果想要讓填充動起來,可以通過anim ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...