保姆級別的vue + ElementUI 搭建后台管理系統教程


vue + ElementUI 搭建后台管理系統記錄

本文檔記錄了該系統從零配置的完整過程

項目源碼請訪問:https://gitee.com/szxio/vue2Admin,如果感覺對你有幫助,請點一個小星星,O(∩_∩)O

新建項目

vue create vueadmin

安裝 less-loader

安裝

這里是一個小坑,安裝 less-loader 時推薦安裝指定版本,如果安裝默認高版本會導致項目出錯

cnpm i less-loader@6.0.0 -D

使用

<style lang="less" scoped>
div{
  b{
    span{
      color: red;
    }
  }
}
</style>

引入 ElementUI

安裝

cnpm i element-ui -S

配置

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

Vue.use(ElementUI);

Vue.config.productionTip = false

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

使用

<template>
  <div>
    <el-row>
      <el-button>默認按鈕</el-button>
      <el-button type="primary">主要按鈕</el-button>
      <el-button type="success">成功按鈕</el-button>
      <el-button type="info">信息按鈕</el-button>
      <el-button type="warning">警告按鈕</el-button>
      <el-button type="danger">危險按鈕</el-button>
    </el-row>
  </div>
</template>

配置 VueRouter

npm安裝

  1. 安裝
npm install vue-router
  1. 新建 scr/router/index.js,並添加如下代碼
import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "首頁",
    component: () => import("../views/Home.vue"),
  },
  {
    path: "/about",
    name: "About",
    component: () => import("../views/About.vue"),
  },
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});

// 前置路由攔截器
router.beforeEach((to, from, next) => {
  // 設置當前頁簽名稱
  document.title = to.name;
  next();
});

export default router;

配置前置路由攔截器動態設置每個頁面的瀏覽器頁簽名稱

  1. 修改 main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import router from './router'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  1. 修改 App.vue
<template>
  <div id="app">
    <router-view />
  </div>
</template>
  1. 重啟項目,分別訪問如下地址可以查看頁面效果

VueCli安裝

如果項目是使用vue-cli創建的,則可以使用下面的命令直接生成上述代碼及兩個示例路由。它也會覆蓋你的 App.vue,因此請確保在項目中運行以下命令之前備份這個文件

vue add router

動態生成左側菜單

添加layout組件

  1. 修改路由文件

首先我們要創建好 router 路由,修改 src\router\index.js 文件

import Vue from "vue";
import VueRouter from "vue-router";
import Layouts from "../layouts";

Vue.use(VueRouter);

const routes = [
  {
    path: "",
    redirect: "home",
    component: Layouts,
    children: [
      {
        path: "/home",
        meta: { title: "首頁", icon: "el-icon-s-home" },
        component: () => import("../views/home"),
      },
      {
        path: "system",
        meta: { title: "系統管理", icon: "el-icon-s-home" },
        component: Layouts,
        children: [
          {
            path: "item1",
            meta: { title: "用戶管理", icon: "el-icon-s-home" },
            component: () => import("../views/system/item1"),
          },
          {
            path: "item2",
            meta: { title: "產品管理", icon: "el-icon-s-home" },
            component: () => import("../views/system/item2"),
          },
        ],
      },
    ],
  },
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});

// 前置路由攔截器
router.beforeEach((to, from, next) => {
  // 設置當前頁簽名稱
  document.title = to.meta.title;
  next();
});

export default router;

代碼說明:

  • path:路由地址
  • redirect:重定向到指定路由
  • component:頁面對應的組件
  • children:設置子路由,二級菜單
  • meta:頁面的補充,用來聲明頁面的名稱和圖標等

我們將所有的頁面都放在根路由的 children 下面,如果下面的菜單沒有配置 children 屬性,則表示該菜單是一級菜單,如果設置了則表示二級菜單,可以多級嵌套。上面的路由對應的修改views 文件夾下的文件結構:

  1. 新建src\layouts\index.vue

這個文件用來配置項目頁面的外殼,左側的菜單和頂部的面包屑都會在該文件夾中

