微信小程序豆瓣電影項目的(de)改造過程經驗分享 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

微信小程序豆瓣電影項目的(de)改造過程經驗分享

發表時(shí)間:2021-4-30

發布人(rén):融晨科技

浏覽次數:62

在(zài)學習微信小程序開發過程中,一部分的(de)難點是(shì)前端邏輯的(de)處理,也(yě)就(jiù)是(shì)對前端JS的(de)代碼編輯;一部分的(de)難點是(shì)前端界面的(de)設計展示;本篇随筆基于(yú)一個(gè)豆瓣電影接口的(de)小程序開源項目進行重新調整,把其中遇到(dào)的(de)相關難點和(hé / huò)改進的(de)地(dì / de)方進行讨論介紹,希望給大(dà)家提供一個(gè)參考的(de)思路,本篇随筆是(shì)基于(yú)前人(rén)小程序的(de)項目基礎上(shàng)進行的(de)改進,因此在(zài)開篇之(zhī)前首先對原作者的(de)辛勞緻敬及感謝。

1、豆瓣電影接口的(de)小程序項目情況

豆瓣電影接口提供了(le/liǎo)很多相關的(de)接口給我們使用,豆瓣電影接口的(de)API地(dì / de)址如下所示: https://developers.douban.com/wiki/?title=movie_v2

在(zài)GitHub的(de)開源庫裏面,可以(yǐ)搜索到(dào)很多關于(yú)豆瓣電影接口的(de)小程序,我本篇随筆是(shì)基于(yú) weapp-douban-movie 這(zhè)個(gè)小程序進行的(de)改造處理,後來(lái)找到(dào)了(le/liǎo)原作者的(de)項目地(dì / de)址: wechat-weapp-movie ,原作者對版本做了(le/liǎo)一次升級,後來(lái)我對照我的(de)調整和(hé / huò)作者最新版本的(de)源碼,發現有些地(dì / de)方改造的(de)思路有些類似,如對于(yú)URL地(dì / de)址外放到(dào)統一的(de)配置文件中的(de)處理,不(bù)過還是(shì)有很多地(dì / de)方改造不(bù)同。

本篇随筆的(de)改造方案是(shì)基于(yú)小程序項目 weapp-douban-movie 的(de),因此對比的(de)代碼也(yě)是(shì)和(hé / huò)這(zhè)個(gè)進行比較,不(bù)知道(dào)這(zhè)個(gè)版本是(shì)不(bù)是(shì)原作者的(de)舊版本,不(bù)過這(zhè)個(gè)版本對文件目錄的(de)區分已經顯得非常幹淨利落了(le/liǎo),對電影信息的(de)展示也(yě)統一到(dào)了(le/liǎo)模闆裏面,進行多次的(de)重複利用,整體的(de)布局和(hé / huò)代碼都做的(de)比較好,看得出(chū)是(shì)花了(le/liǎo)不(bù)少功夫進行整理優化的(de)了(le/liǎo)。

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

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

不(bù)過每個(gè)人(rén)都有不(bù)同的(de)經驗和(hé / huò)看法,對于(yú)開發小程序來(lái)說(shuō),我側重于(yú)使用配置文件減少硬編碼的(de)常量,使用Promise來(lái)優化JS代碼的(de)使用,将獲取和(hé / huò)提交JSON數據的(de)方法封裝到(dào)輔助類,以(yǐ)及使用地(dì / de)理位置接口動态獲取當前城市名稱和(hé / huò)坐标等等。

本篇随筆下面的(de)部分就(jiù)是(shì)介紹使用這(zhè)些内容進行代碼優化的(de)處理過程。

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

我們在(zài)使用任何代碼開發程序的(de)時(shí)候,我們都是(shì)非常注意一些變量或常量的(de)使用,如果能夠統一定義那就(jiù)統一定義好了(le/liǎo),這(zhè)種在(zài)小程序的(de)JS代碼裏面也(yě)是(shì)一樣,我們盡可能抽取一些如URL,固定參數等信息到(dào)獨立的(de)配置文件中,這(zhè)樣在(zài)JS代碼引入文件,使用變量來(lái)代替

