前言

之前讲过使用 Element 辅助前端页面的开发,但是只用到了比较少的内容,这一篇我们来做一下系统的核心页面——图书管理页面的前端部分,旨在熟悉 Vue 的更多特性。

一、导航栏的实现

我们的项目虽然本质上是单页面应用,但表面上有多个功能页面,比如首页、图书馆、笔记本等,后期根据情况还可以把一些功能集中起来做一个后台管理页面。为了方便用户在这三个页面之间切换,我们需要添加一个导航栏。

这个导航栏的要求很简单:

  1. 能够在每个页面显示
  2. 美观

1.路由配置

为了实现第一个要求,我们需要把导航栏放在其它页面的父页面中(对 Vue 来说就是父组件),之前我们讲过,App.vue 是所有组件的父组件,但把导航栏放进去不合适,因为我们的登录页面中不应该显示导航栏。

为了解决这个问题,我们在 components 目录下直接新建一个组件,命名为 Home.vue,原始代码如下:

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

<script>
  export default {
    name: 'Home'
  }
</script>

<style scoped>

</style>

这里和 App.vue 一样,写入了一个 <router-view/>,也就是子页面(组件)显示的地方。

接下来,来建立路由的父子关系。注意我们在一个组件中通过导入引用了其它组件,也可以称之为父子组件,但想要通过 <router-view/> 控制子组件的显示,则需要进行路由的相关配置。

打开 router/index.js ,修改代码如下

import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '../components/home/AppIndex'
import Login from '../components/Login'
import Home from '../components/Home'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/home',
      name: 'Home',
      component: Home,
      // home页面并不需要被访问
      redirect: '/index',
      children: [
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        }
      ]
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    }
  ]
})

注意我们并没有把首页的访问路径设置为 /home/index,仍然可以通过 /index 访问首页,这样配置其实是感受不到 /home 这个路径的存在的。之后再添加新的页面,可以直接在 children 中增添对应的内容。

2.使用 NavMenu 组件

打开 Element 的文档,找到 NavMenu 组件相关内容:

https://element.eleme.cn/2.0/#/zh-CN/component/menu

主要有顶栏、侧栏两种导航样式,我们选择顶栏型,点击显示代码
在这里插入图片描述
这个顶栏其实有两个,上面的是没有底色的,下面的是有底色的。
在这里插入图片描述
这些代码基本涵盖了各种用法,我们可以选择自己需要的部分,并根据下面的文档对它进行改造。

我们在 components 文件夹里新建一个 common 文件夹,用来存储公共的组件,并在该文件夹新建一个组件 NavMenu.vue,经过我修改的代码如下:

<template>
    <el-menu
      :default-active="'/index'"
      router
      mode="horizontal"
      background-color="white"
      text-color="#222"
      active-text-color="red"
      style="min-width: 1300px">
      <el-menu-item v-for="(item,i) in navList" :key="i" :index="item.name">
        {{ item.navItem }}
      </el-menu-item>
      <a href="#nowhere" style="color: #222;float: right;padding: 20px;">更多功能</a>
      <i class="el-icon-menu" style="float:right;font-size: 45px;color: #222;padding-top: 8px"></i>
      <span style="position: absolute;padding-top: 20px;right: 43%;font-size: 20px;font-weight: bold">White Jotter - Your Mind Palace</span>
    </el-menu>
</template>

<script>
  export default {
    name: 'NavMenu',
    data () {
      return {
        navList: [
          {name: '/index', navItem: '首页'},
          {name: '/jotter', navItem: '笔记本'},
          {name: '/library', navItem: '图书馆'},
          {name: '/admin', navItem: '个人中心'}
        ]
      }
    }
  }
</script>

<style scoped>
  a{
    text-decoration: none;
  }

  span {
    pointer-events: none;
  }
</style>

这里需要解释两点。

第一,在 <el-menu> 标签中我们开启了 router 模式,在 Element 文档中的解释如下:

在这里插入图片描述
第二,我们通过 v-for 指令,把 navList 数组渲染为一组 <el-menu-item> 元素,也即导航栏的内容。当然我们也可以分开写,这种用法只是显得 six 一些(当需要动态更改列表内容时就很有用了)

另外为了美观我还加了点别的东西,都很基础,就不多说了。

接下来,我们需要把这个组件放在 Home.vue 中。

修改 Home.vue 的代码如下:

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

<script>
  import NavMenu from './common/NavMenu'
  export default {
    name: 'Home',
    components: {NavMenu}
  }
</script>

<style scoped>

</style>

