1. 程式人生 > 其它 >個人自學前端39-Vue16-後臺管理系統,登入、許可權的業務邏輯,修改UI框架樣式

個人自學前端39-Vue16-後臺管理系統,登入、許可權的業務邏輯,修改UI框架樣式

目錄

後臺管理系統

後臺管理系統涉及的常見功能:

1:ui框架使用。快速佈局。

2:圖表的使用。echarts。

3:登入功能的處理。token。

4:許可權處理。非同步路由。

5:國際化處理。外掛。

一 UI框架

Vue的ui框架可以分為兩類:

1:PC端ui框架 => element-ui,iView。

2:移動端ui框架 => Vant,Vux,mint,ant-design-vue。

一個ui框架的使用涉及的問題:

1:安裝。(看官網)

2:引入。a:完全引入,b:按需引入。

​ element-ui是Vue的外掛,因此引入時,需要使用use處理一次。

​ 完全引入會導致打包後體積比較大。

​ 按需引入的體積沒有那麼大。(按需引入好一點)

3:主題修改。

4:佈局樣式layout佈局。

5:元件使用。(最重要)

6:圖示和顏色。

​ 如何使用圖示,直接class換圖示名字即可。

​ 所有ui框架的圖示都是字型圖示。文字的體積比圖片的小。

​ 不同的顏色對應不同的關鍵字。例如element的藍色是primary。(所有ui通用)

二 如何看別人的專案

不是說全部程式碼都知道是怎麼回事才可以改。

永遠只關心跟自己修改功能相關的程式碼。不要看根自己修改功能無關的模組。

如何找到哪些模組檔案是自己需要修改的?

1:先找到頁面對應的標籤。(內容找不到,找標籤,標籤找不到,找父元素) (目的是找到需要修改的元件是哪個)

2:找到標籤後,通過全域性查詢,找到標籤所在的元件。

3:找到這個元件的繫結的資料。如果資料是靜態的很好處理,如果是動態的,需要順騰摸瓜慢慢找相關模組。

找表格 => userList元件 => tableData陣列 => getUserList方法 => userList.js檔案 => 找到介面。

如何找到我們需要修改的頁面對應的元件?

1:利用正專案中查詢類名。

2:如果找路由元件,路徑名就是元件名。如果找一般元件,標籤的類名就是元件名。(不一定)

如何找到請求資料的邏?

先找到資料對應的元件,再去元件內順騰摸瓜找到資料的來源。

三 登入的業務邏輯

1:什麼是token

token是一個字串。它攜帶了使用者的相關資訊。例如許可權資訊,賬號密碼等等。

token是用來實現使用者驗證的。

什麼是使用者驗證?

http協議是一種無狀態的協議。無狀態 => 無記憶.

前端後端通訊結束之後,如果發起新的請求,後端是無法知道當前的客戶端是不是之前通訊過的客戶端。

如果不做額外的處理,我們是無法實現保留登入狀態的功能的。

使用者驗證就是為了讓後端記住前端。用什麼記住?用token字串進行記憶。

token如何獲取?

登入成功後,後端會發生token給前端。

如何儲存token?

token需要通過本地儲存或者cookie儲存到瀏覽器中。方便隨時獲取傳送給伺服器。

token需要每次請求時都要傳送給後端。如何傳送?

一般會把token寫在header內(請求頭),因為head內的資訊會預設每次都發送給伺服器。

在header內配置一個 Authorizaion:token 20603038ce66e6abfd1182d3a68307929f7fdb40。

如何判斷token是不是過期了?

通過後端返回的資料判斷,例如:code是100表示過期了。是0表示沒過期。

如果token過期了,需要請求特定介面獲取新的token再存起來。

2:專案的登入邏輯需要做的事情

a:發起登入成功之後,把token儲存到cookie或者本地儲存。(在哪裡寫儲存的程式碼不固定)

b:路由守衛中判斷是否登入成功過。(判斷cookie或者本地儲存內有沒有token)

c:需要隨時保證token是最新的。要在響應攔截裡判斷token是否過期了。(通過伺服器返回的欄位判斷)

