使用vue一年多了,作了一個javaee的項目(全棧,前端使用的mvvm框架vue),三個移動端項目,其中兩個釘釘子應用(釘釘的坑不少,心累),一個微信的(ing)。本身也慢慢摸索出一些項目中的最佳實踐,整理了一下,作個記錄一塊兒交流。若是你在閱讀過程當中,以爲我某些地方作的不對或者有更好的方法時,歡迎交流~javascript
清晰的目錄結構不只能夠展示一個團隊的水平,並且別人維護(接鍋)的時候,也能更好的理解你的項目。這個每一個團隊都有本身的標準或者風格,沒有固定的格式。我通常是這麼安排的(vue-cli項目),下面是src目錄:css
—— src
|—— assets // 項目資源目錄
|—— styles // 樣式文件
|—— reset.scss // reset css,會在 /src/main.js 中被導入
|—— variables.scss // 項目中的變量,混合(mixin)等公有樣式變量
|—— ...
|—— images // 圖片
|—— fonts // 字體
|—— ...
|—— components // 組件目錄
|—— layout // 佈局相關組件
|—— Header.vue // 頭部
|—— BottomMenu.vue // 底部菜單
|—— ...
|—— common // 公有組件
|—— base // 基礎組件
|—— ...
|—— pages // 頁面目錄
|—— user // 用戶相關頁面
|—— Login.vue // 登陸頁面
|—— Register.vue // 註冊頁面
|—— Info.vue // 詳情頁面
|—— order // 訂單相關頁面
|—— List.vue // 訂單列表
|—— Detail.vue //訂單詳情
|—— ...
|—— Home.vue // 主頁
|—— ...
|—— router // 路由
|—— modules // 存放各個模塊的路由
|—— user.js // 用戶模塊
|—— order.js // 訂單模塊
|—— index.js // 路由主js,整合各個模塊,而且還會定義一些全局鉤子等其餘
|—— store // 全局狀態管理目錄
|—— mutation-types.js // mutation types
|—— index.js // 主js,整合各個模塊的
|—— actions.js // actions
|—— modules // 各個模塊的states
|—— user.js
|—— order.js
|—— common // 全局工具方法
|—— data-format.js // 數據轉換
|—— http.js // 網絡請求
|—— ...
|—— App.vue
|—— main.js
|—— init-plugins.js // 依賴的第三方的初始化,會在main.js中引入
以上只是我我的的習慣,不過這個結構要根據具體的項目狀況調整。沒必要爲了模塊化而模塊化。若是你的項目業務邏輯不復雜,整個項目也就十幾個頁面,能夠適當的刪減部分模塊。html
你的項目可能須要一些這樣的組件,來提高用戶體驗。前端
no-data-foundvue
這個存在的場景是,好比你加載數據列表或者篩選列表查詢等數據操做,若是請求成功可是沒有數據,這時候有必要提供一個no-data-found的組件。html5
errorjava
當你的應用出錯的時候,好比網絡超時加載不了數據,也能夠給一個組件作提示ios
在開始咱們項目以前,咱們應該知道,有哪些方法是必要的、共有的,相似於咱們的工具方法同樣。這裏我羅列一些供參考:git
日期與字符串轉換
github
關於日期都全部操做,建議採用
momentJs
。功能強大並且兼容性好,我深深的記得以前一個釘釘項目中日期操做不兼容iphone手機的時候,那個bug讓我找了半天才找到根源。
官網傳送門:http://momentjs.cn/
數字與字符串轉換
你的應用應該包含一套用於提示用戶的組件:
Toast
用於提示用戶一些信息
Confirm
用戶提示用戶是否確認接下來的操做。對於一些重要的操做,好比提交表單,刪除信息等操做,務必使用。
Loading
當用戶在上傳或者下載圖片等其餘資源的時候,用於提示進度信息。固然這個請求方法要可以得到到相應的進度信息才行,僞造須謹慎(手動斜眼笑)。
Spinner
加載數據時的提示,俗稱「菊花圖「
mint-ui:http://mint-ui.github.io/docs/#/
vux:https://doc.vux.li/zh-CN/
這裏要說的是,你能夠對這些方法進行二次封裝,以便更方便的使用。包裝後,可能就能夠像下面這樣使用了:
Dialog.toast('cool')
Dialog.confirm('Are you sure?',()=>{Dialog.toast('confirm')}) Dialog.spinner('loading...')
咱們知道vue的SFC(單文件組件,即以.vue結尾的文件),提供了三個基礎的頂級標籤:<template>
, <style>
,<script>
。我我的比較喜歡把樣式也寫進SFC中,由於這樣針對性很強,調試某個頁面樣式的時候,只要打開一個文件就好了。(這麼說是由於我一開始是隔離全部的css文件到assets目錄下,這樣雖然代碼看起來漂亮了,你只要在style標籤內import樣式就能夠了,可是調試的時候很是不方便。)
固然,前提是在你使用css預處理器的狀況下:
爲了系統的UI一致性(consistency),咱們的設計稿確定是一套統一的主題的。因此咱們不一樣頁面的邊框粗細顏色,按鈕背景色,字體大小顏色,一級邊框二級邊框…,一級標題二級標題…等等衆多的樣式須要保持一致。若是在每一個頁面都定義一次,這可行,可是工做量和作法都是不值得提倡的。
有一些loader就是負責處理這類狀況的,以sass爲例,你可使用 sass-resources-loader
來完成全局變量的共享。使用方法也很簡單:
- 安裝
npm install sass-resources-loader --save-dev
scss: generateLoaders('sass').concat({
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/assets/styles/variables.scss')
}
})
接下來就能夠在任意的組件中使用這個varibles.scss裏面的樣式了。
有的ui框架會修改默認樣式,並且不一樣瀏覽器的樣式標準也有一些不一樣,因此resetcss頗有必要。國內諸如淘寶,百度等都有本身的resetcss,你能夠參考這篇博客得到幫助,也能夠根據這個自定義本身項目的resetcss。
https://meyerweb.com/eric/tools/css/reset/
<style scoped>
with <style>
也許你遇到過這種狀況,須要修改某一個ui框架的默認樣式,可是在scoped的style塊中修改不成功。不得不將style塊的scoped屬性拿掉,或者將這個要改變的樣式放進全局樣式裏再在main.js中導入,或者直接將樣式定義在App.vue裏面。這些都是可行的,可是要注意命名空間要是正確的,否則是找不到樣式的。
這裏提供另外一種方法。其實在vue的SFC中,是容許多個style塊的。你能夠像下面這樣使用:
<style scoped lang="scss"> .order-detail { // put your local style here } </style>
<style> .mint-button{ // put your global style here if you want to change the lib's style } </style>
可能不少人用vue-router的時候,只是用來作路由跳轉,配置路由的時候,添加一個path和component就完事了。若是這樣能知足你的全部需求,那也ok。可是有一些業務場景,使用meta屬性能夠很是巧妙的解決問題。
這裏分享一下我使用過的例子:
想要動態的顯示應用/系統的標題,你會怎麼作呢?
你可能會在每個頁面的鉤子中給document.title賦值,可是有更簡單的方法,好比我定義一個下面的router:
{ name:'user-detail', path:'/user-detail', component: UserDetail, meta: { title: '用戶信息' }
},
接着在App.vue裏面,添加下面的代碼:
watch:{
'$route':function(to, from){
document.title = to.meta.title
}
}
這樣每次定義router的時候,只要填寫了meta屬性,系統的title就會跟着改變了。
另外,在App.vue裏面watch的$route,還有不少用處,好比處理前進後退的動畫等。
咱們知道vue提供了一個<keep-alive>
組件,用戶緩存組件以得到更快的交互。簡單介紹一下,當設置某一頁面爲keep-alive的時候,它的mounted只會在第一次加載的時候執行一次,後面在打開該頁面的時候都不會執行。可是activated
和deactivated
兩個鉤子能夠捕獲頁面進入和退出的動做。
根據不一樣的業務邏輯,有些頁面須要緩存有些頁面不須要緩存,因此咱們也能夠定義在router中:
{ name:'user-detail', path:'/user-detail', component: UserDetail, meta: { title: '用戶信息', keepAlive: true }
},
而後修改主路由入口的代碼(App.vue)
<template v-if="$route.meta.keepAlive">
<keep-alive>
<router-view/>
</keep-alive>
</template>
<template v-else>
<router-view/>
</template>
這樣你就能夠根據本身的須要,決定哪些頁面須要緩存了。
關於<keep-alive>
組件的更多用法,參考:https://cn.vuejs.org/v2/api/#keep-alive
咱們知道,vue-router提供了頁面的滾動行爲。vue-router的滾動行爲
咱們也能夠在路由中配置該屬性,來細粒度的控制咱們頁面的滾動行爲。
scrollBehavior方法,摘自官網例子 。我給註釋翻譯了一下。
https://github.com/vuejs/vue-router/blob/next/examples/scroll-behavior/app.js
// - 只在支持html5 history 模式的瀏覽器中有效
// - 默認無滾動行爲
// - 返回false的話,會阻止滾動行爲
const scrollBehavior = (to, from, savedPosition) => {
if (savedPosition) {
// savedPosition 只在popstate的導航中有效
// popstate:https://developer.mozilla.org/zh-CN/docs/Web/Events/popstate
return savedPosition
} else {
const position = {}
// 經過返回選擇器來滾動到錨點位置
if (to.hash) {
position.selector = to.hash
}
// 檢查路由元數據(meta)配置中是不是返回頂部的需求
if (to.matched.some(m => m.meta.scrollToTop)) {
// 設置滾動位置的x和y座標:頂部
position.x = 0
position.y = 0
}
// 若是返回的位置是假值(falsy)或者是空對象,將會返回當前滾動的位置
return position
}
}
OK,今天就說這麼多,還有一些,好比異常處理,vuex使用場景,一致性(consistency)等,下次有機會在寫一篇,今天頭有點痛,得睡覺了。
有一些實踐我已經用到這個項目https://github.com/JerryYuanJ/a-vue-app-template中了,可是因爲這個項目寫的時間比較早,並且主要是爲了熟悉vue和其餘一些練習爲主,那時候還不懂事,因此不少地方仍是得改的,若是你須要拿項目來練手上面的一些實踐的話,這會是個不錯的選擇。你能夠pull requeset,我會merge的~歡迎star