【面向ACG程式設計】連續改造2個Vue網頁

嗶譜嗶譜發表於2017-07-30

記得陰明大大在vueconf上說過:抱著一種解決問題的態度去學習知識是最有效率的。作為一名小白,之前學習Vue總是被動的,規定每天看一點文件,寫一點程式碼。總覺得不得勁。於是就想能不能給自己定個小目標,用Vue做他個網站!

移動端網址:justice-eternal.github.io/
PC端網址:lightmoon.pw
曲庫地址:github.com/zytx121/jus…

曲譜庫的建立

後來偶然看到了BGAIssueBlog,覺得很巧妙的利用了GitHub提供的issue的api,比單純的md部落格更具功能性。下面是作者列出的通過 Issues 記錄學習筆記的優點:

  • 線上編輯和預覽,隨時新增和提交(不用擔心電腦壞了導致筆記丟失)
  • 當筆記裡到巢狀圖片時,支援貼上螢幕截圖和拖拽新增圖片
  • 帶有搜尋和排序功能
  • 可通過 Label 來對 Issues 進行分類
  • 可以把每一個 Comment 作為一個小的知識點不停的追加到 Issue 裡
  • 結合 GitHub Pages 繫結域名來搭建個人部落格站點
  • 於是就想能不能用issue的特性做一個比較新奇的網站呢?

然後我就開始想啊想,怎麼想都想不出什麼好點子。一天,和往常一樣上山跑步的時候,跑著跑著突然靈光一閃,想到了自己關注的 Justice_Eternal 口琴吧!一個口琴大佬雲集的貼吧。該吧有大量的口琴大佬義務扒取各種新番ACG的譜曲併發布在貼吧裡。大量的譜子分散在各個貼子裡面,如果能夠將這些譜子集中起來儲存,豈不是查詢的時候很方便?於是回到家後,我立馬去貼吧逛了一圈,發現已經有了一個利用wordpress做的譜曲資源站,裡面已經對進行了曲譜精心的分類。但是該站是租用的伺服器,對於一個貼吧來說,網站的運營成本無疑是最大的問題。要知道,該站基本上是靠貼吧的各位捐款才勉強維持下來的。這更加堅定了我推行github曲譜庫的決心吧!

隨後我又自己分析了用issue實現曲譜庫的優點:

  • github倉庫完全開源,擁有github完善的API支援,相比於封閉的wordpress資料,更利於曲譜資料的儲存與呼叫
  • 同樣的原因,每個人的部落格或者網站都能自由呼叫曲譜庫中的資料!賽高!
  • github-pages建立的網頁完全免費
  • issue自帶搜尋和排序功能,能夠實現特定樂譜的搜尋
  • issue有自己的Label系統,能夠對譜曲按照首字母等標籤進行分類,方便查詢
  • 將每個issue的title定義為一個作品的名稱,後續可以通過comment新增該作品的譜曲
  • 可以將利用project為部分issues建立特輯,如:LL大法
  • 使用者可以利用issue的comment功能進行評論,交流吹奏心得,放置吹奏錄音或視訊連結
  • 使用者能夠線上編輯和預覽上傳的譜曲,並在釋出後隨時修改
  • 支援複製貼上和拖拽新增曲譜的封面圖片
  • 因為是境外伺服器,一些有擦邊球行為的動漫圖片不會被牆(你懂的),大量galgame譜上線中。。。

完美!!!

然後我參考moeje.org這個wordpress網站的譜曲格式寫了個ISSUE_TEMPLATE.md檔案,放在網頁根目錄的.github資料夾裡。

<!-- 
上面的Title請務必填寫譜子出自的作品名!
上面的Title請務必填寫譜子出自的作品名!
上面的Title請務必填寫譜子出自的作品名!

只有當第一次提交一個新作品的譜子時,才需要新建一個new issue和填寫Title!
因為一個作品(issue)下面可以提交(comment)多次譜子,所以之後每次該作品的譜子只需要在相應issue下以相同格式comment即可。comment時可以將issue模板複製,選擇Add a saved reply,儲存為自己的回答模板。

-->

# 譜曲名稱(替換)

<!-- 歌曲配圖  複製貼上到該處即可 -->


## 歌曲資訊

