專案地址:https://huangxizhou.com/project/iMap
技術棧
專案目錄
.
├── LICENSE
├── README.md
├── build··········································electron-packager 打包出來的各平臺應用
│ └── icons······································各平臺應用圖示
│ ├── icon.icns
│ ├── icon.ico
│ └── icon.png
├── dist···········································應用構建後的程式碼目錄
│ ├── electron
├── package.json···································應用層級的 package.json
├── src············································electron 入口檔案資料夾
│ ├── index.ejs
│ ├── main·······································electron 主程式檔案資料夾
│ │ ├── index.dev.js
│ │ └── index.js
│ └── renderer···································Vue 相關的目錄
│ ├── App.vue································單頁面的主結構
│ ├── assets·································靜態資原始檔夾
│ │ ├── img································專案配圖
│ │ │ ├── china.png
│ │ │ ├── excel_example.png
│ │ │ └── world.png
│ │ └── my-theme···························iVew 自定義主題相關目錄
│ ├── components·····························Vue 相關元件目錄
│ │ ├── Layout·····························佈局元件
│ │ │ └── Header.vue·····················導航欄
│ │ ├── Page·······························頁面元件
│ │ │ ├── Auth.vue·······················使用者許可權獲取元件
│ │ │ ├── Chart.vue······················製作地圖元件
│ │ │ ├── ForgetPassword.vue·············忘記密碼元件
│ │ │ ├── Help.vue·······················幫助文件元件
│ │ │ ├── Home.vue·······················主頁元件
│ │ │ ├── Login.vue······················登入頁元件
│ │ │ ├── Map.vue························地圖型別元件
│ │ │ ├── MyProject.vue··················我的專案元件
│ │ │ ├── Register.vue···················註冊元件
│ │ │ └── Update.vue·····················登入元件
│ │ └── Ui·································功能元件
│ │ ├── AddPointModal.vue··············新增地點元件
│ │ ├── DelPointModal.vue··············刪除地點元件
│ │ └── EditPointModal.vue·············修改地點元件
│ ├── data···································Echarts 相關資料存放資料夾
│ │ ├── china.json·························中國地圖 json 資料
│ │ ├── map.js·····························匯入座標資料
│ │ └── world.json·························世界地圖 json 資料
│ ├── filter·································Vue 過濾器目錄
│ │ └── index.js
│ ├── main.js································Vue 入口檔案
│ ├── router·································Vue 路由檔案
│ │ └── index.js
│ ├── server·································ajax相關操作檔案
│ │ ├── ajax.js····························二次封裝ajax
│ │ └── url.js·····························介面別名
│ ├── store··································Vuex 資料目錄
│ │ ├── actions.js·························涉及多個 mutations 的 action 集合
│ │ ├── index.js···························Vuex 入口檔案
│ │ ├── modules····························模組目錄
│ │ │ ├── excel.js·······················Excel 資料相關模組
│ │ │ └── user_info.js···················使用者資料相關模組
│ │ └── mutations_types.js·················mutation-types 宣告
│ ├── tool···································工具資料夾
│ │ └── index.js
│ └── version································應用版本資料夾
│ └── version.js
└── yarn.lock
介面與資料問題
本專案使用的是官方推薦的axios
Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。
本來之前想使用 prototype
來寫侵入式程式碼,但維護起來還是很麻煩,最終還是擼了個開箱即用的 axios 二次封裝的js檔案出來:
// POST 請求
post({...obj}) {
return new Promise((resolve, reject) => {
axios.post(obj.url, obj.data, {
headers: {
"Authorization": user && user.accessToken
}
}).then((data) => {
if(data.data.code === 0) {
// ...
} else if (data.data.code === 1) {
// ...
} else {
// ...
}
}).catch((data) => {
reject(data)
})
})
}
一般來說,在接收到後端返回的資料時,可以使用resolve(data.data)
來直接處理資料,當然也可以按需引入一些 UI 元件與過濾器,直接在 ajax 封裝檔案中就可以過濾資料並進行全域性提示,提升使用者體驗。
對於 GET 請求,由於專案有使用到百度地圖開放 API 來獲取城市經緯度,涉及到 jsonp
跨域問題,尷尬的是 axios 官方說明不會支援 jsonp
,所以只能引入 jsonp
這個 npm 包,並且將請求此介面從 GET 請求中單獨提取出來。
getLocation({...obj}) {
return new Promise((resolve, reject) => {
jsonp(obj.url + `?` + qs.stringify(obj.data) , null, (err, data) => {
if (err) {
Message.error(`請求錯誤`)
} else {
if(data.status === 0) {
resolve(data)
}
}
})
})
}
GET 請求 ajax 程式碼封裝與 POST 基本一致,只是將 obj.data
換成 { paramas: obj.data }
即可。
關於 Vuex 的使用
Vuex是個能把元件的共享狀態抽取出來,當做一個全域性單例模式進行管理。這樣不管你在何處改變狀態,都會通知使用該狀態的元件做出相應修改。
在本專案中,需要提取到全域性管理的資料有 userInfo
和 excelData
,前者儲存在全域性中,可以減少請求使用者資訊介面的數量,節約資源,後者由於 Excel 檔案上傳到後端後只做解析,不儲存,所以全域性管理 excelData
很重要。
在這裡就單獨說一說新增城市座標的操作好了:
首先是 mutations_types
宣告檔案
// mutations_types.js
export const ADD_EXCEL_DATA = `ADD_EXCEL_DATA`
...
宣告 state
和 mutations
在 Vuex 中,更改 Vuex 的 store 中的狀態的唯一方法就是 mutations
// modules/excel.js
import * as types from `../mutations_types`
// state
const state = {
excelData: {}
}
// mutations
const mutations = {
...
// 新增 excelData
[types.ADD_EXCEL_DATA] (state, data) {
state.excelData.data.push(data)
},
...
}
// 匯出 state, mutations
export default {
state,
mutations
}
然而,Mutations 必須是同步函式,所以我們還需要 actions
// actions.js
import * as types from `./mutations_types`
...
// 新增 excelData
export const addExcelData = ({ commit }, data) => {
commit(types.ADD_EXCEL_DATA, data)
}
...
最後,再在入口檔案注入 modules 和 actions即可
...
export default new Vuex.Store({
actions,
modules: {
excel
}
})
這樣一來,關於 excelData 的 資料管理的任督二脈已經打通,現在就看如何來使用了
在元件中可以使用 mapState
、mapActions
輔助函式來簡化程式碼mapState
函式用在計算屬性中
// AddPointModal.vue
computed: {
...mapState({
excelData: state => state.excel.excelData,
countAlias: `excelData`
})
}
mapActions
函式在本專案中用於 methods 中
methods: {
...mapActions({
addExcelData: `addExcelData`
})
...
}
在函式中呼叫
this.addExcelData(Arrary)
這樣就成功將一個新的陣列元素新增到 excelData
中了。
如何獲取 Excel 資料
本專案採用 Leancloud 來作為後端支援,使用的是Node.js(express),對於獲取使用者的 Excel 資料並不想儲存資料的話,本專案的思路是將 Node 作為一個檔案中轉的存在,上傳使用者 Excel 檔案至伺服器後,在 /public
目錄下儲存Excel檔案,再在下次使用者上傳時,清空 /public
目錄。
使用者 Excel 處理的庫本專案選擇的是 node-xlsx
特別注意的是,在前端檔案中,上傳使用者 Excel 檔案是需要使用 formData
來上傳的
let formData = new FormData()
formData.append(`file`, this.file)
後端使用 formidable 這個庫來接收 Excel 檔案並使用 form.parse
來解析。
關於使用 Echarts
ECharts,一個純 Javascript 的圖表庫,可以流暢的執行在 PC 和移動裝置上,相容當前絕大部分瀏覽器(IE8/9/10/11,Chrome,Firefox,Safari等),底層依賴輕量級的 Canvas 類庫 ZRender,提供直觀,生動,可互動,可高度個性化定製的資料視覺化圖表。
對於在 Vue 專案中使用 Echarts , 本專案採用的是 vue-echarts
在 chart.vue
檔案中,我們利用一個三元運算子來動態切換地圖型別
this.selectMapType === `china` ? ECharts.registerMap(`china`, chinaMap) : ECharts.registerMap(`world`, worldMap)
對於地圖資料的匯入,本專案的方法是的是匯入一個物件,返回地圖 option
資料:
// map.js
...
export default {
getMapData({...obj}) {
...
return {
// 地圖配置資料
}
}
}
再在前端檔案中使用這個函式即可: this.option = map.getMapData(this.excelData)
Vue 中父子元件雙向繫結
在本專案中,我將新增、編輯、刪除地點的彈窗全部提取到公用 Ui 元件資料夾中,然而這就需要利用 v-model 來實現元件 props 雙向繫結
// template
<Modal :value="value" v-model="showModal"></Modal>
// script
export default {
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return: {
showModal: false
}
},
watch:{
value(val) {
this.showModal = val
},
showModal(val) {
this.$emit(`input`, val)
}
},
mounted() {
if (this.value) {
this.showModal = true;
}
}
}
這樣就能使用value來儲存 v-model 的值,從而進行雙向繫結。
在MacOS 上打包 Win32 軟體包
在 electron-vue 文件中有這麼一句話:
If you are wanting to build for Windows with a custom icon using a non-Windows platform, you must have wine installed.
那麼我們就來安裝wine。首先確保你的 Mac 已經安裝 homebrew,執行 brew install wine
來安裝wine。
接下來,會出現一個錯誤提示,提示我們需要安裝 Xquartz,按照錯誤提示給的下載網址下載即可。
再次執行 brew install wine
安裝成功後在專案目錄下執行 npm run build:win32
就可以打包成Win32 安裝包了
求一份工作~
2019年畢業生求帶走