这样,我们访问 http://localhost:8080/index ,就会在顶部出现导航栏。这时我们还没有别的页面可以访问,所以点击按钮就跳到了空白的页面。
在这里插入图片描述
嗯,首页也啥也没有。这个页面我不打算多说什么,大家可以把它作为一个纯粹的展示页面,练习一下 html、css 之类。我做的首页源码可以在 GitHub 上下载下来参考使用,大致是这样的。
在这里插入图片描述

二、图书管理页面

这是我们的核心页面,我们先把它设计出来,以后再去实现具体的功能。

我拍脑袋想了一下,页面大概需要以下内容:

  1. 图书展示区域
  2. 分类导航栏
  3. 搜索栏
  4. 页码

1.LibraryIndex.vue

components 中新建文件夹 library,新建组件 LibraryIndex.vue,作为图书页面的根组件,代码如下

<template>
  <el-container>
    <el-aside style="width: 200px;margin-top: 20px">
      <switch></switch>
      <!--<SideMenu></SideMenu>-->
    </el-aside>
    <el-main>
      <!--<books></books>-->
    </el-main>
  </el-container>
</template>

<script>

  export default {
    name: 'AppLibrary'
  }
</script>

<style scoped>

</style>

注释掉的部分是接下来需要编写的组件。这里我们使用了 Element 提供的 Container 布局容器,把整个页面分为了侧边栏和主要区域两个部分,详细了解请参考

https://element.eleme.cn/2.0/#/zh-CN/component/container

接下来我们配置这个页面的路由,修改 router/index.js 代码如下:

import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '../components/home/AppIndex'
import Login from '../components/Login'
import Home from '../components/Home'
import LibraryIndex from '../components/library/LibraryIndex'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/home',
      name: 'Home',
      component: Home,
      redirect: '/index',
      children: [
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        },
        {
          path: '/library',
          name: 'Library',
          component: LibraryIndex,
          meta: {
            requireAuth: true
          }
        }
      ]
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    }
  ]
})

P.S 关于 router 的配置已经写了许多次了,接下来为了节省篇幅,我就只贴出来主要修改的部分啦

访问 http://localhost:8080/library ,发现可以访问了,当然,页面还是空白的,但是出现了导航栏,可以测试一下在首页和图书馆页面之间切换。
在这里插入图片描述

2.SideMenu.vue

编写一个侧边栏组件。放在 /library 文件夹中,代码如下

<template>
  <el-menu
    class="categories"
    default-active="0"
    @select="handleSelect"
    active-text-color="red">
    <el-menu-item index="0">
      <i class="el-icon-menu"></i>
      <span slot="title">全部</span>
    </el-menu-item>
    <el-menu-item index="1">
      <i class="el-icon-menu"></i>
      <span slot="title">文学</span>
    </el-menu-item>
    <el-menu-item index="2">
      <i class="el-icon-menu"></i>
      <span slot="title">流行</span>
    </el-menu-item>
    <el-menu-item index="3">
      <i class="el-icon-menu"></i>
      <span slot="title">文化</span>
    </el-menu-item>
    <el-menu-item index="4">
      <i class="el-icon-menu"></i>
      <span slot="title">生活</span>
    </el-menu-item>
    <el-menu-item index="5">
      <i class="el-icon-menu"></i>
      <span slot="title">经管</span>
    </el-menu-item>
    <el-menu-item index="6">
      <i class="el-icon-menu"></i>
      <span slot="title">科技</span>
    </el-menu-item>
  </el-menu>
</template>

<script>
  export default {
    name: 'SideMenu'
  }
</script>

<style scoped>
  .categories {
    position: fixed;
    margin-left: 50%;
    left: -600px;
    top: 100px;
    width: 150px;
  }
</style>

LibraryIndex.vue 中使用这个组件

<template>
  <el-container>
    <el-aside style="width: 200px;margin-top: 20px">
      <switch></switch>
      <SideMenu></SideMenu>
    </el-aside>
    <el-main>
      <!--<books></books>-->
    </el-main>
  </el-container>
</template>

<script>
  import SideMenu from './SideMenu'
  export default {
    name: 'AppLibrary',
    components: {SideMenu}
  }
</script>

<style scoped>

</style>

访问 http://localhost:8080/library 查看效果
在这里插入图片描述

3.Books.vue

最后,我们用一个组件来显示图书。这个组件比较复杂,初始代码如下