d:需要把登入成功之後獲取的使用者資料,儲存到vuex中。

  <script>
  // 如何通過token判斷使用者是不是已經登入過?
  // 首先判斷本地儲存或者cookie中是不是已經有了對應token.
  // 如果有token,繼續判斷token是不是過期了.

  // 請求攔截 => 所有的請求發生之前,都會觸發use的回撥.
  // use的回撥的引數config是axios請求的配置項.
  // 通過config,可以在所有請求發生前,修改config.
  // 一定記得return config,否則請求預設會失敗.
  axios.interceptors.request.use(function (config) {
    // 給所有的請求都新增token欄位.
    config.headers.Authorizaion = localStorage.getItem('token');
    // 在傳送請求之前做些什麼
    return config;
  }, function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  });

  // 響應攔截.每次資料請求拿到資料之前都會觸發響應攔截
  // res引數就是伺服器返回的結果.
  // 需要把res return出去.否則then接收不到伺服器返回的結果.
  axios.interceptors.response.use(function (res) {
    // console.log('res', res);
    res.data.msg = '修改喲喲喲喲成功了';
    // 在拿到資料之前做些什麼
    return res;
  }, function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  });

    const Login = {
      template: `
        <div>
          <input type='text' />
          <button @click='toPage'>登入</button>
        </div>
      `,
      props: ['name'],
      methods: {
        toPage() {
          axios.get('data.json').then(res => {
            if (res.data.code === 0) {
              // 獲取token並且儲存到本地。
              localStorage.setItem('token', res.data.token);
              // 跳轉到指定路由.
              this.$router.push({ name: this.name });
            }
          });
        }
      }
    }
    const Home = {
      template: `
        <div>
          <slot />
          <h3>首頁</h3>
        </div>
      `,
    }
    const News = {
      template: `
        <div>
          <slot />
          <h3>新聞</h3>
          <button @click='fn'>修改使用者資訊</button>
        </div>
      `,
      methods: {
        fn() {
          axios({
            url: 'editor.json',
            methods: "GET",
            data: "新修改的使用者名稱",
            // 每次請求,都手動傳送token.
            // headers: { Authorizaion: localStorage.getItem('token') },
          }).then(res => {
            console.log(res);
          })
        }
      }
    }
    const Sport = {
      template: `
        <div>
          <slot />
          <h3>體育</h3>
          <button @click='fn'>修改使用者頭像</button>
        </div>
      `,
      methods: {
        fn() {
          axios({
            url: '頭像介面',
            methods: "POST",
            data: "新修改的頭像",
            // 每次請求,都手動傳送token.
            headers: { Authorizaion: localStorage.getItem('token') },
          }).then(res => {
            console.log(res);
          })
        }
      }
    }
    // 例項化路由
    const router = new VueRouter({
      // 路由元件和路由路徑的對應關係 => 路由選項
      routes: [
        {
          path: '/home',
          component: Home,
          name: 'home',
          meta: {
            // 不需要登入
            authLogin: false
          }
        }, {
          path: '/news',
          component: News,
          name: 'news',
          meta: {
            authLogin: true
          }
        }, {
          path: '/sport',
          component: Sport,
          name: 'sport',
          meta: {
            authLogin: true
          }
        }, {
          path: '/login',
          component: Login,
          name: 'login',
          meta: {
            authLogin: false
          },
          props: true
        },{
          path: '/',
          redirect: '/home'
        }
      ]
    });
    // 全域性守衛處理 登入邏輯
    router.beforeEach((to, from, next) => {
      if (to.meta.authLogin) {
        const token = localStorage.getItem('token');
        if (token === null) {
          // 重定向,並且傳遞目標路由的name
          next({ name: 'login', params: { name: to.name } })
        } else {
          // if (token過期了) {
          //    next({ name: 'login', params: { name: to.name } })
          // } else {
          //    next()
          // }
          next();
        }
      } else {
        next()
      }
    });
    const App = {
      template: `
        <div>
          <router-view>
            <router-link to='/home'>首頁</router-link>
            <router-link to='/news'>新聞</router-link>
            <router-link to='/sport'>體育</router-link>
          </router-view>
        </div>
      `
    };
    new Vue({
      render: h => h(App),
      // 掛載路由
      router
    }).$mount('#app');
  </script>

四 許可權

