【Vue3+GoFrame】后台管理项目实践 #1 搭建前端基础框架

前言

开发这个项目的目的是通过实践的方式,学习Vue3和Golang以及GoFrame框架。实践过程中也会通过扩展知识点,了解其中的原理,更加的巩固知识。 当然作为初学者,肯定会出现很多错误,或者不规范的地方,若有大佬发现,可以提出建议,让小弟我多多学习!感谢。

项目介绍

本项目为销售管理后台,主要功能为管理客户、分销员,以及进行审批。是对我以前开发的一个系统进行重构,之前系统使用Vue2作为前端框架,前端组件库使用Element UI,ThinkPHP作为后端框架。
旧系统由于使用了TP框架的模板功能,所以并不是严格意义上的前后端分离(页面是通过PHP来渲染的),Vue部分也没有使用构建工具(脚手架),所以每个页面都是单独的Vue应用。那在本次重构中,将严格进行前后端分离,使用构建工具进行开发和部署应用。
本项目使用组合式API写法。
本项目代码中,可能会忽略部分样式代码和导入代码,若有特殊情况,将单独说明。

开发环境

Node.js 16+
Vue3
Ant Design of Vue 3+(前端组件库)
Golang 1.19
GoFrame 2.2.1

创建应用

Vue3官方推荐使用Vite作为脚手架,那么我们就按照官方的建议,通过Vite来搭建前端框架。

新建一个vue应用:my-vue-app 为项目文件夹名称

#npm 6.x
npm create vite@latest my-vue-app --template vue
# npm 7+
npm create vite@latest my-vue-app -- --template vue

执行后进入项目文件夹,安装模块,然后运行即可。

在这里插入图片描述

应用目录

新建vue应用后,我们可以得到以下的目录:
在这里插入图片描述

root(根目录)
├─ node_modules  安装的插件都会放到这个文件夹中
├─ public  存放资源文件
├─ src  存放主要开发代码文件
│  ├─ assets  开发过程中使用到的资源文件
│  ├─ components  组件文件夹
│  ├─ App.vue  根组件文件
│  ├─ main.js  入口文件。在这里挂载vue应用,并导入App.vue组件
│  └─ style.css 公共样式文件
└─ index.html  入口文件

本次开发使用单应用模式,所以默认生成的一个入口文件就够用了。

使用Ant Design Vue组件库

安装

npm i --save ant-design-vue

按需加载
使用 unplugin-vue-components 插件来帮助我们完成按需加载组件。但在ant中,此插件不能加载非组件模块(如message),所以这种组件还是需要手动加载。

npm i unplugin-vue-components -D

# -D 表示只安装在开发模式中 
// vite.config.js
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';

export default {
  plugins: [
    /* ... */
    Components({
      resolvers: [AntDesignVueResolver()],
    }),
  ],
};

设计后台页面布局

可以在ant文档中的布局组件中找到喜欢的布局样式,这里选择的是侧边布局。
把整个页面分为左右两部分,左边是导航部分,右边再划分上下区域,上为预留的菜单部分以及用户头像昵称等信息。下区域为主要显示的页面内容。
在这里插入图片描述
把每个部分作为一个个组件进行开发,然后再导入根组件App.vue中。

App (根组件)
├─ Left  左侧导航组件
└─ Right  右侧内容组件
   ├─ Top  上方内容组件
   └─ Content 主要内容组件
   
# 后续根据实际情况可能还会细分出更多的组件

划分组件

既然已经设计好主要的布局方式,那么我们就开始新建对应的组件吧。

左侧导航组件

// Left.vue
<script setup>
defineProps(['collapsed'])
const selectedKeys = ref(['1'])
</script>
<template>
    <a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible>
        <div class="logo" />
        <a-menu v-model:selectedKeys="selectedKeys" theme="dark" mode="inline">
            <a-menu-item key="1">
                <user-outlined />
                <span><span>nav 1</span></span>
            </a-menu-item>
            <a-menu-item key="2">
                <video-camera-outlined />
                <span><span>nav 2</span></span>
            </a-menu-item>
        </a-menu>
    </a-layout-sider>
</template>

右侧内容组件

