vue-admin-template 學習筆記
阿新 • • 發佈:2020-12-20
ps
一個後端閒來無事的瞎折騰,vue的學習過程
vue基礎學習
學習網站
vue-admin-template
學習網站
2020-12-15 02:01:19 快速一刷 似懂非懂(其實就是什麼也看不懂) 直接上手 除錯加百度 手撕原始碼
前端結構
├── build // 構建相關 ├── bin // 執行指令碼 ├── public // 公共檔案 │ ├── favicon.ico // favicon圖示 │ └── index.html // html模板 ├── src // 原始碼 │ ├── api // 所有請求 │ ├── assets // 主題 字型等靜態資源 │ ├── components // 全域性公用元件 │ ├── directive // 全域性指令 │ ├── layout // 佈局 │ ├── router // 路由 │ ├── store // 全域性 store管理 │ ├── styles // css樣式 │ ├── utils // 全域性公用方法 │ ├── views // view │ ├── App.vue // 入口頁面 │ ├── main.js // 入口 載入元件 初始化等 │ ├── permission.js // 許可權管理 │ └── settings.js // 系統配置 ├── .editorconfig // 編碼格式 ├── .env.development // 開發環境配置 ├── .env.production // 生產環境配置 ├── .env.staging // 測試環境配置 ├── .eslintignore // 忽略語法檢查 ├── .eslintrc.js // eslint 配置項 ├── .gitignore // git 忽略項 ├── babel.config.js // babel.config.js ├── package.json // package.json └── vue.config.js // vue.config.js
結構分析
- 登入實現
src/views/login/index.vue 點選登入 呼叫 handleLogin() this.$refs.loginForm.validate // 驗證表單成功進行提交 失敗則error this.$store.dispatch('user/login', this.loginForm) // 提交到store 的 user/login 地址 src/store/index.js modules: {app, settings,user},getters src/store/modules/user.js import { login, logout, getInfo } from '@/api/user'; src/api/user.js 通過login 方法呼叫 src/api/user.js 的login 方法 去請求對應的地址 mock/user.js 最後指向 mock/user.js // 這裡訪問的是模擬的api
檔案分析
src/views/login/index.vue
<template> <div class="login-container"> <!-- 1. ref="loginForm" 傳遞該引數 2. :model="loginForm" 表單資料物件 3. :rules="loginRules" 表單驗證規則 4. class="login-form" css樣式 5. auto-complete="on" 自動提交 一般都是預設的 6. label-position="left" 表單域標籤的位置,如果值為 left 或者 right 時,則需要設定 label-width --> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left" > <div class="title-container"> <h3 class="title">系統登入</h3> </div> <!-- 1. prop=“username” 表單域 model 欄位,在使用 validate、resetFields 方法的情況下,該屬性是必填的,傳入 Form 元件的 model 中的欄位 2. ref="username" 傳遞該引數 3. v-model="loginForm.username" 繫結值 4. placeholder="Username" 佔位符 5. name="username" 原生屬性 6. type="text" 型別 7. tabindex="1" 標籤索引 8. auto-complete="on" 自動提交 --> <el-form-item prop="username"> <span class="svg-container"> <svg-icon icon-class="user" /> </span> <el-input ref="username" v-model="loginForm.username" placeholder="Username" name="username" type="text" tabindex="1" auto-complete="on" /> </el-form-item> <el-form-item prop="password"> <span class="svg-container"> <svg-icon icon-class="password" /> </span> <el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" placeholder="Password" name="password" tabindex="2" auto-complete="on" @keyup.enter.native="handleLogin" /> <span class="show-pwd" @click="showPwd"> <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> </span> </el-form-item> <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin" >登入 </el-button> <!-- <div class="tips">--> <!-- <span style="margin-right:20px;">username: admin</span>--> <!-- <span> password: any</span>--> <!-- </div>--> </el-form> </div> </template> <script> import { validUsername } from '@/utils/validate'; export default { name: 'Login', data() { const validateUsername = (rule, value, callback) => { if (!validUsername(value)) { callback(new Error('請輸入正確的使用者名稱')); } else { callback(); } }; const validatePassword = (rule, value, callback) => { if (value.length < 6) { callback(new Error('密碼不能少於6位數字')); } else { callback(); } }; return { loginForm: { username: 'admin', password: '111111' }, loginRules: { username: [{ required: true, trigger: 'blur', validator: validateUsername }], password: [{ required: true, trigger: 'blur', validator: validatePassword }] }, loading: false, passwordType: 'password', redirect: undefined }; }, watch: { $route: { handler: function(route) { this.redirect = route.query && route.query.redirect; }, immediate: true } }, methods: { // 顯示密碼 showPwd() { if (this.passwordType === 'password') { this.passwordType = ''; } else { this.passwordType = 'password'; } this.$nextTick(() => { this.$refs.password.focus(); }); }, // 處理登入 handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; // 請求 store 中的方法 this.$store.dispatch('user/login', this.loginForm).then(() => { this.$router.push({ path: this.redirect || '/' }); this.loading = false; }).catch(() => { this.loading = false; }); } else { console.log('error submit!!'); return false; } }); } } }; </script> <style lang="scss"> /* 修復input 背景不協調 和游標變色 */ /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ $bg: #283443; $light_gray: #fff; $cursor: #fff; @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { .login-container .el-input input { color: $cursor; } } /* reset element-ui css */ .login-container { .el-input { display: inline-block; height: 47px; width: 85%; input { background: transparent; border: 0; -webkit-appearance: none; border-radius: 0; padding: 12px 5px 12px 15px; color: $light_gray; height: 47px; caret-color: $cursor; &:-webkit-autofill { box-shadow: 0 0 0 1000px $bg inset !important; -webkit-text-fill-color: $cursor !important; } } } .el-form-item { border: 1px solid rgba(255, 255, 255, 0.1); background: rgba(0, 0, 0, 0.1); border-radius: 5px; color: #454545; } } </style> <style lang="scss" scoped> $bg: #2d3a4b; $dark_gray: #889aa4; $light_gray: #eeeeee; .login-container { min-height: 100%; width: 100%; background-color: $bg; overflow: hidden; .login-form { position: relative; width: 520px; max-width: 100%; padding: 160px 35px 0; margin: 0 auto; overflow: hidden; } .tips { font-size: 14px; color: #fff; margin-bottom: 10px; span { &:first-of-type { margin-right: 16px; } } } .svg-container { padding: 6px 5px 6px 15px; color: $dark_gray; vertical-align: middle; width: 30px; display: inline-block; } .title-container { position: relative; .title { font-size: 26px; color: $light_gray; margin: 0 auto 40px auto; text-align: center; font-weight: bold; } } .show-pwd { position: absolute; right: 10px; top: 7px; font-size: 16px; color: $dark_gray; cursor: pointer; user-select: none; } } </style>
執行順序分析
gitee原始碼地址 後續版本刪除了console 日誌
1. 基礎分析
**通過基礎分析大概知道了檔案的普通構成和打包方法**
-
src/App.vue 入口頁面
- 被 src/main.js 引用
-
通過webstorm ait+F7 查詢使用方法得知 依次被引用
- 被 vue.config.js 引用
- 被 build/index.js 引用
- 被 package.json 引用
- “preview”: “node build/index.js --preview”,
-
src/settings.js 設定介面
- src/store/modules/settings.js
- src/store/index.js
- src/utils/get-page-title.js
- src/permission.js
- src/store/modules/settings.js
2. 猜測分析
**通過此段可以分析出 載入方法和載入順序**
- 先載入import 引入的 js 檔案
- 後加載該檔案 日誌後列印
- 進入 src/store/modules/user.js 調整引入檔案順序
console.info('src/store/modules/user.js');
import { login, logout, getInfo } from '@/api/user';
import { getToken, setToken, removeToken } from '@/utils/auth';
import { resetRouter } from '@/router';
變為
console.info('src/store/modules/user.js');
import { resetRouter } from '@/router';
import { login, logout, getInfo } from '@/api/user';
import { getToken, setToken, removeToken } from '@/utils/auth';
- 視窗列印順序
原日誌
src/App.vue 入口頁面
src/api/user.js 引用請求
src/router/index.js 全域性路由
src/store/modules/user.js
src/settings.js 設定介面
src/store/modules/settings.js
src/store/index.js 全域性 store管理
src/utils/get-page-title.js
permission.js 許可權控制
main.js 入口載入元件初始化等
public/index 公共檔案html模板
日誌變化
src/App.vue 入口頁面
src/router/index.js 全域性路由 // 這裡順序發生了變化
src/api/user.js 引用請求 // 這裡順序發生了變化
src/store/modules/user.js
src/settings.js 設定介面
src/store/modules/settings.js
src/store/index.js 全域性 store管理
src/utils/get-page-title.js
permission.js 許可權控制
main.js 入口載入元件初始化等
public/index 公共檔案html模板
3. 得出結論
基本可以得出不太成熟的結論
- 網路請求 index.html 掛載 #app
- main.js 入口載入 元件初始化等
- 根據main.js內引入順序載入 如果載入的js檔案 有載入其他js檔案 那麼 先載入他引入的檔案 以此類推