1. ホーム
  2. js

テンセントのアーキテクトに連れられてコードを書く - vue real enterprise practice sharing

2022-02-22 18:58:27
<パス

Vue.js+element uiによるバックエンド管理システムの構築

この記事を読むと何が得られるのか?

  1. とぼけることなく <強い 実際の企業プロジェクトのハンズオンのヒント そのまま持っていって使うことができる
  2. 実際のインターフェイスの呼び出し 関連する機能を実装している
  3. 優れたラッピングのヒント(このプロジェクトは 元テンセント フロントエンドアーキテクト (元テンセントフロントエンドアーキテクトの指導のもとで構築された)
  4. ポットホールを踏み抜き、よりスムーズな開発を支援します
  5. すべてのコードの感度を下げ、中途半端な理解に陥らないようにします。

プロジェクトプレビュー

  • ログインページ効果

  • ログイン時の遷移効果

  • ログインに成功し、ページに移動します。

  • 左サイドナビゲーションと右サイドテーブルの効果

  • ご覧いただいているのは 標準的なバックエンド管理システム

  • このシンプルなページは、強力なコードに裏付けられています。

プロジェクトのテクノロジースタックの概要

  • 開発ツール:vscode(推奨フロントエンド開発ツール)
  • Vueのバージョン。V 2.6.11
  • vue-router: V 3.2.0
  • 要素 ui のバージョンです。V 2.15.1
  • インターフェイスデバッグ:axios library V 0.21.1
  • vue-cli (scaffolding) のバージョン。V 4.5.0
  • ノードのバージョンです。V 13.14.0
  • node-sassです。V 4.12.0
  • sass-loader。V 8.0.2
  • babel-eslint: V 10.1.0

1. ルーティングの設定

routerフォルダーの下に、index.jsの設定

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '... /views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      requireAuth: true
    },
    children: [
      // Student data
      {
        path: '/home/studentData',
        name: 'studentData',
        meta: {
          requireAuth: true
        },
        component: () => import('... /views/studentData/studentData.vue')
      },
      // Teacher data
      {
        path: '/home/teacherData',
        name: 'teacherData',
        meta: {
          requireAuth: true
        },
        component: () => import('. /views/teacherData/teacherData.vue')
      },
    ]
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('. /views/login/login.vue'),
    // child route
    children: [

    ]
  }
]
// Multiple clicks on the same navigation will report an error, so this code has been added
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}

const router = new VueRouter({
  routes
})
// The router will be used elsewhere, so export it
export default router


  • 注)このような項目があるため は、中段のテーブル部分のみがトグルします。 そのため、ルーティングの設定には <マーク 親子ルーティングパターン
  • 親ルート:home.vueには、1.左ナビゲーション、2.ヘッダー情報バー、3.フォームセクションのコンテナが含まれています。
  • ビューファイルのディレクトリは以下のように設定されています。(あまり熟練していない場合は、まず私の設定に従いましょう)

2. ログインページの設定

login.vue (現在は純粋な静的ページ。後でインターフェースとメソッドを追加)

<template>
  <div class="login-box">
    <div class="form-con">
      <h2>Vue+element ui management system in action</h2>
      <div class="label">
        <el-input placeholder="Please enter account number" v-model="userName">
          <template slot="prepend"><i class="el-icon-user"></i></template>
        </el-input>
      </div>
      <div class="label">
        <el-input placeholder="Please enter your password" v-model="password" show-password @keyup.enter.native="loginFn()">
          <template slot="prepend"><i class="el-icon-lock"></i></template>
        </el-input>
      </div>
      <div class="label">
        <el-button class="login-btn" type="primary" @click="loginFn()"
          >login</el-button
        >
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "login",
  data() {
    return {
      userName: "",
      password: "",
      verify: "",
    };
  },
};
</script>
<style lang="scss" scope>
.login-box {
  width: 100%;
  height: 100%;
  display: flex;
  text-align: center;
  background: url("~@/assets/4.jpg") no-repeat;
  background-size: 100% 100%;
  .form-con {
    h2 {
      color: #ffffff;
      // color: $colorRed;
    }
    width: 360px;
    height: 420px;
    margin: 150px auto auto auto;
    .label {
      margin: 40px 0;
      .login-btn {
        width: 100%;
      }
    }
  }
}
</style>