// Right.vue
<script setup>
defineProps(['collapsed']);
defineEmits(['menuCollapse']);
</script>
<template>
    <a-layout>
        <a-layout-header style="background: #fff; padding: 0">
            <menu-unfold-outlined v-if="collapsed" class="trigger" @click="$emit('menuCollapse')" />
            <menu-fold-outlined v-else class="trigger" @click="$emit('menuCollapse')" />
        </a-layout-header>
        <a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }">
            Content
        </a-layout-content>
        <a-layout-footer style="text-align: center">
            Ant Design ©2018 Created by Ant UED
        </a-layout-footer>
    </a-layout>
</template>

根组件

// App.vue
<script setup>
const collapsed = ref(false)
function menuCollapse(){
    collapsed.value = !collapsed.value;
}
</script>
<template>
    <a-layout :style="{minHeight: '100%'}">
        <Left :collapsed="collapsed" />
        <Right :collapsed="collapsed" @menu-collapse="menuCollapse"/>
    </a-layout>
</template>

在这里,我们实现了一个小小的功能,在右组件中,添加了一个按钮,用于折叠左侧导航。
由于左右两组件是同级关系,右组件的消息想要传达到左组件,则需要一个中间组件来进行传递,即它们的上级:App.vue。

因为在vue中,数据只能单向传递,子组件不能修改父组件传递的值。所以我们在根组件中定义了一个变量collapsed,并传递到两个子组件中,子组件通过声明props来接受父组件传递的变量。同时也定义了一个方法menuCollapse(),用于修改collapsed的值。该方法主要由右组件通过触发事件的方式$emit(‘menuCollapse’)进行调用。

当点击右组件的折叠按钮时,会触发父组件的menuCollapse()修改collapsed值,该值会自动更新传递到子组件中,从而实现左组件的导航菜单折叠功能。

优化
通过传递参数,监听事件的方式,我们也可以使用v-model来进行优化。

// App.vue
// 去掉 menuCollapse(),我们把这个方法放到 Right.vue 的点击事件中执行,所以Right组件也要去掉监听事件。
<Right v-model:collapsed="collapsed" />

// Right.vue
<script setup>
const props = defineProps(['collapsed']);
defineEmits(['update:collapsed']);
</script>
<template>
	...
    <menu-unfold-outlined v-if="collapsed" class="trigger" @click="$emit('update:collapsed', !props.collapsed)" />
    ...
</template>

App组件中,参数collapsed传递方式由:collapsed变为了v-model:collapsed(冒号后为自定义参数名称),此时在Right组件上会自动添加@update:collapsed事件,当组件触发(此刻是click)该事件时,将会修改参数collapsed的值。所以在Right组件中,我们需要声明一个触发事件update:collapsed,以便父组件监听。

v-model也可不使用自定义名称,此时vue会默认使用modelValue作为传递参数名,所以在子组件中需要声明对应的参数名(modelValue)以及update方法名称(update:modelValue)。

在子组件中,父组件传递的值可以直接在template中使用,但是在JS中,只能从defineProps中获取(获取到的值就是父组件参数.value),所以声明了一个变量props以获取defineProps返回值,才能在方法中使用。

在这里,我们直接在Right组件中点击事件调用$emit(),第一个参数为事件名称,第二个参数为默认值。若需要单独使用一个方法,则是这样写:

// 先声明事件变量
const emit = defineEmits(['update:collapsed']);

function a(){ emit('update:collapsed', !props.collapsed) }

因为在这里这个功能比较简单,只是变化collapsed为true或者false,若是比较复杂的功能,还是只能通过触发父组件函数的方式来修改参数值。

使用路由

做到这里,我们的后台页面也渐渐有模有样了,但是有个很重要的部分,就是主要的内容部分应该怎么显示呢?假设今后我们有客户列表、分销员列表,按之前的想法应该分为Customer、Agent组件,然后都导入到Right中,当点击Left中的导航时,切换相应的组件显示。要实现这个功能,我们需要使用路由功能了。

安装

npm install vue-router@4

配置
在src文件夹下新建一个专门存放路由的文件夹router,并新建index.js路由配置文件,路由对应的组件都在这里配置和导入。

import { createRouter, createWebHistory } from "vue-router"
import Index from '../components/index/Index.vue'
import Hellow from '../components/index/Hellow.vue'

const routes = [
    {
        path: '/',
        component: Index ,
    },
    {
        path: '/hellow',
        component: Hellow ,
    },
]

