本文所涉及代碼全在vue-cnodevue
前面兩篇都是介紹組織結構和vue-router,從本文開始咱們將講一些如何優雅的用vue編寫單頁應用。首先咱們從登陸頁面以及開始,由於後續不少其它的頁面都須要登陸信息。node
首先咱們第一步確定是指定一條路由啦,在src/config_router.js
裏面增長一條路由react
export function configRouter (router) { router.map({ '/login': { name: 'login', title: '登陸', // es6箭頭函數 component: (resolve) => require(['./components/login/login.vue'], resolve) } }) }
上面compenents部分,使用了webpack代碼分割功能,這樣他會安需加在./components/login/login.vue
組件。也能夠這樣寫component: require('./components/login/login.vue')
,這樣就不會按需載入了。編譯的第一個文件就有這個。webpack
而後咱們須要在src/conponengts/
下面建立一個login的文件夾一個login.vue的文件。最開始login.vue裏面應該是這樣的:git
<style lang="styl" src='../../assets/styl/login.styl' scoped></style> <template> <section class="content"> // something </section> </template> <script> export default { } </script>
上面是vue-loader的結構,你能夠看到,樣式、模版、js三者很清晰,不像react中的寫法全是js,jsx感受還有點混亂(我的觀點)。es6
上面的style中lang
是指定解析語言,咱們這裏用的是stylus,而後src
指定文件路徑,最後的一個scoped是指定樣式只在當前組件生效。template和script裏面的內容就部多介紹了,如今開始編寫業務邏輯。github
咱們須要保存登陸的信息,由於在後續的全部接口中去獲取數據咱們都須要服務器返回的用戶信息。這裏咱們將獲取用戶信息、保存用戶信息邏輯所有拆出來交給vuex。vue-router
先安裝vuex:npm install vuex --save
,而後咱們建一個store
。在src文件夾下面建立`/vuex/modules/user_info.js:vuex
// content import { SET_BASEINFO, SET_DETAIL } from '../mutation_types' const state = { // 保存第一頁數據 id: '', accessToken: '', loginName: '', avatarUrl: '', score: '', recentTopics: '', recentReplies: '', github: '', createAt: '' } const mutations = { // 設置 token 登陸名 頭像 [SET_BASEINFO] (state, data) { try { state.id = data.id state.accessToken = data.accesstoken state.loginName = data.loginname state.avatarUrl = data.avatar_url } catch (err) { console.log(err) } }, [SET_DETAIL] (state, data) { try { state.score = data.score state.recentTopics = data.recent_topics state.recentReplies = data.recent_replies state.github = data.githubUsername || '' state.createAt = data.create_at } catch (err) { console.log(err) } } } export default { state, mutations }
上面有個mutation_types
是用來讓mutation惟一的,在mutation_types裏面是這樣的:
// user info export const SET_BASEINFO = 'SET_BASEINFO' export const SET_DETAIL = 'SET_DETAIL'
用const
來保證惟一性。
而後咱們須要將modules加到store裏面,新建一個/src/vuex/store.js
文件:
import Vue from 'vue' import Vuex from 'vuex' import userInfo from './modules/user_info' Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' export default new Vuex.Store({ modules: { userInfo }, strict: debug, middlewares: debug ? [] : [] })
再把其在App.vue裏面引用,App.vue加入:
import store from './vuex/store' export default { store }
這樣咱們就能夠用:
vuex: { getters: { accessToken: ({ userInfo }) => userInfo.accessToken } }
來獲取用戶數據了。
咱們將獲取用戶信息,保存用戶信息的邏輯全放在vuex的actions裏面,而不是在業務邏輯裏面獲取,只是在vuex裏面保存一下。這樣業務邏輯就更扁平了,數據的獲取只須要調用一下actions裏面的函數,用getter來動態獲取。具體代碼以下:
// /src/vuex/actions/user_actions.js import * as types from '../mutation_types' import { setMsg } from '../../tool' import Vue from 'vue' let localStorage = window.localStorage let storeBaseInfo = (data) => { localStorage.setItem('cnodeBaseInfo', JSON.stringify(data)) } let storeDetailInfo = (data) => { localStorage.setItem('cnodeDetailInfo', JSON.stringify(data)) } // 獲取存儲在localStorage中的數據 export const getStore = ({ dispatch, state }) => { if (localStorage.getItem('cnodeBaseInfo')) { let data = JSON.parse(localStorage.getItem('cnodeBaseInfo')) dispatch(types.SET_BASEINFO, data) } if (localStorage.getItem('cnodeDetailInfo')) { let data = JSON.parse(localStorage.getItem('cnodeDetailInfo')) dispatch(types.SET_DETAIL, data) } } // 設置基礎數據 export const setBaseInfo = ({ dispatch, state }, token, callback) => { Vue.http({ url: '/api/v1/accesstoken', method: 'POST', body: JSON.stringify({ accesstoken: token }), headers: { contentType: 'application/x-www-form-urlencoded' } }).then(function (res) { let data = JSON.parse(res.data) if (data.success) { data.accesstoken = token delete data.success storeBaseInfo(data) dispatch(types.SET_BASEINFO, data) callback(setMsg(true, '登陸成功')) } else { console.log(data.error_msg) callback(setMsg(false, data.error_msg)) } }).catch(err => { console.log(err) let errBody = JSON.parse(err.body) callback(setMsg(false, errBody.error_msg)) }) }
上面有個setMsg的函數,只是用來將格式化返回給組件的內容的,把action寫的就像一個接口同樣。
上面用了vue-resource。而後咱們作的事主要就件,調用接口,拿數據,錯誤處理,保存數據到localStorage,返回數據。
接下來,咱們看看組件裏面的獲取數據:
import dialog from '../common/dialog' import { setBaseInfo, setDetail } from '../../vuex/actions/user_actions' import { setMenu, setTip } from '../../vuex/actions/doc_actions' export default { vuex: { actions: { setBaseInfo, setMenu, setTip, setDetail } }, data () { return { config: { visible: false, text: '在 Cnode社區網站端登陸你的帳戶,而後在右上角找到【設置】按鈕,點擊進入後將頁面滑動到最底部來查看你的Access Token。', sureText: '肯定' }, access: '' } }, methods: { dialog () { this.config.visible = true }, success () { window.history.go(-1) this.setMenu(true) this.setDetail() }, login () { if (this.access.length < 6) { this.setTip({ text: '請輸入正確的Access Token' }) return } this.setBaseInfo(this.access, (res) => { if (res.success) { this.success() } this.setTip({ text: res.msg }) }) } }, components: { dialog } }
首先引入actions,而後調用,由於返回數據格式事固定的,直接作判斷,錯誤就用dialog彈錯錯誤。是否是很清爽。
我感受要仔仔細細把全部所有講完,篇幅太長了。。。你們仍是看看我這作個指引,具體仍是看代碼
其餘