頁面結構分成三大部分:

  • 左側菜單
  • 頂部面包屑
  • 內容展示區域

對應成代碼結構如下

<template>
  <div>
    <div>左側菜單</div>
    <div>
      <div>頭部面包屑</div>
      <div>內容展示區</div>
    </div>
  </div>
</template>

我們既然要將頁面在內容展示區顯示,所以我們對應的創建專門用來展示頁面的組件。

所以接下來新建 src\layouts\components\AppContent.vue 組件。組件代碼如下

<template>
    <div>
        <router-view/>
    </div>
</template>

沒有看錯,很簡單,只要放置一個 router-view 標簽即可。然后將 AppContent 組件注冊到 layouts\index.vue

<template>
  <div>
    <div>左側菜單</div>
    <div>
      <div>頭部面包屑</div>
      <div>
        <AppContent />
      </div>
    </div>
  </div>
</template>

<script>
import AppContent from "./components/AppContent.vue";
export default {
  components: {
    AppContent,
  },
};
</script>
  1. 修改 App.vue

只保留 router-view

<template>
  <div>
    <router-view/>
  </div>
</template>

現在我們打開頁面看到如下效果

修改頁面樣式

我們首頁雖然已經展示到了 appcontent 組件中,但是樣式並不是我們想要的效果。現在去修改src\layouts\index.vue文件,添加如下代碼

<template>
    <div class="app-wrapper">
      <div class="sidebar-container">
          左側菜單
      </div>
      <div class="main-container">
          <div class="header-main">頭部面包屑</div>
          <AppContent class="app-main" />
      </div>
    </div>
</template>

<script>
import AppContent from "./components/AppContent.vue";
export default {
  components: {
    AppContent,
  }
}
</script>

<style lang="less" scoped>
.app-wrapper {
  position: relative;
  height: 100%;
  width: 100%;
  .sidebar-container {
    -webkit-transition: width 0.28s;
    transition: width 0.28s;
    width: 200px !important;
    background-color: #304156;
    height: 100%;
    position: fixed;
    font-size: 0px;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1001;
    overflow: hidden;
    -webkit-box-shadow: 2px 0 6px rgb(0 21 41 / 35%);
    box-shadow: 2px 0 6px rgb(0 21 41 / 35%);
    & > div {
      width: 211px !important;
    }
  }
  .main-container {
    min-height: 100%;
    -webkit-transition: margin-left 0.28s;
    transition: margin-left 0.28s;
    margin-left: 200px;
    position: relative;
  }
  .main-container {
    -webkit-transition: margin-left 0.28s;
    transition: margin-left 0.28s;
    position: fixed;
    width: calc(100vw - 210px);
    top: 50px;
    right: 0;
    bottom: 0;
    left: 0;
    .header-main {
      position: fixed;
      height: 50px;
      width: calc(100% - 200px);
      right: 0;
      top: 0;
      display: flex;
      align-items: center;
      border-bottom: 1px solid #ddd;
      padding-left: 15px;
      box-sizing: border-box;
    }
    .app-main {
      min-height: 100%;
      width: 100%;
      position: relative;
      overflow: hidden;
    }
  }
}
</style>

效果展示

引入左側菜單

  1. 新建 src\layouts\components\ElMenu\index.vue 組件,初始化代碼
<template>
  <div>
    <el-menu
      default-active="2"
      class="el-menu-vertical-demo"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b"
    >
      <!-- 可展開菜單 -->
      <el-submenu index="1">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span>導航一</span>
        </template>
        <el-menu-item index="3">
          <i class="el-icon-document"></i>
          <span slot="title">導航三</span>
        </el-menu-item>
      </el-submenu>
      <!-- 點擊菜單 -->
      <el-menu-item index="2">
        <i class="el-icon-menu"></i>
        <span slot="title">導航二</span>
      </el-menu-item>
    </el-menu>
  </div>
</template>
  1. 注冊 ElMenu 組件添加到 src\layouts\index.vue