例如原來(lái)的(de)config.js文件裏面,隻是(shì)定義了(le/liǎo)一個(gè)地(dì / de)址和(hé / huò)頁面數量的(de)大(dà)小常量,如下所示

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

原來(lái)的(de)小程序代碼在(zài)獲取待映的(de)電影内容時(shí)候,部分源碼如下所示

其他(tā)頁面JS代碼也(yě)和(hé / huò)這(zhè)個(gè)類似,頭部依舊有很多類似這(zhè)樣URL地(dì / de)址,這(zhè)個(gè)是(shì)我希望統一到(dào)config.js文件的(de)地(dì / de)方,另外這(zhè)個(gè)調用的(de)函數是(shì)使用回調函數的(de)處理方式,如下所示。

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

其實我認爲(wéi / wèi)這(zhè)裏面既然是(shì)定義的(de)外部函數,那麽這(zhè)裏面的(de)url, city, config.city, config.cout都不(bù)需要(yào / yāo)這(zhè)裏,在(zài)封裝函數内部使用這(zhè)些常量即可,因此可以(yǐ)對他(tā)們進行改造,如下我們統一抽取各個(gè)文件裏面的(de)URL,以(yǐ)及一些常見變量到(dào)config.js裏面。

下面代碼是(shì)我優化整理後的(de)配置參數信息。

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: ['功夫熊貓', '烈日灼心', '擺渡人(rén)', '長城', '我不(bù)是(shì)潘金蓮', '這(zhè)個(gè)殺手不(bù)太冷', '驢得水', '海賊王之(zhī)黃金城', '西遊伏妖片', '我在(zài)故宮修文物', '你的(de)名字'],
    hotTag: ['動作', '喜劇', '愛情', '懸疑'],
}

上(shàng)面的(de)配置文件config.js裏面,我統一抽取了(le/liǎo)各個(gè)頁面的(de)URL地(dì / de)址、關鍵詞和(hé / huò)标簽(hotKeyword和(hé / huò)hotTag)、城市及地(dì / de)址(city和(hé / huò)location後面動态獲取)、頁面數量count等參數信息。

另外由于(yú)部分參數統一通過config.js獲取,就(jiù)不(bù)需要(yào / yāo)再次在(zài)調用的(de)時(shí)候傳入了(le/liǎo),因此簡化調用代碼的(de)參數傳入,如下代碼所示。

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

對于(yú)原先的(de)代碼

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

簡化的(de)雖然不(bù)多,但是(shì)盡可能的(de)保持幹淨簡單的(de)接口是(shì)我們的(de)目标,而(ér)且這(zhè)裏把常規的(de)URL等參數提取到(dào)函數裏面,更加符合我們編碼的(de)習慣。

這(zhè)裏定義的(de) douban.fetchComming(that, that.data.start)  使用了(le/liǎo)Promise來(lái)簡化代碼,傳入的(de)that參數是(shì)因爲(wéi / wèi)需要(yào / yāo)在(zài)函數體裏面設置該頁面裏面的(de)Data等處理。

關于(yú)Promise的(de)相關處理,我們在(zài)下面進行介紹。

2、使用Promise來(lái)優化JS代碼

關于(yú)Promise的(de)好處和(hé / huò)如何使用Promise插件介紹,我在(zài)随筆《 在(zài)微信小程序的(de)JS腳本中使用Promise來(lái)優化函數處理 》中已有介紹,我很喜歡使用這(zhè)種Promise的(de)風格代碼,而(ér)且可以(yǐ)定義一些常用的(de)輔助類來(lái)提高代碼的(de)重用。在(zài)我參考的(de)這(zhè)個(gè)豆瓣電影小程序還是(shì)使用常規回調的(de)函數,對比原作者最新版本的(de)  wechat-weapp-movie 小程序,也(yě)依舊使用回調函數模式來(lái)處理,有點奇怪爲(wéi / wèi)什麽不(bù)引入Promise插件來(lái)開發。