許可權 => 頁面的許可權(需要非同步路由),按鈕的許可權(v-if或者自定義指令實現),請求資料的許可權(請求攔截內實現)。

程式碼內,許可權是儲存在使用者資訊內的一個數組. => 怎麼知道登入之後的賬號許可權? => 使用者的登入資訊內獲取.

=> 根據使用者登入的許可權資訊,動態配置不同的routes陣列到路由例項內。

=> 如何動態設定不同頁面的路由?=> router.addRoutes

一般需要許可權的專案,配置路由時,路由選項需要分成兩個部分。

一個部分是不需要許可權的路由,例如登入路由和404路由。

另一個部分是需要許可權的路由。

在登入成功後,獲取到的使用者的許可權列表,再通過許可權列表從需要許可權的路由內篩選出需要的路由。

最後把不需要許可權的路由和經過篩選的路由合併,再通過addRoutes動態配置。

  <script>
    const Login = {
      template: `
        <div>
          <input type='text' />
          <button @click='toPage'>登入</button>
        </div>
      `,
      props: ['name'],
      methods: {
        toPage() {
          axios.get('userData.json').then(res => {
            // 許可權角色
            let role = res.data.role;
            // 根據許可權過濾路由。
            asyncRoutes = asyncRoutes.filter(item => item.meta.roles.includes(role));
            // 過濾後配置動態路由.
            router.addRoutes(asyncRoutes);
            // 跳轉到首頁.
            this.$router.push('/home');
          });
        }
      }
    }
    const Home = {
      template: `
        <div>
          <slot />
          <h3>首頁</h3>
        </div>
      `,
    }
    const News = {
      template: `
        <div>
          <slot />
          <h3>新聞</h3>
        </div>
      `
    }
    const Sport = {
      template: `
        <div>
          <slot />
          <h3>體育</h3>
        </div>
      `,
    }
    const NotFound = {
      template: `
        <div>
          <h3>404頁面,你要訪問的頁面不存在</h3>
        </div>
      `,
    }
    // 不需要許可權的路由選項.
    const staticRoutes = [
      {
        path: '/login',
        component: Login,
        name: 'login'
      }, {
        path: '/notFound',
        component: NotFound
      }, {
        path: '/',
        redirect: '/login'
      }
    ];
    // 需要許可權的路由選項.
    let asyncRoutes = [
      {
        path: '/home',
        component: Home,
        name: 'home',
        meta: {
          roles: ['editor', 'admin']
        }
      }, {
        path: '/news',
        component: News,
        name: 'news',
        meta: {
          roles: ['admin']
        }
      }, {
        path: '/sport',
        component: Sport,
        name: 'sport',
        meta: {
          roles: ['editor']
        }
      },
    ];
    // 例項化路由,只配置不要許可權的路由。
    // 其他頁面的路由選項,需要在登入之後,根據不同的使用者角色來動態配置.
    const router = new VueRouter({ routes: staticRoutes });
    const App = {
      template: `
        <div>
          <router-view>
            <router-link to='/home'>首頁</router-link>
            <router-link to='/news'>新聞</router-link>
            <router-link to='/sport'>體育</router-link>
          </router-view>
        </div>
      `
    };
    new Vue({
      render: h => h(App),
      // 掛載路由
      router
    }).$mount('#app');
  </script>

五 模擬資料

1:最簡單最笨的就是寫json檔案,自己請求。(簡單情況可以這樣做)

2:使用mock模擬資料。mock是一個外掛。

六 修改UI框架的樣式

如果ui框架的樣式需要修改,有以下幾種方式。

一,通過瀏覽器檢查,找到要修改的標籤的類名,然後再元件中寫一個優先順序更高的選擇器個覆蓋ui的預設樣式。

二,通過元件style的scoped來覆蓋修改。添加了scoped之後,還希望父元件的樣式影響子元件,還需要使用樣式穿透。

樣式穿透的三種寫法:

1. /deep/
2. >>>
3. ::v-deep

三,永遠的全部修改,只能改原始碼。也可以使用定製主題的方式修改,原始檔不會被修改。

不管是修改原始碼還是定製主題的方式,會對整個專案的元件都生效。

修改主題時,建議less-loader的版本是5.0.0.