<template>
  <div class="app-wrapper">
    <!-- 左側菜單 -->
    <ElMenu class="sidebar-container"/>
    <!-- 右側操作區域 -->
    <div class="main-container">
      <!-- 頭部面包屑 -->
      <div class="header-main">頭部面包屑</div>
      <!-- 內容展示區 -->
      <AppContent class="app-main" />
    </div>
  </div>
</template>

<script>
import AppContent from "./components/AppContent.vue";
import ElMenu from "./components/ElMenu/index.vue";
export default {
  components: {
    AppContent,
    ElMenu,
  },
};
</script>

<style lang="less" scoped>
...和上面一樣,這里省略
</style>
  1. 此時打開頁面可以看到左側菜單

遞歸菜單組件

目前我們看到的只是一個寫死的菜單,我們想要的是根據 router 文件自動生成對應的菜單,那么應該怎么做呢?

首先左側菜單的每一項都可以當做一個組件,然后獲取到 router 中的所有菜單,循環展示每一項菜單即可,那么就開始做吧!

新建 src\layouts\components\ElMenu\MenuItem.vue 組件,用來展示每一項的菜單名稱

修改 src\layouts\components\ElMenu\index.vue 頁面,引入 router.js 獲取定義的路由數據,並且引入 MenuItem 組件去循環展示每一項菜單

<template>
  <div>
    <el-menu
      :default-active="$route.path"
      class="el-menu-vertical-demo"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b"
    >
      <MenuItem
        v-for="(route, index) in routersList"
        :key="index"
        :item="route"
        :fatherPath="route.path"
      ></MenuItem>
    </el-menu>
  </div>
</template>

<script>
import routers from "../../../router";
import MenuItem from "./MenuItem.vue";
export default {
  components: {
    MenuItem,
  },
  data() {
    return {
      routersList: [],
    };
  },
  mounted() {
    // 獲取所有定義的一級菜單和多級菜單
    this.routersList = routers.options.routes[0].children;
  }
};
</script>

代碼說明:

el-menu 標簽中我們定義了 :default-active="$route.path" ,這個含義表示默認選中當前路由菜單,如果是子級菜單會自動展開並選中,這是因為下面的代碼中我們會將每一個頁面的 path 作為菜單的 index

另外代碼中我們遍歷 MenuItem 組件時傳遞了每個菜單的對象 item 和每個菜單的路徑 fatherPaht ,現在我們要到 MenuItem 組件去根據這個兩個屬性做遞歸展示根菜單和多級菜單結構。來到 MenuItem 組件中,編寫如下代碼

<template>
  <div>
    <!-- 根菜單 -->
    <router-link tag="span" :to="resolvePath()" v-if="!item.children">
      <el-menu-item :index="resolvePath()">
        <i :class="item.meta.icon"></i>
        <span slot="title">{{ item.meta.title }}</span>
      </el-menu-item>
    </router-link>

    <!-- 可展開菜單 -->
    <el-submenu :index="resolvePath()" v-else>
      <template slot="title">
        <i :class="item.meta.icon"></i>
        <span slot="title">{{ item.meta.title }}</span>
      </template>
      <!-- 這里遞歸去展示多級菜單 -->
      <menu-item
        v-for="(route, index) in item.children"
        :key="index"
        :item="route"
        :fatherPath="resolvePath(route.path)"
      >
      </menu-item>
    </el-submenu>
  </div>
</template>

<script>
// 引入path用來處理路徑
import path from "path";

export default {
  // 做組件遞歸時必須定義一個name。然后遞歸時的組件名就是這里的name值
  name: "MenuItem",
  props: {
    // 上一級的路由信息
    item: {
      type: Object,
      default: null,
    },
    // 上一級的路徑
    fatherPath: {
      type: String,
      default: "",
    },
  },
  data() {
    return {};
  },
  methods: {
    resolvePath(routePath = "") {
      return path.resolve(this.fatherPath, routePath);
    },
  },
};
</script>

代碼說明

  • 在做組件遞歸時,必須要在遞歸組件內聲明 name 屬性,屬性值就是當前組件的名稱,這樣才能實現多級嵌套循環效果。

另外在ElementUI 中的菜單分成兩種類型,分別如下

