之前讲过使用 Element 辅助前端页面的开发,但是只用到了比较少的内容,这一篇我们来做一下系统的核心页面——图书管理页面的前端部分,旨在熟悉 Vue 的更多特性。
我们的项目虽然本质上是单页面应用,但表面上有多个功能页面,比如首页、图书馆、笔记本等,后期根据情况还可以把一些功能集中起来做一个后台管理页面。为了方便用户在这三个页面之间切换,我们需要添加一个导航栏。
这个导航栏的要求很简单:
为了实现第一个要求,我们需要把导航栏放在其它页面的父页面中(对 Vue 来说就是父组件),之前我们讲过,App.vue
是所有组件的父组件,但把导航栏放进去不合适,因为我们的登录页面中不应该显示导航栏。
为了解决这个问题,我们在 src/components
目录下直接新建一个组件,命名为 Home.vue
,原始代码如下:
<template>
<div>
<router-view/>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
这里和 App.vue
一样,写入了一个
,也就是子页面(组件)显示的地方。
接下来,来建立路由的父子关系。注意我们在一个组件中通过导入引用了其它组件,也可以称之为父子组件,但想要通过 控制子组件的显示,则需要进行路由的相关配置。
打开 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 中增添对应的内容。
打开 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>
这里需要解释两点。
第一,在
标签中我们开启了 router
模式,在 Element 文档中的解释如下:
第二,我们通过 v-for
指令,把 navList 数组渲染为一组
元素,也即导航栏的内容。当然我们也可以分开写,这种用法只是显得 six 一些(当需要动态更改列表内容时就很有用了)
另外为了美观我还加了点别的东西,都很基础,就不多说了。
接下来,我们需要把这个组件放在 Home.vue
中。
修改 Home.vue
的代码如下:
<template>
<div>
<router-view/>
</div>
</template>
<script>
import NavMenu from './common/NavMenu'
export default {
name: 'Home',
components: {NavMenu}
}
</script>
<style scoped>
</style>
启动前后端项目,测试一下:
npm run dev
这样,我们访问 http://localhost:8080/index ,就会在顶部出现导航栏。这时我们还没有别的页面可以访问,所以点击按钮就跳到了空白的页面。
嗯,首页也啥也没有。这个页面我不打算多说什么,大家可以把它作为一个纯粹的展示页面,练习一下 html、css 之类。我做的首页源码可以在 GitHub 上下载下来参考使用,大致是这样的。
这是我们的核心页面,我们先把它设计出来,以后再去实现具体的功能。
我拍脑袋想了一下,页面大概需要以下内容:
在 src/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,
// 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 ,发现可以访问了,当然,页面还是空白的,但是出现了导航栏,可以测试一下在首页和图书馆页面之间切换。
编写一个侧边栏组件。放在 src/components/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 查看效果
最后,我们用一个组件来显示图书。这个组件比较复杂,初始代码如下
<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>
之后我们要实现的许多功能都与这个组件有关。目前用到的这部分,需要注意的有:
v-for
指令,之后可以使用动态渲染,这里我们用《三体》的内容作为一个默认值,先查看效果。el-tooltip Element
提供的组件,用于展示鼠标悬停时的提示信息。参考 https://element.eleme.cn/2.0/#/zh-CN/component/tooltipslot
插槽,及把标签中的内容插到父组件指定的地方,这里我们插入了 el-tooltip
的 content 中。上述文档中亦有描述。:src="item.cover"
这种写法,: 其实是 v-bind:
的缩写,用于绑定把标签的属性与 data 中的值绑定起来。el-pagination
组件,目前只是样式。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
感谢大家的支持!如果有想不清楚的问题,请给我发个邮件,我一定及时回复!