總覽javascript
api目錄用於存放 api請求,文件名與模型名稱基本一致,文件名使用小駝峯, 方法名稱與後端restful控制器一致.php
enums 目錄存放 常量, 與後端的常量目錄對應css
icons目錄用於存放圖標, element-ui提供的圖標實在是太少啦.因此我一般會使用 阿里的iconfonthtml
lang目錄存放多語言前端
layouts目錄存放佈局vue
mixins 相似php的trait, 可是它更強大, 完整貼合vue組件的生命週期java
plugins 目錄存放插件配置, 好比 axios,vue-lazy等 (這是從nuxt中學到的概念)react
router目錄存放與 前端路由相關的配置,整體來講相似於laravel的api層ios
store 目錄即vuex的目錄, 相似於前端的model. 其文件與後端model相匹配,採用小駝峯命名laravel
utils 目錄存放輔助函數
views 爲業務視圖層,相信後端同窗也很熟悉.其由vue-router直接調度
main.js 爲app的入口, 相似於後端的index.php
components 目錄, 存放組件.一般是一些可複用的組件會單獨存放在該目錄
整體來講, 已後端的mvc思想來看現代的前端項目是很是的天然的. 後端的model對應前端的store, 後端的router對應前端的router,後端的controller + views 對應前端的views.
就目前來講 vue項目不多用到 class, 所以 .js文件一般都是一個 module, 因此文件名使用小駝峯的形式命名. 若是有類文件,則類文件使用大駝峯的形式命名.
.vue文件 可使用 中劃線和大駝峯兩種命名方式, 參考了element/iview/nuxt項目以後, 推薦統一使用中劃線命名.
全部的文件夾名稱統一使用中劃線命名
引入vue組件時文件時須要轉換成大駝峯
import 'TestTest' from '@/components/test-test'
在template 使用時依舊使用中劃線
<test-test />
其餘規範如變量命名和使用規範 使用eslint的standard 便可很好的解決.
前端存在不少的事件 如change/input/upload/sumit等等,相應的處理推薦使用 handle + 事件名稱, 如handleChange
vue-router 解析當前用戶鍵入的 url, 而後匹配合適的視圖組件加載.
着重介紹一下 我對views目錄下的視圖組件的理解,已修改地址爲例
script部分既控制器部分,其請求數據, 而後注入到view 中, 就像後端的mvc同樣.只不過vue將 vc 其寫入到了一個文件中.這樣理解對於寫事後端的同窗顯得更加的天然
在過去的vue項目中,咱們可能會見到這樣的寫法
// ... views/address/edit.vue
created () {
axios.get('/addresses/1')
.then((response) => {
this.list = resposne.data
})
}
//...
複製代碼
這種寫法無異於後端在控制器中寫sql語句同樣,在工程化實踐中不推薦這麼作,後端經過model來獲取數據會更加的優雅天然.在vue項目中, model既vuex,所以推薦這麼作
若是你對我說的東西一臉懵逼, 那麼你能夠看一下 vuex的文檔. 我如今作的就是用後端熟悉的概念,來描述前端項目的最佳實踐
// ... views/address/edit.vue 控制器+視圖
computed: {
address: () => this.$store.address.itemBy[1] // 從store模型中取出咱們想要數據
}
// ...
複製代碼
// ... store/modules/address.js 數據源
export default {
state: {
itemBy: {}
},
actions: {
...
},
mutations: {
...
}
}
// ...
複製代碼
數據固然是從後端的數據庫中獲取,咱們不能讓前端直接訪問咱們的數據庫,所以咱們會提供api讓前端訪問.store中存在一個發起api請求的地方,既 action.
// ... store/modules/address.js 模型
export default {
state: {
itemBy: {}
},
actions: {
async fetchItem({ commit, state }, { id }) {
// 對axios和api進行了簡單的封裝,使api請求更加語義化
cosnt { data } = await address.show(id)
// action只能經過提交commit來修改state,具體緣由請查看vuex文檔 (其實我也忘了爲啥 (╯﹏╰))
commit('SET_ITEM', data)
}
},
mutations: {
SET_ITEM: (state, item) => {
state.itemBy[item.id] = item
}
}
}
// ...
複製代碼
這樣咱們的模型中就有數據啦
fetchItem
去請求後端呢?router.vuejs.org/zh/guide/ad… vue-router文檔的解答
這裏不推薦在vue原始的生命週期中去調用初始化請求,可能會帶來 數據尚未獲取到,template卻已經被渲染.會形成一些數據不存在的異常,推薦在vue-router的生命週期中去請求數據
// ... views/address/edit.vue
async beforeRouteEnter (to, from, next) {
// 等待模型數據加載完畢,才繼續進行vue組件的生命週期
await store.dispatch('fetchItem', to.params.id)
next()
}
created () {
// 不推薦在這裏調用 fetchItem
}
//...
複製代碼
到這裏你可能發現,這和你平時寫的vue有些不同, 沒有相似 this.data = response.data
這種操做. 相似這種操做其實相似賦值操做,或者稱爲反作用,其引入了時間的概念,使數據的管理變的複雜. 直觀的體現就是咱們可能會有這種多餘的 if(data)
判斷.
固然反作用是難以免的,可是咱們能夠統一的管理他們.相似上面的代碼就是一套我以爲還不錯的方法.從view的角度看, 數據是固有存在存在的,其不須要關心是不是否已經被加載完畢,且store中的不可被view修改,既數據只能單向流動
在store中統一管理數據的另一個好處就是方便持久化
上面的描述實際上表達了一種 發佈與訂閱的模式, 從store到view的數據流是嚴格單向數據流動.
view層不容許直接修改store中的數據,可是view層卻能夠經過發送action來影響數據源.
好比初始化時的dispatch的action,各類event觸發的dispatch. 當數據源發生改變時,做爲訂閱者的view層會很是天然的從新渲染.
這種設計和父子組件相似,vue中子組件不容許直接修改父組件props到子組件的數據,只能經過向父組件emit event. 在view和store之間,這種設計依然合理.
這也意味着應用中全部的數據都遵循相同的生命週期,這樣可讓應用變得更加可預測且容易理解。
上面的圖很好的闡述了這種開發模式. 引自 github.com/sorrycc/blo…
view層的script部分,除了充當了傳統的controller,起到初始化的做用外,實際上還作了更多的事情.
先從data部分提及,在view層會有一些狀態須要記錄, 如 菜單的展開或收起, 彈窗的彈出與關閉. 對於這樣的狀態的管理,一種作法就是將存儲在data部分.
也有人將全部的狀態 也放在 store中的state維護. 既state分爲狀態和數據 兩種類型.
view層的script更重要的部分,是其到了一個交互反饋的做用, 既相似下面的代碼
<template>
<button @click="handleSubmit"/>
</template>
<script>
export default {
data: {},
methods: {
handleSubmit() {
}
}
}
</script>
複製代碼
關於css部分,因爲我的不瞭解css,也不清楚css的業界規範及在vue上的最佳實踐,所以不作過多介紹.
在前面的介紹中, store和api 目錄是和數據掛鉤的,當數據庫定下來,這一部分也就定了下來.
views/components 和業務(ui)掛鉤,須要等設計稿肯定後,這一部分才能肯定下來.
PS設計稿的圖層一般就是組件的拆分規範 😋
views和store之間是一種訂閱和發佈的模式.
store中的state應該如何組織? 對於api請求,咱們常常會看到這樣的json數據
// post
{
id: 1,
title: xxxx,
content: xxxx,
user: {
id: xxx,
nickname: xxx,
avatar: xxx,
},
comments: [
{
id: xxx,
user_id: xxx,
content: xxx,
user: {
// ...
}
},
{
//....
}
]
}
複製代碼
上面的數據結構複雜,嵌套深刻. 若是咱們將他們一股腦的存在 post的state中,會形成數據過於集中,冗餘. comments沒法獨立化更新等等問題. 使得前端 scheme/orm,數據組織的規範化變的迫切須要
可是vue在這方面沒有很好的規範和最佳實踐. react在這方面比較不錯的實踐 github.com/paularmstro…
如何設計良好規範的compoents?
組件的設計在業務層很是的重要,在下一篇我會介紹一下我總結出的一些實踐