<el-menu-item index="4">
    <i class="el-icon-setting"></i>
    <span slot="title">導航四</span>
</el-menu-item>
  • 這種的表示根菜單
<el-submenu index="1">
    <template slot="title">
        <i class="el-icon-location"></i>
        <span>導航一</span>
    </template>
    <el-menu-item index="4">
        <i class="el-icon-setting"></i>
        <span slot="title">導航四</span>
    </el-menu-item>
</el-submenu>
  • 這種的表示一個可展開的菜單,我們根據路由有沒有 children 來判斷這個菜單是否有子菜單

在根菜單外層添加了一個 router-link 實現了點擊菜單跳轉到不同頁面

現在我們來查看效果

菜單上出現了一個根菜單和一個二級菜單

添加路由自動完成菜單嵌套

現在我們已經完成了一個二級菜單的展示,那么我們添加一個三級路由會不會自動出現三級菜單呢?

首先新建一個測試頁面,在文件夾 item2 下面新建一個 item2-1,並且在里面添加一個 index.vue 文件,如下圖:

然后去 src\router\index.js 添加這個頁面的路由

添加完成后可以發現產品管理菜單自動變成了一個可展開的菜單,展開后里面有一個類別列表菜單

添加頭部面包屑

基礎用法

我們想要在頭部添加一個如下的效果,可以很清晰的知道當前瀏覽的是哪個頁面

  1. layouts 文件夾添加 HeaderNav 組件,組件地址: src\layouts\components\HeaderNav.vue,添加如下初始代碼
<template>
  <div>
    <el-breadcrumb separator="/">
      <el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
      <el-breadcrumb-item><a href="/">活動管理</a></el-breadcrumb-item>
      <el-breadcrumb-item>活動列表</el-breadcrumb-item>
      <el-breadcrumb-item>活動詳情</el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>
  1. 然后再 src\layouts\index.vue 文件中引入 HeaderNav 組件
<template>
  <div>
    <div class="app-wrapper">
      <!-- 左側菜單 -->
      <ElMenu class="sidebar-container" />
      <!-- 右側操作區域 -->
      <div class="main-container">
        <!-- 頭部面包屑 -->
        <HeaderNav class="header-main" />
        <!-- 內容展示區 -->
        <AppContent class="app-main" />
      </div>
    </div>
  </div>
</template>

<script>
import AppContent from "./components/AppContent.vue";
import ElMenu from "./components/ElMenu/index.vue";
import HeaderNav from "./components/HeaderNav.vue";
export default {
  components: {
    AppContent,
    ElMenu,
    HeaderNav,
  }
};
</script>

<style lang="less" scoped>
樣式省略。。。
</style>
  1. 此時我們的頁面效果是這樣的

是不是有點感覺了呢

  1. 接下只需要監聽頁面的變化去實時獲取最新的路由信息即可,然后循環遍歷顯示

實現代碼:

<template>
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item
        v-for="(route, index) in breadcrumbItems"
        :key="index"
      >
        <i :class="route.icon"></i>
        <span>{{ route.title }}</span>
      </el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script>
export default {
  data() {
    return {
      breadcrumbItems: [],
    };
  },
  mounted() {
    this.geBreadcrumbItems(this.$route);
  },
  methods: {
    geBreadcrumbItems(route) {
      // 獲取當前頁面的路由組
      this.breadcrumbItems = route.matched;
      // 從下標為1的位置開始獲取路由,去除了最外層定義的根路由信息,並且獲取到的數組里面只有meta數據,方便我們取值
      this.breadcrumbItems = this.breadcrumbItems
        .map((item) => item.meta)
        .splice(1);
    },
  },
  watch: {
    $route: function (newVal) {
      this.geBreadcrumbItems(newVal);
    },
  },
};
</script>

效果展示

添加首頁快速入口

我們已經實現了基本效果,但是我們還想在面包屑的首位添加首頁的連接,點擊首頁文字快速跳轉到到首頁

修改 src\layouts\components\HeaderNav.vue 代碼為如下