const router = createRouter({
    history: createWebHistory(),
    routes,
})

export default router

vue-router有两种路由模式,

  1. hash:该模式兼容性较好,但是生成的链接为xx.com/#/hellow,这种链接不够优雅,而且对SEO不友好。这里不采用这种模式。
  2. history:该模式基于浏览器的history功能,所以需要浏览器支持。生成的链接为常见的格式(xx.com/hellow),我们采用这种路由模式。

全局使用

// main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import Router from './router/index'

createApp(App).use(Router).mount('#app')

// Right.vue
<template>
    <a-layout>
        <a-layout-header style="background: #fff; padding: 0">
            <menu-unfold-outlined v-if="collapsed" class="trigger" @click="$emit('update:collapsed', !props.collapsed)" />
            <menu-fold-outlined v-else class="trigger" @click="$emit('update:collapsed', !props.collapsed)" />
        </a-layout-header>
        <a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }">
            <router-view></router-view>
        </a-layout-content>
        <a-layout-footer style="text-align: center">
            Ant Design ©2018 Created by Ant UED
        </a-layout-footer>
    </a-layout>
</template>

// Left.vue
<template>
    <a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible>
        <div class="logo" />
        <a-menu v-model:selectedKeys="selectedKeys" theme="dark" mode="inline">
            <a-menu-item key="1">
                <user-outlined />
                <span><router-link to="/">Go to Home</router-link></span>
            </a-menu-item>
            <a-menu-item key="2">
                <video-camera-outlined />
                <span><router-link to="/hellow">Hellow</router-link></span>
            </a-menu-item>
        </a-menu>
    </a-layout-sider>
</template>

在入口文件main.js中绑定路由到整个应用中,以便可全局使用。

在Left导航中使用标签router-link跳转路由,在Right内容位置使用标签router-view来渲染对应的组件模板。

成果

现在,我们已经完成了后台页面的雏形,接下来将完善左侧导航菜单。

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Vue3 + TypeScript + Vite + Element Plus + Router + Axios搭建前端项目框架的步骤: 1. 首先,确保你已经安装了Node.js和npm。你可以在命令行中运行以下命令来检查它们的版本: ```shell node -v npm -v ``` 2. 创建一个新的项目文件夹,并在该文件夹中打开命令行。 3. 在命令行中运行以下命令来初始化一个新的Vite项目: ```shell npm init vite ``` 在初始化过程中,你需要选择Vue作为模板,选择TypeScript作为语言,并填写项目名称。 4. 进入项目文件夹,并安装所需的依赖: ```shell cd your-project-name npm install ``` 5. 安装Vue Router、Vuex和Axios: ```shell npm install vue-router@next vuex@next axios ``` 6. 在项目文件夹中创建一个新的文件夹,用于存放页面组件和路由配置文件。 7. 在src文件夹中创建一个新的文件夹,用于存放页面组件。 8. 在src文件夹中创建一个新的文件夹,用于存放路由配置文件。 9. 在src/router文件夹中创建一个新的文件,命名为index.ts,并在其中编写路由配置: ```typescript import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; const routes = [ { path: '/', name: 'Home', component: Home, }, // 添加其他页面的路由配置 ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router; ``` 10. 在src/main.ts文件中导入并使用Vue Router: ```typescript import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; createApp(App).use(router).mount('#app'); ``` 11. 在src/views文件夹中创建一个新的文件,命名为Home.vue,并在其中编写一个简单的页面组件: ```vue <template> <div> <h1>Welcome to Home Page</h1> </div> </template> <script> export default { name: 'Home', }; </script> ``` 12.src/App.vue文件中添加一个路由出口,用于显示组件: ```vue <template> <div id="app"> <router-view></router-view> </div> </template> <script> export default { name: 'App', }; </script> ``` 13. 在src/main.ts文件中导入并使用Element Plus: ```typescript import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; import ElementPlus from 'element-plus'; import 'element-plus/lib/theme-chalk/index.css'; createApp(App).use(router).use(ElementPlus).mount('#app'); ``` 14. 运行以下命令来启动开发服务器: ```shell npm run dev ``` 15. 打开浏览器,并访问http://localhost:3000,你将看到一个简单的页面,其中包含"Welcome to Home Page"的文本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值