- ![](https://img.shields.io/badge/專輯-未知-ff69b4.svg)
- ![](https://img.shields.io/badge/作詞-未知-orange.svg)
- ![](https://img.shields.io/badge/作曲-未知-blue.svg)
- ![](https://img.shields.io/badge/編曲-未知-brightgreen.svg)
- ![](https://img.shields.io/badge/歌手-未知-d6504f.svg)


## 譜

【```】

譜子示例
#1#2#3#2
#1#2#3#2
#1#2#3#2

【```】

[![](https://img.shields.io/badge/扒譜-@扒譜大佬的ID-ff69b4.svg)](扒譜大佬的貼吧url)

<!-- 

[^_^]:
      請嚴格遵守上述格式提交曲譜,如果不符合規範,作者有權將其刪除。
      如果連結出錯請檢查是否有空格,有的話請刪去。
      如果資訊預設,刪掉對應程式碼即可。
      ps. 如果有什麼想說的話可以寫在最後,但不能影響上述格式。

-->複製程式碼

具體效果如下:

這裡科普一下,因為JE吧專注於ACG口琴演奏,而半音階口琴的音色是最適合ACG樂曲的,所以這裡的譜預設都是半音階口琴譜,也就是c調,數字譜。關於【】,(), # 等符號請參考使用說明

PC端的建立

接著,我就開始著手pc端的展示網頁改造(完全是以BGAIssueBlog)為模板,因為之前完全沒有自己獨立做過vue網站)。一開始只是換了倉庫名,改動了一下側邊欄,修改了一下element-ui的主題色。通過閱讀這個專案的程式碼,學習了用axios呼叫GitHub介面:


/*
github API的呼叫
 */

module.exports = {
  getLabels (vue) {
    return vue.$http.get(`https://api.github.com/repos/${vue.$store.getters.context}/labels`)
  },
  getGitHubUser (vue) {
    return vue.$http.get(`https://api.github.com/users/${vue.$store.getters.gitHubUsername}`)
  },
  getUserInfo (vue) {
    return vue.$http.all([this.getGitHubUser(vue), this.getLabels(vue)])
  },
  getIssues (vue, data) {
    let label = ''
    if (data.label && data.label.trim().length > 0) {
      label = `+label:${data.label}`
    }

    return vue.$http.get(`https://api.github.com/search/issues?q=${data.keyword}+state:open+repo:${vue.$store.getters.context}${label}&sort=created&order=desc&page=${data.currentPage}&per_page=${data.pageSize}`)
  },
  getIssue (vue, number) {
    return vue.$http.get(`https://api.github.com/repos/${vue.$store.getters.context}/issues/${number}`)
  },
  getComments (vue, url) {
    return vue.$http.get(url)
  },
  getReadme (vue) {
    return vue.$http.get(`https://raw.githubusercontent.com/${vue.$store.getters.context}/master/README.md`)
  },
  getInstruction (vue) {
    return vue.$http.get(`https://raw.githubusercontent.com/${vue.$store.getters.context}/master/instruction.md`)
  },
  getRepos (vue, data) {
    return vue.$http.get(`https://api.github.com/users/${vue.$store.getters.gitHubUsername}/repos?sort=stargazers_count&order=desc&page=1&per_page=100`)
  }
}複製程式碼

marked.js渲染markdown檔案,highlight.js程式碼高亮,github-markdown-css將渲染後的markdown設定成github的樣式。

利用vuex儲存label狀態,在各個元件中獲取和改變其屬性。後來依葫蘆畫瓢,利用vuex和正規表示式新增了label的部分展示/隱藏功能。

const SET_LABELS = 'SET_LABELS'
const SET_ACTIVE_LABEL = 'SET_ACTIVE_LABEL'
const SET_SHOWLABELS = 'SET_SHOWLABELS'

const state = {
  labels: [],
  activeLabel: null,
  showLabels: true,
}

const mutations = {
  [SET_LABELS] (state, labels) {
    state.labels = labels
  },
  [SET_SHOWLABELS] (state, showLabels) {
    state.showLabels = !state.showLabels
  },
  [SET_ACTIVE_LABEL] (state, label) {
    if ((state.activeLabel && label && label.name === state.activeLabel.name) || (!state.activeLabel && !label)) {
      return
    }

    state.activeLabel = label
  }
}

const actions = {
  setLabels: makeAction(SET_LABELS),
  setShowLabels: makeAction(SET_SHOWLABELS),
  updateActiveLabel: makeAction(SET_ACTIVE_LABEL),
}

const getters = {
  labels: (state) => {
    return state.labels
  },
  labels1: (state) => {
    return state.labels.filter(label => label.name.match(/^[A-Z]$/))
  },
  showLabels: (state) => {
    return state.showLabels
  },
  activeLabel: (state) => {
    return state.activeLabel
  }
}

export default {
  state,
  mutations,
  getters,
  actions
}複製程式碼

到這裡,基礎的改造工作就結束了。已經能夠正常顯示曲譜了(預設只顯示按首字母分類的標籤)

目前譜曲庫庫存告急,正在緊急搬運中- -!歡迎同道中人來做苦力! 曲庫地址

可是我覺得光是有這個查曲譜的功能未免太單調。於是就想,能否加入幾個別的功能。既然是ACG口琴網站,那麼acg元素和口琴當然是少不了的。於是我就著手進行口琴錄音播放以及口琴視訊播放這兩個功能的製作。首先做的是視訊部分。說到acg視訊,我首先想到的就是b站了。然後我就在GitHub搜有沒有b站的API什麼的。後來在掘金上看到一篇用Vue和typescript重構aplayer播放器的文章。然後我就點進去看了看,覺得這個音訊播放器設計的超級漂亮!接著我順藤摸瓜,無意間發現了DIYgod大佬。其倉庫下有無數動漫相關傑作,如 aplayerdplayer。天啦,這正是我想要的!對了,之前那個ISSUE_TEMPLATE.md檔案也是DIYgod大佬教我設定的!感謝!

接著參照doc,我新建了一個頁面,然後引入了DPlayer播放器,值得一提的是該播放器是支援彈幕播放以及彈幕傳送的喲!

video: {
          url: 'https://api.prprpr.me/dplayer/video/bilibili?aid=1845743',
          pic: 'http://upload-images.jianshu.io/upload_images/2141706-0be35df51011b7b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'
        },
        danmaku: {
          id: 'zy00000001',
          api: 'https://api.prprpr.me/dplayer/',
          addition: ['https://api.prprpr.me/dplayer/bilibili?aid=1845743']
        }複製程式碼

其中danmaku.id欄位是指向DIYgod自己的彈幕後端DPlayer-backend裡面的彈幕資料,每個視訊的這個需要獨一無二(doc裡面有個列表),不然會和別人存的彈幕車禍。而danmaku.addition則是指向b站的彈幕資料,可以讀取指定aid視訊的彈幕,並顯示出來。最後顯示在你螢幕前的彈幕是由兩部分組成的,而你傳送的彈幕會存在DPlayer-backend裡面。

最後我又同理,在側邊欄加入了aplayer,自動播放口琴演奏的宮崎駿動漫組曲!其實糾結了好久好不要用narrow模式- -!PC端大功告成!

技術棧:vue + vue-router + vuex + axios 全家桶,以及element-ui

移動端的建立

將PC端公佈在貼吧之後,由於感受到了貼吧小夥伴們的熱情!由於很多吧友都希望能夠在手機上使用本網站,而原本的pc端部落格不能很好的相應移動端。本著服務群眾的想法,我又開始了移動端的開發。本想一步到位做個響應式網站,也找了個響應式 material design ui ,但無奈自己完全沒有類似經驗,從ui開始實現對我來說話費的時間可能會很長。本著學習的目的,於是我就去找了個移動端的輪子來改造。嘗試了一把百度的lavas,把文件通讀了一遍,介面什麼都很鐘意。但是因為預設使用PWA的service worker ,沒辦法使用github-pages生成。以省錢為第一要務的我,果斷放棄。接著我又找到了github上面的一個專案 Vue.js仿嗶哩嗶哩動畫移動端 。並以此為基礎,開始了網站的改造。期間請教了作者許多問題,都得到很好的解決,所以在這裡必須感謝一下youhonglian

錄音播放部分

在PC端原有的曲譜查詢和視訊播放上,我又用aplayer新增了一個頁面專門播放大佬們的口琴錄音。

視訊部分

在視訊播放頁面上出現了一些問題。。。關於跨域

由於原來的專案的部分介面使用的是b站的,本地開發的時候設定了代理,所以能夠正常使用。但是部署在github上面後,問題出現了。根據MDN文件HTTP訪問控制(CORS)導致跨域並非不一定是瀏覽器限制了發起跨站請求,而也可能是跨站請求可以正常發起,但是返回結果被瀏覽器攔截了。通過檢視開發者皮膚中的Network,發現請求確實發出去了,但是沒有迴應。於是我就矇蔽了,之前PC端為什麼沒有出現這種情況?難道DIYgaod提供的API沒有跨域嗎?接著我惡補了一下關於跨域的相關知識,做了如下總結。

首先,本地開發的時候。實際上,vue生成的靜態頁面是在express伺服器上執行。當靜態頁面發出get請求後,express伺服器能夠監聽到,去相應的的域名拿到資料並返回給靜態頁面。
當我們把靜態頁面上傳到伺服器後,其實可以把伺服器看成我們的電腦。由於瀏覽器禁止一個域名(我們的網站)的 JS ,在未經允許的情況下讀取另一個域名(例如:b站api)的內容(這也是為什麼我們要跨域的原因)。所以當靜態頁面提出一個請求後,我們需要設定伺服器,讓他去api伺服器拿到資料,然後轉交給我們的靜態頁面(也就是反向代理)。其實就是開發環境express伺服器做的事!

  • github-pages只能渲染靜態頁面,而靜態頁面裡面的js程式碼沒辦法獲取到b站api的內容(跨域)
  • 正向代理隱藏真實客戶端,反向代理隱藏真實服務端
  • 跨域解決方案之一:jsonp,然而axios不支援jsonp。另外,jsonp不能發post請求,不管是否跨域,只要用jsonp方式就只能是get,因為本質是script方式載入的。
  • 設定vue-cli模板裡面config中的proxyTable後,可以解決開發環境的跨域問題。
  • 目前主流解決辦法:讓後端的同事設定header(詳情參考:HTTP訪問控制(CORS)

由於手機無法使用dplayer的彈幕功能,所以我直接使用了video標籤播放視訊,使用的是 journey-adapi。我將關於api跨域的疑問告訴了journey-ad,終於解決了這個問題。原來他在所有公開的api的響應頭都加了Access-Control-Allow-Origin: *欄位,所以可以被任何網頁發起呼叫。

回去又讀了一遍MDN文件:

Access-Control-Allow-Origin: * 
表示所有域名都能訪問該資源
Access-Control-Allow-Origin: lightmoon.pw
表示除了lightmoon.pw,其它外域均不能訪問該資源複製程式碼

看來之所以訪問b站api跨域是因為它沒有對所有人開放,而對於dplayer和imjad這類api是對所有人開放的,所以設定了Access-Control-Allow-Origin: *響應頭,解決了跨域問題。而對於開發環境下的跨域,全都可以通過設定伺服器代理來解決。但是對於生產環境下無法配置伺服器的(比如github),便無法訪問那些不對外開放的api了。

但是這類開放的b站api視訊都只能通過電腦播放,在手機上都播放不了。最後我只好用最笨的方法,通過下載對應的視訊上傳到七牛雲生成連結解決。不過視訊的相關標籤和評論還是呼叫的api的資料。(在此向觀眾老爺提問:有什麼更好的解決辦法嗎?)

譜曲庫部分

將pc段的程式碼整合了進來。( 注意:移動端專案中使用了vue-axios外掛,而PC段是沒有使用的,所以作為一個處女座,必須注意axios程式碼寫法的統一) 然後,稍微改了下label的樣式,以及內容的佈局。


最後又改了下sidebar和header。

技術棧:vue + vue-router + vuex + axios 全家桶,以及mint-ui

完結撒花!!!

很開心已經有github上面的ACG粉開始義務上傳曲譜了!作者自己也會抽空上傳曲譜。希望有更多熱愛ACG和樂器的程式設計師大佬加入我們。目前的曲譜的主要來源是moeje.org之前整理的譜曲,以及貼吧中的譜樓。

通過這此網頁的改寫讓我知道了自己的不足,也學到了不少以前完全沒有涉及的知識,得到了許多大佬的指點。果然如同陰明大佬所說:抱著一種解決問題的態度去學習知識是最有效率的。連續三天沒日沒夜的擼程式碼,終於把自己腦海中的東西基本實現了,也加深了對vue的理解。雖然這次網站改寫並不複雜,但也暴露出了我的很多問題,看來接下來自己還需要先在基礎知識方面多多努力,好好啃一啃高程和CSS權威指南。

關於本站

本站完全出於興趣構建,基本零成本,如果大家喜歡,還請在github上star一下本專案,順便follow一下本人~~阿里嘎多!

另外,由於本人能力有限,難免有不盡人意的地方,如果對本站有什麼建議也一定!務必!要在issue中提出來哦!阿里嘎多!

最後放上相關地址

移動端網址:justice-eternal.github.io/
PC端網址:lightmoon.pw
曲庫地址:github.com/zytx121/jus…
貼吧地址: Justice_Eternal 口琴吧
搬運譜子的苦力組織: github.com/Justice-Ete…

關於如何npm run build後的靜態頁面用Github展示出來,可以參考我之前寫的這篇文章:
利用 GitHub 以及 Travis-CI 展示帶自己域名的 Vue 頁面

最後,歡迎喜歡ACG音樂的大佬入半音階口琴的坑!

使用說明 | 新手入門

相關文章