<template>
  <div>
    <el-row style="height: 840px;">
      <!--<search-bar></search-bar>-->
      <el-tooltip effect="dark" placement="right"
                  v-for="item in books"
                  :key="item.id">
        <p slot="content" style="font-size: 14px;margin-bottom: 6px;">{{item.title}}</p>
        <p slot="content" style="font-size: 13px;margin-bottom: 6px">
          <span>{{item.author}}</span> /
          <span>{{item.date}}</span> /
          <span>{{item.press}}</span>
        </p>
        <p slot="content" style="width: 300px" class="abstract">{{item.abs}}</p>
        <el-card style="width: 135px;margin-bottom: 20px;height: 233px;float: left;margin-right: 15px" class="book"
                 bodyStyle="padding:10px" shadow="hover">
          <div class="cover">
            <img :src="item.cover" alt="封面">
          </div>
          <div class="info">
            <div class="title">
              <a href="">{{item.title}}</a>
            </div>
          </div>
          <div class="author">{{item.author}}</div>
        </el-card>
      </el-tooltip>
    </el-row>
    <el-row>
      <el-pagination
        :current-page="1"
        :page-size="10"
        :total="20">
      </el-pagination>
    </el-row>
  </div>
</template>

<script>
  export default {
    name: 'Books',
    data () {
      return {
        books: [
          {
            cover: 'https://i.loli.net/2019/04/10/5cada7e73d601.jpg',
            title: '三体',
            author: '刘慈欣',
            date: '2019-05-05',
            press: '重庆出版社',
            abs: '文化大革命如火如荼进行的同时。军方探寻外星文明的绝秘计划“红岸工程”取得了突破性进展。但在按下发射键的那一刻,历经劫难的叶文洁没有意识到,她彻底改变了人类的命运。地球文明向宇宙发出的第一声啼鸣,以太阳为中心,以光速向宇宙深处飞驰……'
          }
        ]
      }
    }
  }
</script>

<style scoped>
  .cover {
    width: 115px;
    height: 172px;
    margin-bottom: 7px;
    overflow: hidden;
    cursor: pointer;
  }

  img {
    width: 115px;
    height: 172px;
    /*margin: 0 auto;*/
  }

  .title {
    font-size: 14px;
    text-align: left;
  }

  .author {
    color: #333;
    width: 102px;
    font-size: 13px;
    margin-bottom: 6px;
    text-align: left;
  }

  .abstract {
    display: block;
    line-height: 17px;
  }

  a {
    text-decoration: none;
  }

  a:link, a:visited, a:focus {
    color: #3377aa;
  }
</style>

之后我们要实现的许多功能都与这个组件有关。目前用到的这部分,需要注意的有:

  1. v-for 指令,之后可以使用动态渲染,这里我们用《三体》的内容作为一个默认值,先查看效果。
  2. el-tooltip Element 提供的组件,用于展示鼠标悬停时的提示信息。参考 https://element.eleme.cn/2.0/#/zh-CN/component/tooltip
  3. slot 插槽,及把标签中的内容插到父组件指定的地方,这里我们插入了 el-tooltipcontent 中。上述文档中亦有描述。
  4. 封面图像标签中,我们使用了 :src="item.cover" 这种写法,: 其实是 v-bind: 的缩写,用于绑定把标签的属性与 data 中的值绑定起来。
  5. 搜索栏暂不理会
  6. 分页使用 el-pagination 组件,目前只是样式。

图书卡片的样式是模仿豆瓣读书做的。
在这里插入图片描述

最后把 Books 组件放在 LibraryIndex.vue 中,并稍微修改一下样式

<template>
  <el-container>
    <el-aside style="width: 200px;margin-top: 20px">
      <switch></switch>
      <SideMenu></SideMenu>
    </el-aside>
    <el-main>
      <books class="books-area"></books>
    </el-main>
  </el-container>
</template>

<script>
  import SideMenu from './SideMenu'
  import Books from './Books'
  export default {
    name: 'AppLibrary',
    components: {SideMenu, Books}
  }
</script>

<style scoped>
  .books-area {
    width: 990px;
    margin-left: auto;
    margin-right: auto;
  }
</style>

P.S 以后添加组件之类的代码我也尽量只放关键部分,大家要多尝试自己调试。

最后,访问 http://localhost:8080/library ,效果如下
在这里插入图片描述
功能完善之后是这个样子的
在这里插入图片描述


项目的源码在我的 GitHub 上,可以下载下来参考:

https://github.com/Antabot/White-Jotter

感谢大家的支持!如果有想不清楚的问题,请给我发个邮件,我一定及时回复!

查看系列文章目录:
https://learner.blog.csdn.net/article/details/88925013

上一篇: Vue + Spring Boot 项目实战(六):前端路由与登录拦截器

下一篇:Vue + Spring Boot 项目实战(八):数据库设计与增删改查

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