3. APIレイヤーの設定(インターフェース設定)

  • メンテナンス性を考慮し、階層的にデザインされたインターフェース 以下の4つの基本ファイルが用意されます(これらは推奨の必須アイテムで、残りは必要に応じて追加可能です)。

  • このうち最初の3つのファイルを書き込んだ後は、基本的に動かす必要はなく、きっぱり、かっこいい

  • アイデア ディープデカップリング 高い再利用性

3.1 Service.jsの設定

  • このファイルは、バックエンドの処理と、すべてのインターフェイス(各種インターセプト処理、ステータス処理など)の統一を担当する。
import axios from 'axios'
import vue from '... /main.js'
// Get the token from local
function getTokenByLocal() {
    let token = sessionStorage.getItem('token');
    return token;
}

const service = axios.create({
    baseURL: '/sys',
    // withCredentials: true,
    timeout: 5000,
})


// Request interception
service.interceptors.request.use(
    config => {
        if (getTokenByLocal()) {
            // Here you can set all interface headers headers
            config.headers['token'] = getTokenByLocal();
        }else{
            // window.location.href="/login";
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// Response interception
service.interceptors.response.use(
    response => {
        let res = response.data;
        // console.log(res);
        // status code handling
        if (res.code == '200') {
            // location.href = "home/login";
        }
        // If -101 means the user is not logged in
        if(res.code == '-101'){
            vue.$router.push('/login');
        }   
        return Promise.resolve(res);
    },
    error => {
        return Promise.reject(error)
    }
)

export default service;


3.2 Common.jsの設定

  • このファイルが行うことはただ一つです。 プロジェクト内のすべてのインターフェイスのパススルーの取り扱いを統一します。
  • 一般的に言って、あまり派手なパススルーはないでしょう。
// Bring in service.js
import service from '. /service.js'

// post request 80% low coupling high reusability
export function requestOfPost(url, data){
    return service.post(url, data);
}


3.3 api.jsの設定

  • このファイルは、非同期を処理するためのプロミスを追加したセカンダリラッパーです。
import {requestOfPost} from '. /common.js'

export function postRequest(url, data){
    return new Promise((resolve, reject) => {
        requestOfPost(url, data).then(res => resolve(res))
        .catch(error => reject(error))
    })
}



3.4 url.jの設定

  • このファイルは、すべてのインターフェイスのパスの統一管理、それ以外のプロジェクト東1西1トラブルを維持するために(建築家は言った、我々は反論する勇気がない、慎重にそれについて考え、それはまた正しいです)
  • プロジェクトに百以上のインターフェイスがある場合は、2つに分割することができます。
  • コメントを追加することを忘れないでください。
const url = {
    // login
    login: '/login',
    // Student list
    getClassmates: '/getClassmates' 
}
export default url;


4. クロスドメインハンドリング

  • 一般的に言って、ローカル開発はクロスドメインでインターフェイスを設定する必要があり、バックエンドは一般的にそれに対処するには怠慢すぎる(謙虚なフロントエンドの無力さ)。

  • プロジェクトの一番外側のレイヤーにファイルを追加する。 <マーク vue.config.js

  • 構成は以下の通りです。

module.exports = {
    devServer: {
        compress: false,
        open: true,
        proxy: {
            '/sys': {
                // proxy address
                target: 'http://api.gebilaowang.com',
                // websocket (usually used for instant messaging, games, not needed here, so don't open)
                ws: false, 
                // whether to allow cross-domain
                changeOrigin: true,
                // rewrite
                pathRewite: {
                    '/sys': '/'
                }
            }
        }
    }
}


5. これで楽しくインターフェイスをチューニングすることができます

login.vueのコードを追加しました。

<script>
// This is a globally defined transition method
import { loadingShow } from ". /... /common/js/common.js";
import url from "... /... /request/url.js";
import { postRequest } from ". /... /request/api.js";

export default {
  name: "login",
  props: {
    msg: String,
  },
  data() {
    return {
      userName: "",
      password: "",
      verify: "",
    };
  },
  methods: {
  	// Login method
    loginFn() {
      if (!this.userName) {
        this.msgFn("warning", "Please enter your account name");
        return;
      } else if (!this.password) {
        this.msgFn("warning", "Please enter password");
        return;
      } else {
        // Loading animation
        loadingShow();
        let data = {
          userName: this.userName,
          passWord: this.password
        };
        postRequest(url.login, data).then(
          (res) => {
            // animation hide
            loadingHide();
            if (res.code == 500) {
              this.msgFn("error", res.msg);
              return;
            }
            // token is stored in sessionStorage
            sessionStorage.setItem("token", res.token);
            // page jump
            setTimeout(() => {
              this.$router.push("/home/studentData");
            }, 500);
          },
          (error) => {
            console.log(error);
          }
        );
      }
    },


    // popup window
    msgFn(type, text) {
      this.$message({
        message: text,
        type: type,
      });
    },
  },
  created() {
  },
};
</script>



6. main.jsに必要な構成

  • ui要素に要素を導入して登録する
  • グローバルなアニメーション設定
import Vue from 'vue'
import App from '. /App.vue'
import router from '. /router'

import {
  Button,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Input,
  Loading,
  Message,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Dropdown,
  DropdownMenu,
  Table,
  TableColumn,
  DropdownItem,
  Form,
  FormItem,
  Select,
  Option,
  OptionGroup,
  DatePicker,
  Pagination,
  MessageBox,
  Popover,
  Tag,
  Switch,
  Dialog

} from 'element-ui';
Vue.use(global)
Vue.use(Button)
Vue.use(Container)
Vue.use(Header)
Vue.use(Aside)
Vue.use(Main)
Vue.use(Footer)
Vue.use(Input)
Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem)
Vue.use(MenuItemGroup)
Vue.use(Dropdown)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(DropdownMenu)
Vue.use(DropdownItem)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Select)
Vue.use(Option)
Vue.use(OptionGroup)
Vue.use(DatePicker)
Vue.use(Pagination)
Vue.use(Popover)
Vue.use(Dialog);
Vue.use(Tag)
Vue.use(Switch)
Vue.use(Loading.directive);

// Add global methods
Vue.prototype.$loading = Loading.service;
Vue.prototype.$message = Message;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$msgbox = MessageBox;
Vue.config.productionTip = false;


let vue = new Vue({
  router,
  render: h => h(App)
}). $mount('#app')

export default vue;


7. ルートブロックを設定する

  • コンテンツが少ない場合はmain.jsに入れる
  • ルータを忘れずに導入する
router.beforeEach((to, from, next) => {
  // Take token as an example
  let token = sessionStorage.getItem('token');
  // requires authentication before it can enter requireAuth
  if (to.meta.requireAuth) {
    if (token) {
      next();
      // Accessed successfully
    } else {
      // jump to the specified page
      next({
        path: '/login'
      })
    }
  } else {
    // Smooth entry
    next();
  }
})


8. グローバルメソッドの設定

  • ストレージディレクトリは、以下の通りです(建築家が言っていたことで、もう少し考えたら、ここに置くのが理にかなっています)。
  • 参考までにグローバルなメソッドをあげると、後続のメソッドはこれに続く(まだ非常に甘い)。
import vue from '... /... /main.js'

// Mask layer control
export function loadingShow(close){
    const loadingFade = vue.$loading({
      lock: true,
      text: 'Loading',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0, 0.7)'
    })
    if(close){
        loadingFade.close();
    }
  }


