还不会用VUE?快来看看这个vue小Demo!

128 阅读4分钟

本文详细介绍了如何使用Vue.js构建一个简单的图书管理系统。从项目初始化和配置开始,创建了登录页面和首页,并通过v-model实现双向绑定,通过v-bind绑定属性,通过Vue Router实现页面跳转和状态管理。文章还展示了如何进行组件化开发,如何使用localStorage在不同页面间传递数据,最终提供了完整的代码和项目效果,帮助读者从零开始掌握Vue.js项目的基本构建流程及相关技术。

1、准备工作

在项目文件夹下运行终端命令 npm create vue@latest 安装项目所需依赖,除vue Router外全部选择“

image.png

随后按照指令进入到 manage-demo 文件夹 npm install 完成初始化

image.png

为了得到一个干净的框架 将assets和component文件夹,views文件夹下的两个初始页面删除
此外,清空App.vue,删除main.js中的第一行引入代码,并将router文件夹下的index.js删除至如图片所示,避免报错

image.png image.png image.png

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>

展示效果如下(哈哈...经典登入界面)

image.png

随后,我们简化下登入操作,希望“如果账号,密码输入不为空,那么我就跳转到首页”。
可以想象,只需要把登入按钮,绑定点击事件,判段一下账号密码是否为空,非空即可使用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中设置如下

image.png
并且在APP.vue中引用

image.png

3、管理系统的首页

首先在view文件夹下创建Home.vue文件,并为其配置路由(在index.js中添加) image.png

此时有个小小的想法?如果我想实现用户在登入成功进入到首页,首页欢迎{{user}}。但是问题来了,不同页面之间如何传数据呢?我们可以使用localStorage来实现本地存储。在登入页面,绑定的login函数内,将登入信息保存下来 (Login.vue) image.png 此时,我们在Home.vue下就可以用localStorage来访问user值了(Home.vue)

image.png
效果如下: image.png
再然后,现在我想做一个菜单栏。那么,我们在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的引入不加{},仅此而已!

image.png 随后在views文件夹下创建pages文件夹,用来装左侧菜单栏的标签指向,分别为Borrow.vue,Category.vue,Search.vue,内容如下(三个页面暂时性内容都设为文字类型的暂替页面)

image.png

image.png 当然,此时并没有完成同步, 我们需要再router中为其配置路由

image.png 最后全部渲染好的主页面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、最终效果

登入界面 image.png 首页 image.png