Electron+Vue實現仿網易雲音樂實戰

發表於2024-02-11

前言

這個專案是我跟著官方文件的那個Electron入門教程大致跑了一遍,瞭解了下Electron開發流程之後的實戰專案,所以中間應該是會有很多寫法不是很規範,安全性有可能也沒考慮到,可實現的各種api也不是很瞭解,適合初學者。
必須感謝 https://github.com/Binaryify/NeteaseCloudMusicApi 作者大大提供的API,給上satr,這個專案直接拉下來跑在本地就是一個後臺啦,很感謝!
使用文件:https://binaryify.github.io/NeteaseCloudMusicApi/#/

一、建立vue專案

1.用vue-cli建立vue專案

vue create electron-vue-cloud-music

image.png

2.檢視專案是否正常執行

cd electron-vue-cloud-music
npm run serve

3.設定electron的映象

npm config set registry=https://registry.npmmirror.com
npm config set disturl=https://registry.npmmirror.com/-/binary/node

npm config set electron_mirror=https://registry.npmmirror.com/-/binary/electron/

防止在打包的時候或者下載的時候由於網路原因失敗。

4.安裝electron環境

使用 vue-cli-plugin-electron-builder 外掛實現vue和electron的使用。
安裝外掛:

vue add electron-builder

我這裡選擇13版本。
image.png
出現 Successfully 表示安裝成功。
image.png

5.檢視執行命令

開啟package.json檔案,檢視使用命令。
image.png

可以看到主入口檔案是 background.js ,執行命令是 electron:serve, 打包命令是 electron:build

6.測試命令是否成功

6.1執行專案

npm run electron:serve

image.png
如果出現擴充套件失敗,並不斷嘗試,請先等待4次,稍後專案會正常執行。
image.png
專案正常執行:
image.png
開啟入口檔案 background.js 檔案,找到剛剛擴充套件失敗的程式碼:
image.png
可以看到是由於在開發環境的時候 vue 的 devtools 工具安裝失敗導致,我這邊直接註釋這部分程式碼(主要是我也沒研究怎麼解決,暫時用不到,不然每次啟動專案都要等待擴充套件有點浪費時間)

6.2打包專案

npm run electron:build

image.png
耐心等待,只要安裝了我上面的映象應該是沒問題,出現 Build complete 表示打包成功。
image.png
可以看到打包完成的目錄:dist_electron
image.png
點選.exe檔案就可以安裝,然後正常執行,這裡是測試,後面會等專案最後進行講更加具體的專案打包。

二、實現標題欄

1.隱藏標題欄

對於這部分的選單欄需要隱藏,雖然這裡有縮小、放大、關閉按鈕,但是需要自定義選單欄的話還是自己寫吧(我這裡是直接用vue元件實現的,如果electron這個框架有對這部分可以自定義的話麻煩也告知一下)
image.png
image.png
可以看到透過 frame:false 現在隱藏了標題欄,並且我還設定了視窗的最小寬度和高度,對於控制檯的顯示也做了控制,只有在開發環境下才能開啟控制檯,生產環境下不能開啟。
控制檯快捷鍵:Ctrl + Shift + I
image.png

2.實現標題欄樣式

標題欄樣式差不多如下,先實現右上角縮小、放大、關閉按鈕功能。
image.png
結構目錄如下:
image.png
可以看到我是直接把各個頁面放在App.vue檔案裡面了,想封裝的自己封裝,我這隻為了實現功能和熟悉框架。
views目錄下面的 TitleBar.vue 表示的是 標題欄的功能頁面, SideBar.vue 表示的是側邊欄的功能頁面, BottomBar.vue 表示的是底部播放欄的功能頁面。這裡我先把基本的結構給搭好,後面基本就是存業務操作,和electron相關的會重點記錄下。

3.實現放大、縮小、關閉

部分功能可能後面會再最佳化和實現,先實現放大、縮小、關閉按鈕功能。

3.1引入ipcRenderer

在渲染程式中引入ipcRenderer,注意這個時候需要安裝個外掛 node-polyfill-webpack-plugin 。
這是由於在webpack5中移除了nodejs核心模組的polyfill自動引入,所以需要手動引入。如果是用webpack4的小夥伴應該是不需要安裝的,應該不會報錯。