<template>
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item
        v-for="(route, index) in breadcrumbItems"
        :key="index"
      >
        <!-- 判斷面包屑是否有path屬性,如果有則顯示router-link標簽 -->
        <router-link v-if="route.path" :to="route.path">
          <i :class="route.icon"></i>
          <span>{{ route.title }}</span>
        </router-link>
        <!-- 如果沒有path屬性則不跳轉 -->
        <template v-else>
          <i :class="route.icon"></i>
          <span>{{ route.title }}</span>
        </template>
      </el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script>
export default {
  data() {
    return {
      breadcrumbItems: [],
    };
  },
  mounted() {
    this.geBreadcrumbItems(this.$route);
  },
  methods: {
    geBreadcrumbItems(route) {
      // 獲取當前頁面的路由組
      this.breadcrumbItems = route.matched;
      // 從下標為1的位置開始獲取路由,去除了最外層定義的根路由信息,並且獲取到的數組里面只有meta數據,方便我們取值
      this.breadcrumbItems = this.breadcrumbItems
        .map((item) => item.meta)
        .splice(1);

      // 判斷當前頁面是否已經是首頁
      let nowPath = route.path;
      // 如果當前頁面不是首頁,則在面包屑的首位置添加一個首頁鏈接
      if (nowPath !== "/home") {
        this.breadcrumbItems.unshift({
          title: "首頁",
          icon: "el-icon-s-home",
          path: "/home",
        });
      }
    },
  },
  watch: {
    $route: function (newVal) {
      this.geBreadcrumbItems(newVal);
    },
  },
};
</script>

修改之后頁面效果是當我們進入非首頁頁面時,面包屑前面會有一個首頁的快速入口,當進入首頁時不會展示首頁連接

個性化菜單配置

配置獨立頁面

現在我們看到的頁面都嵌套在左側菜單和面包屑下面,但是有些頁面時不能在這個嵌套頁面的,例如登錄頁面。那么我們怎么通過配置路由來實現這樣的效果呢?

首先添加登錄頁面,新建 src\views\login\index.vue,編寫如下代碼

<template>
    <div>
        登錄頁面
    </div>
</template>

添加完登錄頁面后前往 src\router\index.js 文件添加路由信息,如下圖

我們在登錄頁面的路由信息中的增加一個 oneself:true 的標識,用來標識這個頁面時獨自打開的,不需要嵌套在菜單下

添加完路由后找到 src\layouts\index.vue 頁面修改為如下代碼

<template>
  <div>
    <!-- 判斷是否在空白頁打開 -->
    <template v-if="!isOneself">
      <div class="app-wrapper">
        <div class="sidebar-container">
          <ElMenu />
        </div>
        <div class="main-container">
          <HeaderNav class="header-main" />
          <AppContent class="app-main" />
        </div>
      </div>
    </template>
    <!-- 如果在空白頁打開則不顯示框架 -->
    <template v-else>
      <AppContent />
    </template>
  </div>
</template>

<script>
import AppContent from "./components/AppContent.vue";
import ElMenu from "./components/ElMenu/index.vue";
import HeaderNav from "./components/HeaderNav.vue";
export default {
  components: {
    AppContent,
    ElMenu,
    HeaderNav,
  },
  data() {
    return {
      isOneself: false,
    };
  },
  mounted() {
    // 獲取當前路由是否是獨自打開的
    this.isOneself = this.$route.meta.oneself;
  },
  watch: {
    // 監聽路由變化,實時獲取路由信息
    $route: function (newVal) {
      this.isOneself = newVal.meta.oneself;
    },
  },
};
</script>

<style lang="less" scoped>
css省略。。。
</style>

修改完成后查看頁面效果

效果很明顯,點擊了登錄后左側的菜單和面包屑都沒有了,瀏覽器只會展示登錄頁面信息。

到這里我們會發現登錄頁面作為了一個菜單項顯示到了左側菜單中,這個問題怎么解決呢?

配置隱藏菜單

找到 src\router\index.js 文件,為登錄頁面添加一個 hide:true ,如下圖,這個屬性用來表示這個頁面不在左側菜單中顯示

