先說說寫這個項目的動機。以前工做的時候,雖然作過很多項目,可是由於簽了保密協議,無法把代碼放出來。後來跳槽的時候,拿不出一個完整的我的項目,只能把平時寫的一些小demo拿出來遛遛。因此打算寫一個本身的項目。
這個項目仿的是「米丫天氣」APP。也不知道會不會侵權,反正先放上來再說。功能部分其實很簡單,只是通常的數據獲取,還有用戶管理這一塊的功能。主要是經過這個項目來練習一個完整的項目所須要考慮到的地方。例如:項目文件架構,邏輯組件和公共組件應該如何安排;vuex部分該怎樣劃分和組合;router部分該怎樣配置;前臺和後臺應該若是關聯。
目前項目還有很多bug,先發了,後面再慢慢優化。
這篇文章將把我作這個項目的過程和一些想法描述出來,給本身總結一下。固然,若是能夠幫助到也在寫vue的朋友就更好了。
按字母順序vue
這裏稍微提一下css的解決方案。
以前一直都在使用sass,只是node-sass很難安裝成功,因此就改用stylus。二者的差異我感受不是很大。另外是.vue
文件中的style
部分,即便添加scoped
屬性,仍是會有可能發生衝突。例如父子組件的樣式中都擁有同一個類名,這時就會發生衝突。目前正在打算準備使用css-modules
。
對於路由,各位寫過vue的朋友應該都不陌生了。這裏主要講一下路由的結構,我把它理解爲「分層」,也就是router-view
組件的位置。以前在看一個ui框架的時候(忘了是啥框架了),留意到它的頁面分層的概念。大概是這樣的:
1.遮罩層(loading之類的) 2.交互層(模態框什麼的) 3.消息提示層(本項目中的toast組件) 4.主內容界面 5.嵌套的子路由
目前就只想到這些了。node
另外是router.js
文件的寫法。在本項目中,我把全部的路由寫在同一個文件,是由於路由比較少,若是在路由結構多而複雜的項目,這種寫法會很頭疼。建議的寫法是將各個邏輯模塊的路由分開,最後在主路由裏引入。大概是這樣的:react
// router/module-a.js const View1 = () => import('@/view/view-1') const View2 = () => import('@/view/view-2') export default [ { path: '/home/module-a/view-1', name: 'view-1', component: View1 }, { path: '/home/module-a/view-2', name: 'view-2', component: View2 } ]
// router/index.js import Vue from 'vue' import Router from 'vue-router' import ModuleA from './module-a' Vue.use(Router) const router = new Router({ routes: [ ...ModuleA ] }) export default router
噢,對了。以前還在sf
找到一個小技巧:如何在切換路由時,修改瀏覽器標籤的標題。ios
router.beforeEach((to, from, next) => { window.document.title = to.meta.title || '米丫天氣' next() })
注意:我試過把title
寫在路由屬性中而不是meta
裏,發現是不可行(多寫一層也沒啥大問題)。git
在項目的store裏面,只有modules
,沒有根層的state,這個主要是受redux的一些影響吧。把全部須要緩存的數據放在一個store樹裏面,每一個模塊單獨控制。另外在store/index.js
裏面會看到setState
這個方法。這個也是受react的影響(this.setState 方法),也是一個小技巧吧。vuex裏面提到mutations
只處理同步的操做,actions
處理異步操做。那麼基本上每一個action
都會commit
一個或者多個mutation
。而mutation
是應該只修改一個state
仍是多個?這個問題根據不一樣的業務邏輯會有不一樣的結果。因此定義了setState
這個通用的方法。至於action的寫法,本項目裏的寫法我感受仍是有點問題的。下面是最近找到的關於async
函數的寫法:web
async function getSomething() { try{ const result = await apiGetSomething() if(result.status === 'ok') { // some code } } catch(err) { console.error(err) } }
關於這種寫法目前還在思考中,後續會進行修改。vue-router
上述提到的action
裏使用到請求數據的api方法。api方法都會返回一個promise
對象,同時也是一個異步函數。
說到api就要提一下easy-mock。這個網站是基於mock.js
,能夠很方便生成自定義接口,就算你不會後臺,也能夠很快速簡單的編輯本身想要的接口。使用方法嘛,仍是直接看官方教程吧。
由於本項目要使用的數據比較簡單,因此接口部分沒有什麼好說的了。vuex
assets
部分的圖標會被看成依賴,引用的時候使用import
引入,而後還不能直接使用,必須放到配置項裏面,通常是放在data
。
而後是style
,這裏主要是配置全局樣式變量,例如主題色之類的。
具體方法:
在build/utils.js的generateLoaders
中修改.
添加全局變量的文件配置redux
const stylusOptions = { import: [path.join(__dirname, '../src/assets/style/theme.styl')], paths: [path.join(__dirname, '../src/assets/style/'), path.join(__dirname, '../')] }
其中的theme.styl
定義全局變量的文件
修改stylus
的配置
stylus: generateLoaders('stylus', stylusOptions), styl: generateLoaders('stylus', stylusOptions)
基本上我把能夠單獨提出來的內容都寫成公共組件。另外單獨寫了一個index.js
文件。裏面將全部的公共組件引入而後打包導出,這樣在使用的時候就能夠少寫不少代碼,這個技巧是以前看vux-ui
裏面的組件定義學到的。
// components/index.js const TabBar = () => import('./TabBar') const AddressBar = () => import('./AddressBar') const TmpPanel = () => import('./TmpPanel') // ... export { TabBar, AddressBar, TmpPanel //... }
// 邏輯頁面引入 import { TabBar, AddressBar, TmpPanel } from '@/components'
待續。。。