目次
(3) メインインターフェースのフレームワークコードを記述する
I.はじめに:
まず、完成したプロジェクト テンプレートのスクリーンショット:
オープン ソースの Vue 管理バックグラウンド テンプレートが多数あります。バックグラウンド管理を迅速に開発する必要がある場合は、「Vue 管理 バックグラウンド テンプレート」を検索できます。コードのみが必要な学生は、ソース。この章のブログを通じて、次のことを学ぶことができます。
(1)、要素 UI コンポーネント ライブラリの使用。
(2) コンポーネントをカスタマイズする方法。
(3) ルーティングを上手に利用する。
(4) Vue プロジェクト開発アイデアの改善。
(5)、……
このプロジェクトは、前の章の統合プロジェクトに基づいて開発されています。最初に以下のリンクをクリックして読んでください。(この章をバリアフリーで読んでいる場合は、無視してください)
2. ウェブサイトのページ分析
Web サイトは、ログイン ページ、メイン インターフェイス、およびコンテンツ ページで構成されます。
メイン インターフェイスのモジュール全体は次のもので構成されます。
(1) ナビゲーションバー。
(2)、左側のナビゲーション メニュー バー。
(3)、ページタブバー。
(4)、内容欄(表示ページ)。
構成。
メニュー バーのスイッチをクリックすると、コンテンツ バーの内容のみが変更され、次のような結果が得られます。
ログイン ページとメイン インターフェイスは第 1 レベルのルートであり、コンテンツ ページはメイン インターフェイスの下にネストされたルートです。
3. 開発手順
(1)、インストール要素
公式ウェブサイト: Vue 3 UI フレームワーク | Element Plus。
リソースパッケージのダウンロード速度が速くなるように、最初に国内のnpmミラーをインストールします。
npm install cnpm -g --registry=https://registry.npmmirror.com
次に要素をインストールします
npm install element-plus --save
プロジェクトをインポートし、次のコードを main.js ファイルに追加します。
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)
導入が成功したかどうかをテストし、ボタンコンポーネントをhome.vueに追加します。
<el-button type="primary">プライマリ</el-button>
プロジェクトを実行します: npm run dev
実行時の効果は次のとおりで、インポートが成功したことを示しています。
(2)、svgプラグインをインストールして使用します
- インストール:
npm i vite-plugin-svg-icons -D
- src の下に新しいストレージ svg ディレクトリを作成します。
- コンポーネント ディレクトリに新しいコンポーネントを作成します: SvgIcon.vue
<template>
<svg aria-hidden="true">
<use :xlink:href="symbolId" />
</svg>
</template>
<script>
import { defineComponent, computed } from 'vue';
export default defineComponent({
name: 'SvgIcon',
props: {
prefix: {
type: String,
default: 'icon',
},
name: {
type: String,
required: true,
},
},
setup(props) {
const symbolId = computed(() => `#${props.prefix}-${props.name}`);
return { symbolId };
},
});
</script>
- vite.config.js で設定します。
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
// 指定symbolId格式
symbolId: '[name]',
})
]
})
- main.js に導入され、コードを追加します。
//Svg 画像をインポートするプラグインで、ページ上に Svg 画像を表示できます
import 'virtual:svg-icons-register'
import SvgIcon from "./components/SvgIcon.vue";
app.component('SvgIcon',SvgIcon)
- この時点で、プロジェクトの実行時にエラーが発生します: fast-glob が見つかりません。fast-globをインストールする必要があります。
npm 私は高速グロブします
- テスト使用
アイコンをクリックして SVG コンテンツをコピーします
新しく作成した svg ディレクトリに新しい svg ファイルを作成し、名前の形式: icon-「アイコン名」を指定し、内容を貼り付けて保存します。
ページで次を使用します。
<SvgIcon name="目的" class="icon-svg" />
(3) メインインターフェースのフレームワークコードを記述する
- まず全体的なフレームワークである home.vue コードを構築します。
<template v-slot:default>
<div :class="['content',isCollapse?'menu--fold':'menu--unfold']">
<!-- 侧边菜单栏 -->
<div class="menuLeft">
<div class="menu-nav-header">
<span>{
{isCollapse?'控制台':'管理控制台'}}</span>
</div>
<!--todo 菜单栏组件 -->
</div>
<!-- 右边内容 -->
<div class="content-main">
<div class="navTop horizontalView">
<div class="nav_tools horizontalView">
<SvgIcon :name="isCollapse?'expand':'fold'" class="icon-svg" @click="isCollapse=!isCollapse" />
</div>
</div>
<!-- todo 内容组件 -->
</div>
</div>
</template>
<script>
export default {
components: {
},
data: function() {
return {
isCollapse: false
}
}
}
</script>
<style>
@import url('../assets/css/home.css');
</style>
- CSSスタイルを書く
共通のものはbase.cssに配置され、ページ固有のものはhome.cssに配置されます。
- Base.css コード:
.content {
width: 100%;
height: 100%;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
/* 水平布局 居中*/
.horizontalView {
position: relative;
flex-direction: row;
display: flex;
align-items: center;
}
/* 垂直布局居中 */
.verticalView {
position: relative;
flex-direction: column;
display: flex;
align-items: center;
}
/* 居中 */
.center {
position: absolute;
top: 50%;
left: 50%;
font-size: 28px;
transform: translate(-50%, -50%);
}
.w100 {
width: 100%;
}
.h100 {
height: 100%;
}
.icon-svg {
width: 1.4rem;
height: 1.4rem;
fill: currentColor;
overflow: hidden;
}
- home.css コード:
/* -------侧边栏 折叠 */
.menu--fold .menuLeft {
width: 64px;
}
.menu--fold .content-main {
margin-left: 64px;
}
/* --------------------- */
/* ---------侧边栏 展开 */
.menu--unfold .menuLeft {
width: 230px;
}
.menu--unfold .content-main {
margin-left: 230px;
}
/* ------------- */
.navTop {
position: relative;
width: 100%;
height: 50px;
z-index: 100;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
box-sizing: border-box;
background: white;
}
.nav_tools {
height: 100%;
}
.nav_tools .icon-svg {
margin-left: 10px;
color: #5b5b5b;
}
.menuLeft {
position: fixed;
top: 0;
left: 0;
bottom: 0;
z-index: 1020;
overflow: hidden;
background-color: #263238;
}
.content-main {
position: relative;
background: #f1f4f5;
height: 100%;
}
.menu-nav-header {
color: white;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 20px;
font-weight: bold;
/* background-color: #9fbea7; */
background-color: #566f7e;
}
/* 动画 */
.nav_tools,
.menuLeft,
.content-main {
transition: inline-block 0.3s, left 0.3s, width 0.3s, margin-left 0.3s, font-size 0.3s;
}
- Base.css は app.vue に配置されます
@import url("./assets/css/base.css");
- ページの効果を見てみましょう。
- 上の「折りたたむ」ボタンをクリックします
(4) メニューバーの作成
まずコンポーネントの使用法に関するドキュメントを理解してください:メニュー メニュー | Element Plus
サンプル コードをコピーして、コンテンツのプロパティとスタイルをカスタマイズし、コンポーネントによって提供される折りたたみアニメーションを閉じ、アニメーション スタイルをカスタマイズします。
- home.vue のメニュー コンポーネント コードを追加および変更する
<!--todo 菜单栏组件 -->
<el-menu active-text-color="#fff" background-color="#263238" class="el-menu-vertical-demo"
:collapse-transition="false" default-active="2" text-color="#96a4ab " @open="handleOpen"
@close="handleClose" :collapse="isCollapse">
<el-menu-item index="1">
<SvgIcon name="home" class="icon-svg" />
<span slot=""> 首页</span>
</el-menu-item>
<el-sub-menu index="2">
<template #title>
<SvgIcon name="img" class="icon-svg" />
<span> 图片管理</span>
</template>
<el-menu-item index="1-1">
<SvgIcon name="img" class="icon-svg" />
<span> 图片1</span>
</el-menu-item>
<el-menu-item index="1-2">
<SvgIcon name="img" class="icon-svg" />
<span> 图片2</span>
</el-menu-item>
<el-sub-menu index="1-4">
<template #title>
<SvgIcon name="img" class="icon-svg" />
<span> 图片3</span>
</template>
<el-menu-item index="1-4-1">
<SvgIcon name="img" class="icon-svg" />
<span> 图片三级子菜单</span>
</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="3">
<template #title>
<SvgIcon name="collection" class="icon-svg" />
<span> 收藏管理</span>
</template>
<el-menu-item index="3">
<SvgIcon name="collection" class="icon-svg" />
<span class="icon-text"> 收藏</span>
</el-menu-item>
</el-sub-menu>
<el-menu-item index="4">
<SvgIcon name="about" class="icon-svg" />
<span> 设置</span>
</el-menu-item>
</el-menu>
- 変更したスタイルコードをhome.cssに追加します。
/* 修改菜单栏样式样式 */
.menuLeft .el-menu {
border-right: none;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
border-right: none;
width: 230px;
}
.el-menu .icon-text {
margin-left: 10px;
}
- ページ効果:
メニューバーの書き込みはまだ終わっていませんが、上記のような書き方だと、メニューを追加・修正・削除するたびに、ページ上の位置を探して修正するのが少々面倒です。ページコードやメニュー項目が多すぎると編集や修正が面倒になるため、後でコードを最適化し、メニューをメニューデータセットにカプセル化して、ページ上の for ループで表示します。
(5)、新しいページとルーティング
- 新しいページ:
Index.vue、img1.vue、collect.vue、set.vue。そして、ページにページ識別テキストを追加します。
- ルーティングを構成します。
ルーターディレクトリ内のindex.jsコード:
// import Vue from 'vue' //引入Vue
import {
createRouter,
createWebHashHistory
} from 'vue-router' //引入vue-router
// Vue.use(Router) //Vue全局使用Router
import home from '../views/home.vue'
import login from '../views/login.vue'
import index from '../views/index.vue'
import collect from '../views/collect.vue'
import set from '../views/set.vue'
import img1 from '../views/img1.vue'
const routes = [{
path: '',
redirect: "home"
}, {
path: '/',
redirect: "home"
},
{
path: '/login',
name: 'login',
component: login,
meta: {
title: '登录'
}
},
{
path: '/home',
name: 'home',
component: home,
/* 子路由 */
children: [{
path: '/',
redirect: "index"
},{
path: '',
redirect: "index"
}, {
path: '/index',
name: 'index',
component: index,
meta: {
title: '首页',
}
},
{
path: '/collect',
name: 'collect',
component: collect,
meta: {
title: '收藏',
isTab: true
}
},
{
path: '/img1',
name: 'img1',
component: img1,
meta: {
title: '图片1',
isTab: true
}
},
{
path: '/set',
name: 'set',
component: set,
meta: {
title: '设置',
isTab: true
}
}
]
}
];
// 导航守卫
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
/* router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next();
} else {
let token = localStorage.getItem('Authorization');
if (token === null || token === '') {
next('/login');
} else {
next();
}
}
}); */
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router;
- ルーティング コンポーネントを home.vue に追加して、ルーティング ジャンプをテストします。
<ルータービュー />
- ジャンプルーティングコードをメニュー項目に追加します。
クリック リダイレクト ルーティング コードを [ホーム] メニュー項目に追加します: @click="$router.push({ name: 'index' })"
同様に、他のメニュー項目にも対応するコードを追加します。
- テスト効果
「設定」をクリックします
「お気に入り」をクリックします
OK、ルーティング設定は成功しました!
(6)、カスタム ページ ラベル バー
2 つのステップ:
(1) ルート切り替えを監視し、リダイレクトされたルートの名前 (またはパス) コレクションを保存し、現在のルート名を保存します。
(2) el-tabs タブ ページ コンポーネントTabs tab | Element Plusを使用して、スタイルをカスタマイズし、コンテンツ コンポーネントを記述します。
最初の一歩:
- ルートの変更を監視し、監視とデータは同じレイヤーにあります。
watch: {
$route: {
handler(to, from) {
if (to.path != from.path) {
// 处理路由
this.routeHandle(to);
}
}
}
},
- 忘れて、すべての js コードを直接入力してください。
<script>
export default {
components: {
},
data: function() {
return {
isCollapse: false,
mainTabs: [],
mainTabsActiveName: '',
menuActiveName: '',
menus: []
}
},
created() {
let that = this;
that.routeHandle(that.$route);
},
// 监听路由变化
watch: {
$route: {
handler(to, from) {
if (to.path != from.path) {
// 处理路由
this.routeHandle(to);
}
}
}
},
methods: {
resetDocumentClientHeight: function() {
this.documentClientHeight = document.documentElement['clientHeight'];
window.onresize = () => {
this.documentClientHeight = document.documentElement['clientHeight'];
this.loadSiteContentViewHeight();
};
},
loadSiteContentViewHeight: function() {
let height = this.documentClientHeight - 52; //减去导航栏高度50
console.log(this.$route.meta.isTab)
if (this.$route.meta.isTab) {
height -= 70; //减去tab栏高度40,减去上下边距30
/* this.siteContentViewHeight = {
'min-height': height + 'px'
}; */
this.siteContentViewHeight = height;
} else {
height -= 30;
//给内容区设置高度
this.siteContentViewHeight = height;
}
},
routeHandle: function(route) {
//每次切换页面,重新计算页面高度和内容区高度
this.resetDocumentClientHeight();
this.loadSiteContentViewHeight();
if (route.meta.isTab) {
// tab选中, 不存在先添加
var tab = this.mainTabs.filter(item => item.name === route.name)[0];
if (!tab) {
if (route.meta.isDynamic) {
route = this.dynamicMenuRoutes.filter(item => item.name === route.name)[0];
if (!route) {
return console.error('未能找到可用标签页!');
}
}
tab = {
menuId: route.meta.menuId || route.name,
name: route.name,
title: route.meta.title,
iframeUrl: route.meta.iframeUrl || '',
params: route.params,
query: route.query
};
this.mainTabs = this.mainTabs.concat(tab);
}
this.menuActiveName = tab.menuId + '';
this.mainTabsActiveName = tab.name;
}
},
mounted: function() {
let that = this;
that.resetDocumentClientHeight();
that.loadSiteContentViewHeight();
}
}
}
</script>
ステップ2:
- コンポーネントの書き込み
<!-- todo 内容组件 -->
<el-tabs v-if="$route.meta.isTab" v-model="mainTabsActiveName" :closable="true"
@tab-click="selectedTabHandle" @tab-remove="removeTabHandle">
<el-scrollbar ref="scroll" :height="siteContentViewHeight+32+'px'" @scroll="scroll">
<el-tab-pane v-for="item in mainTabs" :label="item.title" :name="item.name">
<el-card :style="'min-height:'+siteContentViewHeight + 'px'">
<router-view v-if="item.name === mainTabsActiveName" />
</el-card>
</el-tab-pane>
</el-scrollbar>
</el-tabs>
<div v-else>
<el-scrollbar ref="scroll" :height="siteContentViewHeight+32+'px'" @scroll="scroll">
<!-- 主入口标签页 e -->
<el-card :style="'min-height:'+ siteContentViewHeight + 'px'">
<router-view />
</el-card>
</el-scrollbar>
</div>
- スタイルを変更します。
/* 修改标签栏样式 */
.content-main .el-tabs .el-tabs__header {
z-index: 90;
padding: 0 55px 0 15px;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
background-color: #fff;
}
.content-main .el-tabs .el-tabs__nav-wrap::after {
width: 0px;
}
.content-main .el-scrollbar .el-card {
margin: 15px 15px;
}
.content-main .el-tabs .el-tabs__header{
margin: unset;
}
.content-main .el-tabs .el-tab-pane{
}
- メソッドに関数メソッドを追加
selectedTabHandle: function(tab, e) {
tab = this.mainTabs.filter(item => item.name === tab.paneName);
if (tab.length >= 1) {
this.$router.push({
name: tab[0].name,
query: tab[0].query,
params: tab[0].params
});
}
},
removeTabHandle: function(tabName) {
this.mainTabs = this.mainTabs.filter(item => item.name !== tabName);
if (this.mainTabs.length >= 1) {
// 当前选中tab被删除
if (tabName === this.mainTabsActiveName) {
var tab = this.mainTabs[this.mainTabs.length - 1];
this.$router.push({
name: tab.name,
query: tab.query,
params: tab.params
},
() => {
this.mainTabsActiveName = this.$route.name;
}
);
}
} else {
this.menuActiveName = '';
this.$router.push({
name: 'Home'
});
}
},
- 効果:
(7) パッケージのメニューバーを変更する
- ルーターファイルの下に新しいファイルを作成します
- menu.js ファイルのコード:
var mu = {
longTitle: '管理控制台',
littleTitle: '控制台',
items: [{
iconName: 'home',
name: '首页',
routerName: 'index',
disabled: false
}, {
iconName: 'img',
name: '图片管理',
submenu: [{
iconName: 'img',
name: '图片一',
routerName: 'img1',
disabled: false
}, {
iconName: 'img',
name: '图片二',
routerName: 'img2',
disabled: false
}, {
iconName: 'img',
name: '图片三管理',
submenu: [{
iconName: 'img',
name: '图片三',
routerName: 'img1',
disabled: true
}]
}]
},
{
iconName: 'collection',
name: '收藏管理',
submenu: [{
iconName: 'collection',
name: '收藏',
routerName: 'collect',
disabled: false
}]
},
{
iconName: 'about',
name: '设置',
routerName: 'set',
disabled: false
}
]
}
export default mu;
- メニューコンポーネントを書き換えます。
<div class="menu-nav-header">
<span>{
{isCollapse?littleTitle:longTitle}}</span>
</div>
<el-menu active-text-color="#fff" background-color="#263238" class="el-menu-vertical-demo"
:collapse-transition="false" text-color="#96a4ab " @open="handleOpen"
@close="handleClose" :collapse="isCollapse">
<template v-for="(item,index) in menus">
<el-menu-item v-if="!item.submenu" :index="index" @click="$router.push({ name: item.routerName })" :disabled="item.disabled">
<SvgIcon :name="item.iconName" class="icon-svg" />
<span slot=""> {
{item.name}}</span>
</el-menu-item>
<el-sub-menu v-else :index="index">
<template #title>
<SvgIcon :name="item.iconName" class="icon-svg" />
<span slot=""> {
{item.name}}</span>
</template>
<template v-for="(submenuItem,submenuIndex) in item.submenu">
<el-menu-item v-if="!submenuItem.submenu" :index="index+'-'+submenuIndex" :disabled="submenuItem.disabled"
@click="$router.push({ name: submenuItem.routerName })">
<SvgIcon :name="submenuItem.iconName" class="icon-svg" />
<span slot=""> {
{submenuItem.name}}</span>
</el-menu-item>
<el-sub-menu v-else :index="index+'-'+submenuIndex">
<template #title>
<SvgIcon :name="submenuItem.iconName" class="icon-svg" />
<span slot=""> {
{submenuItem.name}}</span>
</template>
<el-menu-item v-for="(item3,index3) in submenuItem.submenu" :index="index" :disabled="item3.disabled"
@click="$router.push({ name: item3.routerName })">
<SvgIcon :name="item3.iconName" class="icon-svg" />
<span slot=""> {
{item3.name}}</span>
</el-menu-item>
</el-sub-menu>
</template>
</el-sub-menu>
</template>
</el-menu>
ネストされるサブメニューは 3 レベルのみです。それ以上のサブメニューがある場合は、コンポーネント内で複数の for ループをネストする必要があります。
- スクリプト コードは最初にメニューをインポートします。
'../router/menu/menu.js' から mu をインポートします。
- 呼び出されて作成されました
このように、メニュー バーを変更するには、menu.js で編集するだけで済み、ページ コードを変更する必要はなくなります。
(8)パン粉を付ける
- ブレッドクラム コンポーネントをページに追加します。
<el-breadcrumb separator="/">
<el-breadcrumb-item v-if="!breadcrumbList.size && breadcrumbList[0]!='首页'" :to="{ name: 'index' }">
首页
</el-breadcrumb-item>
<el-breadcrumb-item v-for="it in breadcrumbList">{
{it}}</el-breadcrumb-item>
</el-breadcrumb>
- 作成されたメニュー バー コレクションを次の形式に処理します。
{
"首页":["首页"],
"图片一":["图片管理","图片一"],
......
}
- コード:
//菜单项层级处理,做一个面包屑集合保存
var mus=that.menus
for (let i1 of mus) {
if (i1.submenu) {
for (let i2 of i1.submenu) {
if (i2.submenu) {
for (let i3 of i2.submenu) {
if (!i3.submenu) {
that.breadcrumbObj[i3.name] = [i1.name, i2.name, i3.name];
}
}
} else {
that.breadcrumbObj[i2.name] = [i1.name, i2.name];
console.log(i2.name)
}
}
} else {
that.breadcrumbObj[i1.name] = [i1.name];
console.log(i1.name)
}
}
ルートが変更されたときに値を割り当て、それを監視に追加します。
this.breadcrumbList = this.breadcrumbObj[to.meta.title]
注: ルート内の名前は、メニュー内の名前と一致している必要があります。
4.終了
この時点で、シンプルな管理背景テンプレートが完成しました。ソース コードは評価されず、コード ワードも簡単ではありません。これをご覧になったので、離れる前に「いいね」を押してください。