npm install node-polyfill-webpack-plugin

在vue.conifg.js中進行配置:
image.png
在 main.js 中引入 ipcRenderer:
image.png
注意在主入口 background.js 檔案中要把node使用開啟:
image.png
這樣就引入成功了,如果有別的報錯可能是別的原因。
ps:這裡我是直接在渲染程式中就引入ipcRenderer,按照官方教程考慮安全性應該使用預載入指令碼建立一個preload.js然後透過 contextBridge.exposeInMainWorld 丟擲ipcRenderer的功能,但是這個方法我按照網上教程失敗了,有了解的小夥伴可以告訴我下應該把preload.js檔案放在哪裡,我之前是放在public 目錄下,但是沒有生效,後面也沒有繼續嘗試(後面我會繼續研究下,除去安全性,確實程式間通訊還是放在一個檔案中好管理一下)。

3.2點選按鈕程式間通訊實現

因為渲染程式和主程式之間是隔離的,所以現在在渲染程式中的點選事件我需要透過ipcRenderer傳遞給主程式,在主程式中完成功能。
在 TitleBar.vue 檔案下設定點選事件:

<i class="iconfont icon-suoxiao1" @click="minimizeClick" title="最小化"></i>
<i v-show="isMaximize" class="iconfont icon-fangda1" @click="maximizeClick" title="最大化"></i>
<i v-show="!isMaximize" class="iconfont icon-suoxiao" @click="maximizeClick" title="向下還原"></i>
<i class="iconfont icon-guanbi1" @click="closeAppClick" title="關閉"></i>


 methods: {
    // 最小化
    minimizeClick() {
      window.ipcRenderer.send('minimize-window');
    },
    // 最大化
    maximizeClick() {
      window.ipcRenderer.send('maximize-window')
      this.isMaximize = !this.isMaximize
    },
    // 關閉
    closeAppClick() {
      window.ipcRenderer.send('close-app');
    }
  }

透過ipcRenderer.send()把點選事件傳送給主程式監聽。

在 background.js 檔案中進行監聽事件的發生,並進行事件的處理:

import { app, protocol, BrowserWindow, ipcMain } from 'electron'

// 最小化
ipcMain.on('minimize-window', () => {
  const win = BrowserWindow.getFocusedWindow();
  if (win) {
    win.minimize();
  }
})

// 最大化
ipcMain.on('maximize-window', () => {
  const win = BrowserWindow.getFocusedWindow();
  if (win) {
    if (win.isMaximized()) {
      win.unmaximize(); // 如果視窗已經最大化,則還原視窗大小
    } else {
      win.maximize(); // 否則最大化視窗
    }
  }
})

// 關閉
ipcMain.on('close-app', () => {
  app.exit()
})

引入ipcMain,並透過ipcMain.on進行監聽事件,然後進行事件處理。
這樣就實現了應用放大、縮小、關閉的效果。

三、封裝axios請求

1.安裝axios

先安裝aioxs:

npm install axios

2.建立公共請求頭

這邊是本地跑後端環境,對vue.config.js中的代理伺服器設定我就不開了,直接設定環境變數使用公共的url。

2.1建立.env.development檔案

.env.development表示開發環境的配置。
設定公共請求頭(請根據自己的實際後端埠號,預設把後端專案拉下來應該是3000埠):

# 介面公共部分
VUE_APP_BASE_URL = 'http://localhost:9080'

2.2建立.env.production檔案

.env.production 表示生產環境的配置。
設定公共請求頭(請根據自己的實際後端埠號,預設把後端專案拉下來應該是3000埠):

# 介面公共部分
VUE_APP_BASE_URL = 'http://localhost:9080'

3.安裝js-cookie

3.1安裝

安裝 js-cookie 用於儲存token。

npm install js-cookie

3.2封裝js-cookie

在src/utils 檔案下建立 auth.js 用於封裝 cookie的相關使用:

import Cookies from "js-cookie";

const TokenKey = 'token'
// 獲取token
export function getToken () {
  return Cookies.get(TokenKey)
}
// 設定token
export function setToken (token) {
  return Cookies.set(TokenKey, token)
}
// 移除token
export function removeToken () {
  return Cookies.remove(TokenKey)
}

4.安裝element-plus

這裡是用來做訊息彈框。