添加完成后找到 src\layouts\components\ElMenu\MenuItem.vue 文件,在根標簽上添加一個 v-if 判斷,用來判斷當前菜單是否需要被渲染

由於這個功能所添加的代碼極少,所以就不貼代碼了。修改完之后查看頁面

通過動畫可以看到登錄頁面已經不在菜單中展示,修改頁面地址也會正常的在新頁面中打開。

配置外部連接

現在我們配置的地址只能配置我們項目中的地址,那么我需要點擊菜單直接打開百度怎么做呢?

首先添加路由信息如下

此時我們點擊菜單並不能正常的打開百度

這是因為我們並沒有判斷頁面的 path 類型。

接下來新建 src\layouts\components\ElMenu\MenuLink.vue,編寫如下代碼

下面代碼的含義是定義了一個動態組件,根據父組件傳遞過來的路徑類型顯示不同的組件

<template>
  <component :is="type" v-bind="linkProps(to)">
    <slot />
  </component>
</template>

<script>
export default {
  props: {
    // 接收從父組件傳遞過來的頁面地址
    to: {
      type: String,
      required: true,
    },
  },
  computed: {
    isExternal() {
      return /^(https?:|mailto:|tel:)/.test(this.to);
    },
    type() {
      // 根據路徑判斷組件類型,如果是外部連接則用a標簽
      if (this.isExternal) {
        return "a";
      }
      // 如果不是外部連接則用router-link組件包裹
      return "router-link";
    },
  },
  methods: {
    // 綁定組件屬性
    linkProps(to) {
      // 如果是外部連接則設置a標簽的href地址為傳遞過來的地址,並且設置在新標簽打開
      if (this.isExternal) {
        return {
          href: to,
          target: "_blank",
          style: {
            "text-decoration": "none",
          },
        };
      }
      // 如果是內部地址則設置router-link的to屬性值,以及tag屬性值為span
      return {
        to: to,
        tag: "span",
      };
    },
  },
};
</script>

然后找到 src\layouts\components\ElMenu\MenuItem.vue 文件,引入剛剛新建 MenuLink 組件

修改代碼如下

<template>
  <!-- 判斷當前頁面是否顯示,如果hide為true,則不渲染該菜單 -->
  <div v-if="!item.meta.hide">
    <!-- 根菜單 -->
    <MenuLink :to="resolvePath()" v-if="!item.children">
      <el-menu-item :index="resolvePath()">
        <i :class="item.meta.icon"></i>
        <span slot="title">{{ item.meta.title }}</span>
      </el-menu-item>
    </MenuLink>

    <!-- 可展開菜單 -->
    <el-submenu :index="resolvePath()" v-else>
      <template slot="title">
        <i :class="item.meta.icon"></i>
        <span slot="title">{{ item.meta.title }}</span>
      </template>
      <!-- 這里遞歸去展示多級菜單 -->
      <menu-item
        v-for="(route, index) in item.children"
        :key="index"
        :item="route"
        :fatherPath="resolvePath(route.path)"
      >
      </menu-item>
    </el-submenu>
  </div>
</template>

<script>
// 引入path用來處理路徑
import path from "path";
import MenuLink from "./MenuLink.vue";

export default {
  // 做組件遞歸時必須定義一個name。然后遞歸時的組件名就是這里的name值
  name: "MenuItem",
  components: {
    MenuLink,
  },
  props: {
    // 上一級的路由信息
    item: {
      type: Object,
      default: null,
    },
    // 上一級的路徑
    fatherPath: {
      type: String,
      default: "",
    },
  },
  data() {
    return {};
  },
  methods: {
    // 判斷路徑是否是外部地址
    isExternal(path) {
      return /^(https?:|mailto:|tel:)/.test(path);
    },
    // 解析頁面地址
    resolvePath(routePath = "") {
      // 判斷當前頁面地址是否為外部地址
      if (this.isExternal(routePath)) {
        return routePath;
      }
      // 判斷從父組件傳遞過來的地址是否為外部地址
      if (this.isExternal(this.fatherPath)) {
        return this.fatherPath;
      }
      // 格式化頁面地址
      return path.resolve(this.fatherPath, routePath);
    },
  },
};
</script>