原來(lái)的(de)小程序,電影接口的(de)相關處理,統一在(zài)fetch.js裏面進行處理,這(zhè)裏封裝對各種豆瓣API接口的(de)調用。

這(zhè)裏我們來(lái)看看原來(lái)程序沒有采用Promise的(de)回調函數處理代碼

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: '網絡開小差了(le/liǎo)',
              icon: 'warning',
              duration: 3000
            })
          }
        })
      }
    },

這(zhè)個(gè)函數是(shì)一個(gè)通用的(de)函數,用來(lái)獲取待映、熱映、top250口碑的(de)記錄信息,不(bù)過它把參數抛給調用者傳入,因此顯得調用比較複雜一些,我們經過使用Promise優化代碼處理,并對接口的(de)參數進行簡化,代碼改造如下所示。

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);
    },

    //通用的(de)熱映、待映的(de)獲取方式
    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";//特殊設置,默認是(shì)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);            
          })
        }
      })
    },

最終的(de)請求接口參數隻有兩個(gè),一個(gè)是(shì)頁面對象,一個(gè)是(shì)請求的(de)起始位置,如下代碼所示

function(page, start)

另外我們使用了(le/liǎo)代碼

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

來(lái)對wx.request方法的(de)統一封裝,直接使用工具類裏面的(de)方法即可獲取結果,不(bù)需要(yào / yāo)反複的(de)、臃腫的(de)處理代碼。這(zhè)就(jiù)是(shì)我們使用Promise來(lái)優化JS,并抽取常用代碼到(dào)工具類裏面的(de)做法。

我們再來(lái)對比一下獲取電影詳細信息的(de)接口函數封裝,原來(lái)代碼如下所示。

    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: '網絡開小差了(le/liǎo)',
            icon: 'warning',
            duration: 3000
          })
        }
      })
    },

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

    //獲取電影詳細信息
    fetchFilmDetail: function(page, id) {      
      return new Promise((resolve, reject) => {
        var that = page;
        var url = config.detail_url + id;
        var type = "json";//特殊設置,默認是(shì)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函數代碼的(de)改造處理,可以(yǐ)看到(dào)調用的(de)JS代碼參數減少了(le/liǎo)很多,而(ér)且頁面也(yě)不(bù)用保留那麽多連接等參數常量信息了(le/liǎo)。

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

3、使用地(dì / de)理位置接口動态獲取當前城市名稱和(hé / huò)坐标

原來(lái)程序使用硬編碼的(de)方式設置當前城市,如下腳本所示

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

不(bù)過我們不(bù)同地(dì / de)方的(de)人(rén)員使用的(de)時(shí)候,這(zhè)個(gè)城市名稱肯定需要(yào / yāo)變化的(de),因此可以(yǐ)使用微信的(de)地(dì / de)理位置接口動态獲取當前位置信息,然後寫入到(dào)配置文件裏面即可。

//獲取當前位置信息
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 = https://www.wxapp-union.com/{ 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);
}

然後我們在(zài)app.js裏面編寫代碼,在(zài)app啓動的(de)時(shí)候,動态獲取城市名稱、坐标信息然後寫入配置文件即可,這(zhè)裏使用的(de)還是(shì)Promise的(de)函數調用實現。

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)
    })
  },
...

最後呈上(shàng)改造過代碼的(de)運行界面,還是(shì)保留原來(lái)的(de)功能正常使用。

以(yǐ)上(shàng)就(jiù)是(shì)我對這(zhè)個(gè)小程序進行不(bù)同方面的(de)調整思路和(hé / huò)經驗總結,希望大(dà)家有所收益或者建議,感謝閱讀支持。

相關案例查看更多