npm install element-plus --save

5.封裝axios

在 src/utils 檔案下新建 request.js 檔案,用於封裝axios。這裡具體的封裝方式就不具體寫出來了,有興趣自己看 request.js 檔案。(主要是這個檔案應該會不斷改動,所以現在我也還不確定最後是怎麼樣)

6.建立api檔案

封裝完 axios 後在 src 下建立一個api檔案,用於儲存介面請求。

四、實現側邊欄

1.建立路由頁面

思路:
1.1.在views檔案下面建立路由頁面,對應左邊側邊欄的頁面;
1.2.在router.js檔案中寫入頁面路由。
image.png

2.實現側邊欄樣式

修改 views檔案下的 SideBar.vue 檔案樣式,最終實現效果如下所示:
image.png
根據上面步驟建立的路由頁面,實現點選的時候切換不同的頁面,並設定樣式。現在基本結構搭建好了,接下來就逐步寫各個頁面的介面和頁面功能,豐富這個應用。

五、實現發現音樂

發現音樂頁面還有6個子頁面。如下所示:
image.png
所以要對路由和頁面進行調整,思路:
1.給原本的/faxian路由後面新增上這6個子路由頁面:
2.在/views/faxian檔案下面建立一個children檔案,用於存放子路由頁面。

1.給/faxian新增子路由

{
    path: '/faxian',
    name: 'faxian',
    title: '發現音樂',
    redirect: '/tuijian',
    component: FaXian,
    children: [{
      path: '/tuijian',
      title: '個性推薦',
      component: () => import('../views/faxian/children/tuijian.vue')
    },{
      path: '/playList',
      title: '歌單',
      component: () => import('../views/faxian/children/playlist.vue')
    },{
      path: '/dj',
      title: '主播電臺',
      component: () => import('../views/faxian/children/dj.vue')
    },{
      path: '/rank',
      title: '排行榜',
      component: () => import('../views/faxian/children/rank.vue')
    },{
      path: '/artist',
      title: '歌手',
      component: () => import('../views/faxian/children/artist.vue')
    },{
      path: '/newSong',
      title: '最新音樂',
      component: () => import('../views/faxian/children/newSong.vue')
    }]
  },

注意:把原本的/faxian路由頁面現在重定向到/tuijian路由頁面,確保點選“發現音樂”的時候“個性推薦”能自動顯示。

2.建立子路由頁面

在/views/faxian檔案下面建立children檔案,用於儲存子路由頁面。
image.png

3.實現頁面

安裝 vue-lazyload 外掛實現圖片懶載入。

$ npm i vue-lazyload -S

網站:
https://github.com/hilongjw/vue-lazyload/tree/next
剩下的頁面就是實現發現的各個子頁面(這部分就是css 和 html 沒有什麼邏輯比較簡單就直接放上效果圖,在實現的過程中發現有的介面引數可能不能用了,建議還是自己實際修改下,或者不呼叫)
實現效果圖:
個性推薦:
image.png
歌單:
image.png主播電臺:
image.png排行榜:
image.png最新音樂:
image.png
這些頁面點進入的歌單現在還沒有實現,還有和播放關聯的部分,後面再去實現功能。並且 歌手應該也是 發現音樂的子頁面,但是實現的時候好像有BUG,就暫時放側邊欄了。

六、實現歌手頁面

歌手頁面原本是在發現音樂頁面的子頁面中的,現在單獨放在側邊欄,所以調整下路由結構和檔案結構。

建立歌手頁面檔案

image.png

新增路由

image.png

實現頁面

主要是實現樣式效果,直接上實現完的效果頁面:
歌手:
image.png

七、建立底邊欄播放音樂

功能思路:
底邊欄一般具有喜歡、列表迴圈、上一首/下一首、播放/暫停、顯示/隱藏歌詞、聲音控制、播放列表。
這邊主要就是播放列表的實現,把播放列表透過vuex進行全域性管理。

css樣式實現

樣式效果如下所示:
image.png
現在基本的樣式就已經完成了,剩下的就是實現功能。

功能實現

基本思路:
因為這邊播放的歌曲是任何頁面都會相關聯的,所以把當前播放的歌曲就直接放在vuex中進行管理,把歌單也是直接放在vuex中進行管理。