Element UI v1.2 における主要コンポーネントの実装とルーティング制御

1. 環境構築と基本セットアップ

1.1 Vueプロジェクトの初期化

CLIまたはGUIツールによりVue 2.xプロジェクトを生成し、IDEでプロジェクトを開く。

1.2 Element UIの導入

以下のコマンドでライブラリをインストール:

npm install element-ui --save

1.3 メインスクリプトでのグローバル登録

main.js に以下を追加:

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)

2. 認証フローと状態管理

2.1 ログイン画面の実装

Vuex を利用し、認証状態をグローバルに管理。LoginView.vue では以下のような構成:

<template>
  <el-row type="flex" justify="center">
    <el-col :span="10">
      <el-card>
        <h2>システムへようこそ</h2>
        <el-form ref="loginForm" :model="credentials" label-width="80px">
          <el-form-item label="ID">
            <el-input v-model="credentials.id" placeholder="ユーザーID" />
          </el-form-item>
          <el-form-item label="パスワード">
            <el-input v-model="credentials.password" type="password" show-password />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="attemptLogin">ログイン</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </el-col>
  </el-row>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  name: 'LoginView',
  data() {
    return {
      credentials: { id: '', password: '' }
    }
  },
  methods: {
    ...mapActions('auth', ['authenticate']),
    async attemptLogin() {
      try {
        const res = await this.authenticate(this.credentials)
        if (res.success) {
          this.$message.success('ログインに成功しました')
          this.$router.push({ name: 'Dashboard' })
        } else {
          this.$message.error('IDまたはパスワードが正しくありません')
        }
      } catch (err) {
        console.error('ログインエラー:', err)
        this.$message.error('通信エラー')
      }
    }
  }
}
</script>

2.2 Vuexによる認証状態と永続化

/store/modules/auth.js

import Vue from 'vue'

const state = {
  currentUser: null
}

const mutations = {
  SET_USER(state, user) {
    state.currentUser = user
  },
  CLEAR_USER(state) {
    state.currentUser = null
  }
}

const actions = {
  async authenticate({ commit }, { id, password }) {
    try {
      const response = await Vue.prototype.$axios.get('/api/auth', {
        params: { id, password }
      })
      if (response.status === 200 && response.data.code === 2000) {
        commit('SET_USER', response.data.user)
        return { success: true }
      }
      return { success: false }
    } catch (e) {
      throw e
    }
  },
  logout({ commit }) {
    commit('CLEAR_USER')
  }
}

export default { namespaced: true, state, mutations, actions }

/store/index.js で状態をセッションに永続化:

import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import auth from './modules/auth'

export default new Vuex.Store({
  modules: { auth },
  plugins: [
    createPersistedState({
      storage: window.sessionStorage,
      key: 'auth_state'
    })
  ]
})

3. 画面構成とルーティング制御

3.1 認可钩子関数とルート定義

router/index.js

import VueRouter from 'vue-router'
import { store } from '@/store'
import LoginView from '@/views/LoginView.vue'
import DashboardView from '@/views/DashboardView.vue'

const routes = [
  { path: '/', redirect: '/login' },
  { path: '/login', name: 'Login', component: LoginView },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: DashboardView,
    meta: { requiresAuth: true }
  },
  {
    path: '/user',
    name: 'UserList',
    component: () => import('@/views/UserListView.vue'),
    meta: { requiresAuth: true }
  }
]

const router = new VueRouter({
  mode: 'history',
  routes
})

router.beforeEach((to, from, next) => {
  const isAuthRequired = to.matched.some(record => record.meta.requiresAuth)
  const user = store.state.auth.currentUser
  
  if (isAuthRequired && !user) {
    next({ name: 'Login', query: { redirect: to.fullPath } })
  } else {
    next()
  }
})

export default router

3.2 ダッシュボードレイアウト(主画面)

<template>
  <el-container class="app-container">
    <el-header class="app-header">
      <div class="header-left">管理ダッシュボード</div>
      <el-button type="text" @click="logout">ログアウト</el-button>
    </el-header>
    <el-container>
      <el-aside width="200px" class="app-aside">
        <el-menu :default-openeds="['dashboard']">
          <el-submenu index="dashboard">
            <template #title>
              <i class="el-icon-s-operation"></i>
              <span>ダッシュボード</span>
            </template>
            <el-menu-item index="1">
              <router-link :to="{ name: 'Dashboard' }">概要</router-link>
            </el-menu-item>
          </el-submenu>
          <el-submenu index="user">
            <template #title>
              <i class="el-icon-user"></i>
              <span>ユーザー管理</span>
            </template>
            <el-menu-item index="2">
              <router-link :to="{ name: 'UserList' }">一覧</router-link>
            </el-menu-item>
          </el-submenu>
        </el-menu>
      </el-aside>
      <el-main>
        <router-view />
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  name: 'DashboardView',
  methods: {
    ...mapActions('auth', ['logout'])
  }
}
</script>

<style scoped>
.app-container { height: 100vh; }
.app-header { display: flex; justify-content: space-between; align-items: center; }
.app-aside { background-color: #f0f1f5; }
</style>

3.3 ユーザー一覧画面:検索・ページネーション対応












検索
クリア













編集
削除












import axios from 'axios'

export default {
name: 'UserListView',
data() {
return {
users: [],
filters: { id: '', phone: '' },
currentPage: 1,
pageSize: 10,
totalCount: 0
}
},
async mounted() {
await this.loadUsers()
},
methods: {
async loadUsers(page = 1) {
try {
const { data } = await axios.get('/api/users', {
params: {
pageNum: page,
pageSize: this.pageSize,
...Object.fromEntries(Object.entries(this.filters).filter(([_, v]) => v))
}
})
this.users = data.records || []
this.totalCount = data.total || 0
this.currentPage = page
} catch (e) {
console.error('ユーザー取得失敗:', e)
}
},
handleSizeChange(size) {
this.pageSize = size
this.loadUsers()
},
handlePageChange(page) {
this.loadUsers(page)
},
searchUsers() {
this.loadUsers(1)
},
resetFilters() {
this.filters = { id: '', phone: '' }
this.loadUsers(1)
},
handleEdit(user) {
// 編集モーダルを開く処理
},
handleDelete(user) {
this.$confirm('このユーザーを削除してもよろしいですか?', '確認', {
type: 'warning'
}).then(async () => {
await axios.delete(`/api/users/${user.id}`)
this.$message.success('削除完了')
this.loadUsers()
})
}
}
}
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































上記コードはVue 2 + Element UI v1.4系に準拠した典型的な管理画面実装を示しています。実際のバックエンドAPI连携時はレスポンス構造を適宜調整し、認証状態の管理にはVuexストアのモジュール設計を推奨します。

タグ: Element-UI vuejs Vuex vue-router Axios

6月27日 21:38 投稿