<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                # 重構代碼 [TOC] 我們在之前的章節中提到過: 由于 Vuex 只會存在于一次會話中,刷新頁面就沒有了,而 localStorage 在瀏覽器端是持久存儲的,所以我們還需要 * 封裝 Axios * 檢測 token 可用性 * 初始化頁面時使用該 token 請求用戶數據 * 將用戶數據塞入 Vuex 并且我們編寫了太多重復代碼,這樣不利于維護和使用,所以本節的主要目標就是優化所有代碼,并且解決已知問題。 ## 檢測 token 可用性 我們需要在入口文件初始化的時候檢測一次可用性: src\App.vue ```html <script> export default { data: () => ({ navItems: [{ title: "主頁", icon: "mdi-home", to: "/" }], navUserItems: [ { title: "注冊", icon: "mdi-account-plus", to: "/sign" }, { title: "登錄", icon: "mdi-login", to: "/login" } ] }), mounted() { const config = { token: localStorage.getItem("JWT_TOKEN"), api: "http://127.0.0.1:8000/", postData: "", headers: { Authorization: "Bearer " + config.token } }; this.login(config, 'me'); }, methods: { login(config, url) { if (config.token) { this.axios .post( config.api + url, config.postData, config.headers ) .then(response => { const data = response.data; this.$store.commit("user_data", data); this.$store.commit("login"); this.$router.push("/"); }) .catch(() => { this.logout(); }); } else { this.logout(); } }, logout() { const token = localStorage.getItem("JWT_TOKEN"); const postData = ""; const api = "http://127.0.0.1:8000/logout"; const headers = { Authorization: "Bearer " + token }; this.axios .post(api, postData, { headers: headers }) .then(() => { this.$store.commit("logout"); }) .catch(error => { alert(error.response.data.error); }); } } }; </script> ``` ## 封裝 Axios 雖然可以正常發送請求的,但是編寫過于繁瑣,可以看到我們 HTTP 請求的代碼太過于重復,所以我們需要將它抽象出來。 創建文件 model\http.js: ```javascript title="model\http.js" /** * axios封裝 * 請求攔截、響應攔截、錯誤統一處理 */ import axios from 'axios'; import router from '../src/router/index'; import store from '../src/store/index'; /** * 跳轉登錄頁 * 攜帶當前頁面路由,以期在登錄頁面完成登錄后返回當前頁面 */ const toLogin = () => { router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); } /** * 請求失敗后的錯誤統一處理 * @param {Number} status 請求失敗的狀態碼 */ const errorHandle = (status, other) => { // 狀態碼判斷 switch (status) { case 500: case 401: store.commit('logout'); toLogin(); break; // 404請求不存在 case 404: console.log('請求的資源不存在') break; default: console.log(other); } } // 創建axios實例 const instance = axios.create({ timeout: 1000 * 12 }); // 設置post請求頭 instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; /** * 請求攔截器 * 每次請求前,如果存在token則在請求頭中攜帶token */ instance.interceptors.request.use( config => { // 登錄流程控制中,根據本地是否存在token判斷用戶的登錄情況 // 但是即使token存在,也有可能token是過期的,所以在每次的請求頭中攜帶token // 后臺根據攜帶的token判斷用戶的登錄情況,并返回給我們對應的狀態碼 // 而后我們可以在響應攔截器中,根據狀態碼進行一些統一的操作。 const token = localStorage.getItem("JWT_TOKEN"); config.headers.Authorization = 'Bearer ' + token return config; }, error => Promise.error(error)) // 響應攔截器 instance.interceptors.response.use( // 請求成功 res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res), // 請求失敗 error => { const { response } = error; if (response) { // 請求已發出,但是不在2xx的范圍 errorHandle(response.status, response.data.message); return Promise.reject(response); } else { // 處理斷網的情況 // eg:請求超時或斷網時,更新state的network狀態 // network狀態在app.vue中控制著一個全局的斷網提示組件的顯示隱藏 // 關于斷網組件中的刷新重新獲取數據,會在斷網組件中說明 if (!window.navigator.onLine) { store.commit('changeNetwork', false); } else { return Promise.reject(error); } } }); export default instance; ``` 該文件是我們初始化 Axios 時設置的一些內容,包括請求頭,錯誤處理等等。 現在我們還需要創建一個 API 模塊來集中管理: model\api.js ```javascript title="model\api.js" /** * api接口統一管理 */ import axios from './http' import store from '../src/store/index'; import router from '../src/router/index'; const domain = 'http://127.0.0.1:8000' const api = { userDetail(id) { return axios.get(`${domain}/user/${id}`); }, me() { return axios .post(`${domain}/me`) .then((res) => { store.commit("user_data", res.data); store.commit("login"); }); }, auth(action, params) { return axios .post(`${domain}/${action}`, params) .then((res) => { localStorage.setItem("JWT_TOKEN", res.data.token); store.commit("user_data", res.data); store.commit("login"); router.push("/"); }); }, logout(params) { return axios .post(`${domain}/logout`, params) .then(() => { localStorage.removeItem('JWT_TOKEN'); store.commit('logout') router.push("/login"); }); } } export default api; ``` 可以看到,我們在該文件內編寫了幾個之前用到的獲取數據的方法,這樣在前端再也不用挨著挨著重復的書寫了。 接著更新一下 Vuex 文件: src\store\index.js ```javascript title="src\store\index.js" import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { user: { isLogin: false, data: "" } }, mutations: { user_data(state, data) { state.user.data = data; }, login(state) { state.user.isLogin = true; }, logout(state) { state.user.isLogin = false; state.user.data = ""; } }, actions: {}, modules: {} }); ``` 好了,封裝 Axios 基本已經完成了,我們現在所需要做的就是在前端去調用它: src\App.vue ```html title="src\App.vue" <script> export default { data: () => ({ navItems: [{ title: "主頁", icon: "mdi-home", to: "/" }], navUserItems: [ { title: "注冊", icon: "mdi-account-plus", to: "/sign" }, { title: "登錄", icon: "mdi-login", to: "/login" } ] }), mounted() { this.$api.me() }, methods: { } }; </script> ``` src\views\Login.vue ```html title="src\views\Login.vue" <script> export default { data: () => ({ email: "", password: "", error: "" }), methods: { login() { const params = { email: this.email, password: this.password }; this.$api.auth('login', params); } } }; </script> ``` src\views\Sign.vue ```html title="src\views\Sign.vue" <script> export default { data: () => ({ email: "", password: "", error: "" }), methods: { sign() { const params = { email: this.email, password: this.password }; this.$api.auth('sign', params); } } }; </script> ``` 接著我們還需要在入口處注冊 api: src\main.js ```javascript title="src\main.js" import Vue from "vue"; import App from "./App.vue"; import "./registerServiceWorker"; import router from "./router"; import store from "./store"; import vuetify from "./plugins/vuetify"; import api from '../model/api' Vue.prototype.$api = api; // 將api掛載到vue的原型上 new Vue({ router, store, vuetify, render: h => h(App) }).$mount("#app"); ``` Vue.prototype 是 Vue 原型方法,例如上面的代碼就是將 api 掛載到 Vue 上,那么在文件中我們就可以通過 `this.$api` 進行調用。 ## 清理多余文件 刪除: * src\views\About.vue * src\plugins\axios.js * src\components\HelloWorld.vue ## 移除多余擴展包 ```powershell title="Powershell" # 如果你使用的是 npm npm uninstall vue-axios # 如果你使用的是 yarn yarn remove vue-axios ``` 現在的問題基本都解決了,再次訪問網站并刷新頁面即可看到 token 被持久化存儲和調用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看