9. 親ページの設定(home.vue)

  • 必要な人がいそうな気がするので、コードはそのまま掲載(作者が必要だと思うから必要なのです)
<template>
  <div class="container-big">
    <el-container class="container">
      <el-aside width="220px">
        <el-menu class="menu" :default-active="index">
          <el-submenu index="1">
            <template slot="title"><i class="el-icon-s-home"></i>home</template>
            <el-menu-item index="1-1" @click="toRoute('/home/studentData', 'student data')"
              >studentData</el-menu-item
            >
          </el-submenu>
          <el-submenu index="2">
            <template slot="title"
              ><i class="el-icon-s-cooperation"></i>Academic Affairs / Administration</template
            >
            <el-submenu index="2-2">
              <template slot="title">Role Management</template>
              <el-menu-item
                index="2-2-1"
                @click="toRoute('/home/teacherData', 'Teacher Management')"
              >
                Teacher management</el-menu-item
              >
              <el-menu-item
                index="2-2-2"
                @click="toRoute()"
              >
                Teacher review</el-menu-item
              >
            </el-submenu>
            <el-submenu index="2-3">
              <template slot="title">other-management</template>
              <el-menu-item
                index="2-3-1"
                @click="
                  toRoute()
                "
              >
                Academic Administration</el-menu-item
              >
              <el-menu-item
                index="2-3-3"
                @click="
                  toRoute(
                    '/home/shopList',
                    ' / operations management / store management / shop list',
                    'shopList',
                    '2-3-3'
                  )
                "
              >
                Toilet sweep management</el-menu-item
              >
            </el-submenu>
          </el-submenu>
        </el-menu>
      </el-aside>

      <el-container>
        <el-header style="text-align: right; font-size: 14px">
          <div class="optimization">
            <el-dropdown>
              <i class="el-icon-setting" style="margin-right: 15px"> operation </i>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item @click.native="logOut()"
                  >LogoutLogout</el-dropdown-item
                >
              </el-dropdown-menu>
            </el-dropdown>
            <span>{{ userName }}</span>
          </div>
          <div class="router-con">
            <div>
              <span>xxx company operations management system</span>
            </div>
            <h2>{{pageName}}</h2>
          </div>
        </el-header>

        <el-main>
          <router-view> </router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "home",
  data() {
    return {
      userName: "",
      index: "1-1",
      pageName: ''
    };
  },
  created() {
    // You can fetch permission-related data here
  },
  methods: {
    // Jump to individual pages
    toRoute(url, name) {
      this.$router.push(url);
      this.pageName = name;
    },
    // Logout
    logOut() {
      // Jump to the login page
      this.$router.push("/login");
      // Usually you need to clear some cached data for the user here
    },
  },
};
</script>