圖片說明修改點

修改完成后查看頁面效果

現在可以看到點擊百度搜索菜單后在新頁簽打開了百度。

配置多環境地址

首先安裝 cross-env

npm i --save-dev cross-env

然后修改 package.json 文件中的 scripts 對象

{
  ......省略其他
    
  "scripts": {
    "serve": "cross-env VUE_APP_ENV=dev vue-cli-service serve",
    "build": "cross-env VUE_APP_ENV=production vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

  ......省略其他
}

我們在啟動命令和打包命令前添加 cross-env 關鍵字,然后使用鍵值對的方式對一個變量賦值 VUE_APP_ENV=dev

然后新建src\utils\baseurl.js 文件,編寫如下代碼

// 封裝公共的請求api
const apiConfig = {
    // 開發環境
    dev: {
        fayongApi: "https://192.168.199.100"
    },
    // 生產環境
    production: {
        fayongApi: "https://appsh.yikongenomics.com"
    },
};

// 根據全局全局變量自動切換請求地址前綴
export default apiConfig[process.env.VUE_APP_ENV];

關鍵代碼process.env.VUE_APP_ENV 通過這個可以獲取到輸入不同命令式設置的不同值。

最后我們在頁面中引入 baseurl 來查看當前獲取的環境地址

<template>
    <div>
        首頁
    </div>
</template>

<script>
import env from "../../utils/baseurl"
export default {
    data() {
      return{

      }  
    },
    mounted(){
        console.log(env.fayongApi);  //=> https://192.168.199.100
    }
}
</script>

此時獲取到的就是本地的一個地址,當我們打包后,這里就會自動變成線上地址,從而實現了多套環境的搭建和根據打包命令自動切換的功能。

配置代理和publicPath

在項目根目錄新建 vue.config.js。配置代碼如下

module.exports = {
    publicPath: "./",
    devServer: {
        disableHostCheck: true, //禁用主機檢查 
        proxy: {
            "/fayong": { // 設置以什么前綴開頭的請求用來代理
                target: "http://w79f7c.natappfree.cc/index", //要訪問的跨域的域名
                secure: false, // 使用的是http協議則設置為false,https協議則設置為true
                changOrigin: true, //開啟代理
                pathRewrite: {
                    "^/fayong": "",
                },
            }
        },
    },
};

然后重啟項目生效

簡單封裝一下 axios

首先安裝 axios

npm i axios --save

然后新建 src\utils\http.js,編寫如下代碼

// 引入axiox
import axios from 'axios'
// 創建axios實例
const service = axios.create()

// 請求攔截器
axios.interceptors.request.use(function (config) {
    // 在這里可以添加請求頭,請求token等信息
    return config;
}, function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
});

// 響應攔截器
service.interceptors.response.use(function (result) {
    // 判斷成功
    const { status, data } = result
    // 判斷接口返回狀態
    if (status === 200) {
        // 如果接口正常則返回接口給的數據
        return data
    } else {
        // 如果不正常則返回一個錯誤信息
        return Promise.reject('系統未知錯誤,請反饋給管理員')
    }
}, function (error) {
    // 返回錯誤信息
    return Promise.reject(error)
})

export default service

最后來使用一下

import http from '../../utils/http'

export default {
  data() {
    return {}
  },
  methods: {
    test() {
      http
        .get(`node/search/users?q=songzx`)
        .then((res) => {
          console.log(res)
        })
        .catch((err) => {
          console.log(err)
        })
    },
  },
}

查看控制台拿到的數據就是接口直接返回的數據

封裝全局Loading方法

main.js 中添加如下方法

/**
 * 配置全局loading提示框
 * 顯示loading this.showLoading()
 * 關閉loading this.hideLoading()
 */
Vue.prototype.loading = null
Vue.prototype.showLoading = function (msg = 'Loading') {
  Vue.prototype.loading = this.$loading({
    lock: true,
    text: msg,
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  });
}
Vue.prototype.hideLoading = function(){
  Vue.prototype.loading.close();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM