本文详细介绍了如何使用Vue.js构建一个简单的图书管理系统。从项目初始化和配置开始,创建了登录页面和首页,并通过
v-model
实现双向绑定,通过v-bind
绑定属性,通过Vue Router实现页面跳转和状态管理。文章还展示了如何进行组件化开发,如何使用localStorage
在不同页面间传递数据,最终提供了完整的代码和项目效果,帮助读者从零开始掌握Vue.js项目的基本构建流程及相关技术。
1、准备工作
在项目文件夹下运行终端命令 npm create vue@latest 安装项目所需依赖,除vue Router外全部选择“否”
随后按照指令进入到 manage-demo 文件夹 npm install 完成初始化
为了得到一个干净的框架
将assets和component文件夹,views文件夹下的两个初始页面删除
此外,清空App.vue,删除main.js中的第一行引入代码,并将router文件夹下的index.js删除至如图片所示,避免报错
2、管理系统的登入页面
首先来写一个purely的HTML+CSS代码,来实现我们的登入框。这是一个简单的登入界面入口,开袋即食,文件命名为login.vue,存在我们的views文件夹下
<template>
<div class="login">
<h3>图书管理系统</h3>
<div class="user">
<span>账号:</span>
<input type="text">
</div>
<div class="pwd">
<span>密码:</span>
<input type="text">
</div>
<div class="btn">
<button>登入</button>
</div>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped>
.login{
background-color: #e9e9e9;
box-shadow: 0 0 20px #e9e9e9;
width: 350px;
height: 220px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 20px;
box-sizing: border-box;
}
h3{
margin-bottom: 20px;
text-align: center;
}
.user, .pwd{
margin-bottom: 20px;
display: flex;
align-items: center;
}
span{
width: 50px;
}
input{
flex: 1;
font-size: 18px;
padding: 3px 10px;
}
button{
width: 80%;
margin: 0 auto;
display: block;
padding: 5px 0;
background-color: #0a948f;
color: #fff;
border:none;
border-radius: 100px;
cursor: pointer
}
</style>
展示效果如下(哈哈...经典登入界面)
随后,我们简化下登入操作,希望“如果账号,密码输入不为空,那么我就跳转到首页”。
可以想象,只需要把登入按钮,绑定点击事件,判段一下账号密码是否为空,非空即可使用vue-router完成跳转。此处使用state(user, pwd)来保存用户在账号和密码框的输入,当用户输入后,在v-model的双向绑定下,数据从页面到js中的state中保存。最后判段逻辑条件完成
以下是登入界面完整代码(除css部分):
<template>
<div class="login">
<h3>图书管理系统</h3>
<div class="user">
<span>账号:</span>
<input type="text" v-model="state.user">
</div>
<div class="pwd">
<span>密码:</span>
<input type="text" v-model="state.pwd">
</div>
<div class="btn">
<button @click="login">登入</button>
</div>
</div>
</template>
<script setup>
import { reactive } from 'vue';
import { useRouter } from 'vue-router';
const state = reactive({
user: '',
pwd: ''
})
const router = useRouter()
const login = () => {
if(state.user != '' && state.pwd != ''){
router.push('/home')
}
}
</script>
为了实现组件化布局,将用户首次进入到界面设置为登入界面,将router文件夹下的index.js中设置如下
并且在APP.vue中引用
3、管理系统的首页
首先在view文件夹下创建Home.vue文件,并为其配置路由(在index.js中添加)
此时有个小小的想法?如果我想实现用户在登入成功进入到首页,首页欢迎{{user}}。但是问题来了,不同页面之间如何传数据呢?我们可以使用localStorage来实现本地存储。在登入页面,绑定的login函数内,将登入信息保存下来
(Login.vue)
此时,我们在Home.vue下就可以用localStorage来访问user值了(Home.vue)
效果如下:
再然后,现在我想做一个菜单栏。那么,我们在src目录下创建一个index.js保存内容如下:
export const menu = [
{id: 1, title: '图书分类', path: '/category'},
{id: 2, title: '查询图书', path: '/search'},
{id: 3, title: '添加图书', path: '/add-book'},
{id: 4, title: '借阅管理', path: '/borrow'}
]
在Home.vue文件夹下引入。可以发现这里使用的是export将数组抛出,与在代码段末尾export default menu的区别仅仅在于。这样在App.vue的引入是加{}的,而export default menu的引入不加{},仅此而已!
随后在views文件夹下创建pages文件夹,用来装左侧菜单栏的标签指向,分别为Borrow.vue,Category.vue,Search.vue,内容如下(三个页面暂时性内容都设为文字类型的暂替页面)
当然,此时并没有完成同步, 我们需要再router中为其配置路由
最后全部渲染好的主页面HOME页面如下:
<template>
<div class="home">
<header class="header">
<div class="name">图书管理系统</div>
<div class="userInfor">
<span>欢迎 {{user}}</span>
</div>
</header>
<section class="main">
<div class="menu">
<ul>
<li class='list-item' v-for="item in menu">
<RouterLink v-bind:to="`/home${item.path}`">{{ item.title}} </RouterLink>
<!-- 标签属性一定要v-bind绑定一下,不然不会把他当做属性处理 -->
</li>
</ul>
</div>
<div class="content">
<RouterView></RouterView>
</div>
</section>
</div>
</template>
<script setup>
import { menu } from '../menuData'
const user = localStorage.getItem("user");
</script>
<style lang="css" scoped>
.home{
height: 100vh;
display: flex;
flex-direction: column;
}
.header{
height: 60px;
background-color: #96da6c;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 50px;
}
.name{
font-size: 26px;
font-weight: bolder;
}
.main{
flex: 1;
display: flex;
}
.menu{
flex: 0 0 200px;
background-color: aqua;
}
.content{
flex: 1;
}
.menu-list{
padding: 20px 0;
}
.list-item{
height: 40px;
line-height: 40px;
font-size: 18px;
}
.list-item a{
display: block;
width: 100%;
height: 100%;
text-align: center;
}
.list-item:hover{
background-color: rgba(0, 0, 0, 0.5);
}
</style>
4. 所有的完整代码
router下的index.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history:
createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
redirect: './login'
},
{
path: '/login',
component: () => import('../views/Login.vue')
},
{
path: '/home',
component: () => import('../views/Home.vue'),
children: [
{
path: '/home/category',
component: () => import('../views/pages/Category.vue')
},
{
path: '/home/Search',
component: () => import('../views/pages/Borrow.vue')
}
]
}
]
})
export default router
App.vue
<template>
<div>
<RouterView></RouterView>
</div>
</template>
<script setup>
import { RouterView } from 'vue-router';
</script>
<style lang="css">
*{
margin: 0;
padding: 0;
}
ul li{
list-style: none;
}
a{
color: #000;
text-decoration: none;
}
</style>
5、最终效果
登入界面
首页