<style lang="scss" scope>
.logo {
  overflow: hidden;
  padding: 10px 0px 10px 20px;
  cursor: pointer;
  img {
    float: left;
    margin-top: 10px;
  }
  p {
    float: left;
    margin: 12px 0 0 12px;
    color: #fff;
    font-weight: 600;
    font-size: 20px;
    vertical-align: middle;
    animation: fade-in;
    animation-duration: 0.3s;
  }
}
.el-submenu .el-menu-item {
  text-align: left;
  height: 40px;
  line-height: 40px;
  // margin-left: 10px;
}
.menu {
  .el-submenu {
    .el-submenu__title {
      padding-left: 30px;
    }
    .el-menu {
      .el-submenu__title {
        padding-left: 50px !important;
      }
    }
  }
}

.el-header {
  color: #333;
  border-bottom: 1px solid #d3d3d3;
  background: #fff;
  padding: 0;
  box-shadow: darkgrey 5px 0 5px 1px; //border-shadow
  .optimization {
    height: 60px;
    line-height: 60px;
    padding: 0 20px;
    curso

  • コードは詳細にコメントされているので、ここでは説明しませんが
  • あなたのファイルにすべてコピーして、効果を確認することができます(とてもスイートでしょう?)

10. よくある質問 よくある質問とその回答

  1. 何かが間違ってインストールされている(外国のネットワークが不安定な場合があります、あなたはタオバオミラーを設定することができます)。
  2. 何かが動作していない(バージョンの問題に注意してください)
  3. vue.config.js ファイルは有効になりません。 <マーク 必ずサービスを再起動する
    と再コンパイル)
  4. 一部のコンポーネントでスタイルが正しく表示されない( main.js (で導入や登録が行われているかどうかを確認する)。
  5. 一部のモジュールが見つからないという報告(ファイル格納パス、導入パスが正しいか確認する)
  6. その他の課題(可能な限り 直接プライベートメッセージ (一日に数回チェックし、見かけたらすぐに返信します)。
  • 誰もが読めるように理解するために努力するためには、問題ないでしょう。この記事は、完了するために多くの努力を取った(喫煙レッドターザン、夜更かし)それはあなたの助けになることを願っています。
  • 三社の波を忘れずに~、いいね!、コメント、フォロー
  • 一度に読み切れない場合は、ブックマークしておくといいですよ〜。
  • いつも応援ありがとうございます!これからも良質な記事を必ずアウトプットしていきます〜。