一、添加columnDetail 頁面
首頁有專欄列表(ColumnList組件),專欄列表中有很多專欄,然后點擊某個專欄就進入專欄詳情頁(ColumnDetail組件),專欄詳情頁中有很多文章,點擊某個文章就進入文章詳情頁()這樣子
數據我們是設計成什么樣子呢,如下
testData是專欄數據,testPosts是文章數據,就是每個專欄里面都對應著它們相對應的文章們,它們是怎么聯系起來的呢也就是說怎么知道這個文章是哪個專欄里的呢?通過文章中的columnId=專欄中的id,則說明這個文章是這個專欄的。
那url中參數怎么與專欄和文章聯系起來呢,我們之前做路由跳轉的時候跳轉到columnDetail專欄詳情頁的時候不是做了動態路由嘛,通過加:id,到時候url中我們通過在url的column/后加2,那么它就會跳轉到query中id為2的數據頁面中。所以我們url中這個參數我們讓它等于專欄的id,即url中這個參數是2時,則讓它是id為2的專欄。
所以當url中該參數為2時,則找出專欄中id為2的數據,因為專欄詳情頁中需要展示出該專欄下的文章,所以還需要獲取這個專欄下的文章們,而專欄和文章是以專欄id(和url那個id其實是相等了) = 文章columnId,即過濾出columnId等于2的即可找出這個專欄下的文章了
如下
數據獲取到了,然后專欄詳情頁中不是有文章們嘛,就建個PostList組件,專門放該專欄詳情頁下的文章列表
二、vuex
1、什么是狀態管理工具
我們現在有3個頁面了,分別是首頁、登錄頁、專欄詳情頁,這三個頁面中都有一些共同的數據需要獲取和處理,現在我們的做法是把這些共用的數據都保存在一個全局的js對象中
全局對象的弊端:
·數據不是響應式的
·數據修改無法追蹤
·不符合組件開發的原則
狀態管理工具的基本原則:
·一個類似object 的全局數據結構 - 稱為store (里面的數據是不能隨便更改的,只能通過action修改)
·只能調用一些特殊的方法來實現數據修改(所以store中的數據變化是可追溯可控制的)
2、vuex 簡介 和 安裝
單向數據流理念,state決定了view長什么樣,view上可以通過actions方法修改state
但是,當多個組件共享狀態時,單向數據流就容易被破壞。
vuex的核心是store,store就像一個倉庫,store包含應用中大多數狀態(state)
vuex的特點:
·狀態存儲是響應式的
·不能直接改變store中的狀態,唯一途徑就是顯式地提交(commit) mutation
安裝vuex:npm install vuex --save
3、vuex 整合當前應用
創建一個store.ts如下
然后我們需要把這個store和vue聯合起來,去main.ts,如下即把store和整個應用整合到了一起
接下來看看在組件中怎么拿到數據,在home.vue中舉個例子,如下
我們哪里要用就引入vuex的useStore,然后通過 useStore() 就可以拿到vuex中的store了
如下發現沒有自動補全,我們可以引入store的GlobalDataProps
當做泛型傳入進去后就可以出現自動補全了
由于vuex的狀態存儲是響應式的,從store實例中讀取狀態最簡單的方法是在計算屬性中返回某個狀態,如下
第二個任務就是修改數據
我們希望登錄以后,vuex數據發生變化,然后觸發頁面上的變化。登錄后就把vuex中當前登錄人的信息從未登錄變成登錄,從某某人變成當前人這樣子
然后到App.vue中引入vuex,然后 useStore() 拿到vuex中的store,然后在computed中通過store.state.user拿到store中的user信息
到login.vue中,我們希望它登錄后跳轉到首頁去,并且嘗試修改,注意修改一定要用commit。
如下,commit就會去觸發store中的mutations,commit('login') 即觸發mutations中的login函數,如下這個login函數中就會去修改store中的user信息
如此,去登錄,發現登錄成功后就跳轉到了首頁了
4、使用vuex getters
前面我們知道了怎么給整個頁面添加vuex store,同時知道了怎么在vue組件中獲取store的數據,以及怎么觸發mutation,從而引起應用的更新。
接下來我們了解getter,有時候我們需要從store的state中派生出一些狀態,比如說我們對專欄們進行過濾,找出id大于2的有多少專欄,我們就需要這樣:store.state.columns.filter(c=>c.id>2).length,通過這么一長串邏輯就拿到了有多少專欄id大于2
假如我們在多個頁面當中都要使用的話,就需要反復重復這么長的代碼,就比較麻煩
vuex就允許我們在store中定義一個叫getter的東西,可以認為是store的一個計算屬性,就和計算屬性一樣,getter返回值會根據它的依賴被緩存起來,且當它依賴值發生改變才會重新計算。
如下,接下來我們使用getter,就直接通過store.getters.biggerColumnsLen就可以拿到id大于2的專欄數量了
我們來到專欄詳情頁,我們想通過getters,查詢具體是哪個column
如下是還沒用getters的
這里和之前的區別就是,我們需要傳入一個稱為currentId的值,因為這個值是在頁面上才能拿到的,所以你在頁面拿到后,你得傳入到getters中,然后拿currentId做上面的這些操作
在getters中我們可以讓它返回一個函數來實現給getters傳參,它在你對store里的數組進行查詢的時候非常有用,如下
三、添加新建文章頁面
每個column專欄都有一個作者(有columnId,id等),它們兩個是一對一的關系,這個作者信息和當前這個用戶登錄信息使用的是同一個數據結構,所以我們在新建文章的時候,可以從當前登錄用戶的信息中拿到這個columnId,然后創建定義的文章
就是你創建文章,你得知道這個文章是誰寫的?(這里有點?)
views中新建一個CreatePost.vue即新建文章頁面,新建文章中也是用的validate-input
然后到router.ts中加入新建文章的頁面路徑,并且在新建文章按鈕中把a標簽變成router-link標簽,:to指向/create,這樣點擊新建文章時就會跳轉到新建文章頁面
應該讓validateInput支持textarea,添加一個屬性讓它判斷要顯示哪個節點就好
如下,設置一個類型是input或者textarea,然后props中接入一個tag,這個tag就是要展示input還是textarea,然后input標簽中就通過v-if來判斷是input類型還是textarea類型框
然后新建文章這里,我們傳入tag=textarea,這樣子在新建文章頁面
如果要創建文章,我們就需要拿到用戶信息的columnId,所以我們給我們的數據結構做一些修改
如下:在mutations中定義createPost,接收newPost即新建的文章,把傳過來的新建的文章追加到state的posts中
如下:新建文章點擊提交按鈕后,觸發onFormSubmit事件,從當前用戶中獲取columnId做當前新建文章的columnId,然后新建newPost對象,這個對象中放置這個新建文章的信息,然后commit調用vuex的mutation,把當前新建文章追加到state中的posts中,并且往router中push如下路徑
四、vue router 添加路由守衛
1、 前置守衛
接下來談談不同路由的權限問題,有些路由有某些特定權限才能使用,比如新建文章頁面只有在用戶登錄以后才可以使用,如果用戶未登錄,直接訪問新建頁面的話,一般會重定向到另外一個路由,比如說此時重定向到login頁面去登錄;比如說登錄和注冊頁面,在未登錄的時候就可以訪問,如果已經登錄,此時去訪問這兩個頁面一般會重定向到首頁去。
由于我們整體應用是SPA,即所說的單頁面,那我們的路由使用了vue-router,我們就去看看vue-router怎么完成這個任務,就是這個導航守衛
現在我們就來注冊一個全局前置守衛,判斷一下加入用戶是否登錄,如果沒有登錄,那么就讓頁面跳轉到login頁面,如上,注冊守衛其實很簡單,我們需要在router的實例上拿到beforeEach方法,
beforeEach方法就是當一個導航觸發的時候,這個beforeEach要全局前置守衛,就按照創建順序調用,守衛是一步一個解析執行,此時導航的所有守衛resolve完之前一直處于等待中
to就是即將到達的路由,from是正在離開的路由,next是一個function
?從首頁到新建文章頁,可以看到to即將到達的路由變成/create,from當前路由是首頁
但是此時我們發現,已經點擊新建文章按鈕了,卻沒有跳轉到新建文章頁面,這是因為最后一個參數next在作祟
next是一個function,我們一定要調用該方法來resolve這個鉤子,讓這個路由繼續前進到下一個鉤子,此時我們就直接讓它next()繼續前進不要停在這里即可到新建文章頁面
如果為false則不能跳轉了
然后我們來完成,當沒有登錄的時候就跳轉到登錄頁面去
如下,如果不是跳轉到登錄頁,并且當前沒有登錄,即當前沒有登錄還想跳到非登錄頁就讓它重定向回登錄頁得先登錄再去其他頁面
此時如果沒有登錄,那么到首頁就會重定向到登錄頁,或者到新建文章頁也會重定向回登錄頁
這個功能是實現了,但是這不是我們最終想要的結果,因為有些頁面即使沒有登錄也是可以訪問的,只有特定的頁面才需要登錄后才能訪問,所以我們還需要再把這個功能進化一下
2、使用元信息完成權限管理
現在路由可以被這個守衛操控,在跳轉之前進行對應的檢查,但是現在我們的規則是眉毛胡子一起抓,用一個規則把所有頁面都拒之門外。
第一種是home和columndetail這兩個頁面是無論有沒有登錄都是可以訪問的;第二種是create頁面是只有登錄的用戶才可以訪問的;第三種是login這個頁面,用戶登錄以后他訪問就會直接跳轉到首頁;所以有三種對應的路由,又代表了三種不同的行為,也就是說我們需要在特定種類的路由上面添加獨特的信息進行區分,看文檔如下
要知道怎么在路由上添加元信息,即在路由上添加meta: { xx: xx }
路由元信息,也就是說我們在定義路由的時候可以配置一個叫meta的字段,這個就是這個元信息,這個meta字段下面我們可以使用Object形式寫出來我們所需要的一些額外的信息
這時候我們就在create頁面上面添加一個元信息,添加完了后我們需要到beforeEach中訪問這個信息,如下
我們訪問create可以看到打印出了requiredLogin:true,既然我們能拿到這個信息,后面的判斷就可以做了
我們只需要用meta中的信息判斷該路由是否登錄就可以了
如下create頁面是只有登錄的用戶才可以訪問的
登錄用戶訪問登錄頁面就會跳轉到首頁