VUE 从零开始搭建企业级后台管理

创建项目

js 复制代码
// 使用vite创建项目, 并指定模板为vue
npm create vite@latest vue-app -- --template vue
// 执行上面命令后,控制台会输出下面三句话
cd vue-app // 进行项目文件夹
npm install // 安装项目依赖 网络不好的可以尝试使用 yarn 或 cnpm
npm run dev // 运行项目

执行完以上命令后 你将会看到一下页面

下面们来看看项目的代码, 在编辑器里打开后会呈现如下的文件目录

其中我们最关心的红色部分

  • node_modules里存放的全是项目依赖 通过npm install安装的都会在里面,
  • public存放的是静态文件 如 index.html 图片等文件
  • assets里放静态资源 图片 图标 等
  • components 存放的是我们项目里的vue 组件
  • app.vue 项目跟组件 最先加载的组件
  • main.js 项目入口文件 主要用于启动插件
  • vite.config.js vite的配置 项目打包配置时有用

下面我们来看项目入口文件,和根组件

main.js

app.vue

使用路由

首先我们安装路由

js 复制代码
npm install vue-router@4 //网络不好可以使用 yarn add vue-router@4 或 cnpm 

使用路由

  • 在scr下创建views文件夹, 在views下创建两个vue文件, 就是路由跳转匹配的页面
  • 首先在src文件夹下创建router文件夹, 然后再router 文件夹下创建 index.js
  • 在index.js编写路由规则 在文件里我们写了两个路由 / 和 /about 并使用createWebHashHistory方式加载路由 这里我我们使用了 import.meta.glob('../views/**/*.vue')的方式去加载组件
js 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'

const routerFile =  import.meta.glob('../views/**/*.vue')
const routes = [
    {
        path: "/",
        component: () => routerFile['../views/home.vue']()
    },
     {
        path: "/about",
        component: () => routerFile['../views/about.vue']()
    }
]

// 导出router 在main里给vue使用
export const router = createRouter({
    history: createWebHashHistory(),
    routes
})

expoer funtion setupRouter(app){
    app.use(router)
    router.isReady()
}
  • 在main.js 里使用路由
js 复制代码
import { createApp } from 'vue' 
import { setupRouter } from './router/index.js' // 引入 router 导出
import './style.css'
import App from './App.vue'


const app = createApp(App)
setupRouter(app)
app.mount("#app")
  • 在app跟组件里来接受路由
js 复制代码
<template>
  <p>
    <router-link to="/">Home</router-link>
    /
    <router-link to="/about">About</router-link>
  </p>

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

<script setup>

</script>

以上就实现了最简单的路由匹配, 让我们来查一下效果吧

使用antd

安装antd

js 复制代码
npm install ant-design-vue@4.x --save
// 或者
yarn add ant-design-vue@4.x

如何使用,在main.js里引入 并use(antd), 这里是全局注册,要按需注册,需引入所需组件使用即可

js 复制代码
 import { createApp } from 'vue'; 
 import Antd from 'ant-design-vue'; 
 import App from './App'; 
 import 'ant-design-vue/dist/reset.css'; 
 
 const app = createApp(App); 
 app.use(Antd)
 app.mount('#app');

更多antd 用法请参考antdv官网 各种组件用法例示都有

antd layout布局

1 首先写出layout 组件, 在components下 新建layout文件夹, 创建 index.js 以及两个组件 登录layout 和 main layout 代码如下

index.js

js 复制代码
import  MainLayout  from './mainLayout.vue'
import  LoginLayout  from './loginLayout.vue'

export function setupLayout(app){
    app.component('MainLayout', MainLayout)
    app.component('LoginLayout', LoginLayout)
}

mainLayout.vue

js 复制代码
<template>
  <a-layout style="height: 100vh;">
      <a-layout-header :style="headerStyle">顶部区域</a-layout-header>
      <a-layout>
        <a-layout-sider :style="siderStyle">菜单区域</a-layout-sider>
        <a-layout-content :style="contentStyle">
           <router-view></router-view>
        </a-layout-content>
      </a-layout>
      <a-layout-footer :style="footerStyle">底部区域</a-layout-footer>
  </a-layout>
</template>

loginLayout.vue

js 复制代码
<template>
    <a-layout class="main-container">
        <router-view></router-view>
    </a-layout>
</template>

完成以上步骤后 在main.js 里引入并使用 layout 代码如下

js 复制代码
import { createApp } from 'vue'  // 引入vue启动函数
import { router } from './router/index.js'
import Antd from 'ant-design-vue';
import { setupLayout } from './components/layout/index.js'
import './style.css'
import 'ant-design-vue/dist/reset.css';
// 引入App组件
import App from './App.vue'


const app = createApp(App)
// 使用引入的layout
setupLayout(app)  
app.use(router)
app.use(Antd)
app.mount("#app")

下面还需要配置两处地方,才可以产生效果 app.vue 和 router下面的index.js

app.vue 修改后

js 复制代码
<template>
  <component :is="componentId">
    <router-view></router-view>
  </component>

</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router';

const route = useRoute()
const componentId = computed(() => {
    return route.meta.layout || 'div'; // 默认情况下使用一个 div 包裹
});
</script>

router/ index.js

js 复制代码
import { createRouter, createWebHashHistory } from 'vue-router'

const routeFiles = import.meta.glob('../views/**/*.vue')

const routes = [
    {
        path: "/",
        name: 'index',
        meta:{
            layout: 'MainLayout'
         },
        component:() => routeFiles['../views/home.vue']()
       
    },
    {
        path: "/login",
        name: 'login',
        meta:{
            layout: 'LoginLayout'
         },
        component:() => routeFiles['../views/login/index.vue']()
       
    },

    {
        path: '/about',
        name: 'about',
        meta:{
            layout: 'MainLayout'
         },
        component:() => routeFiles['../views/about.vue']()
      
    }
]

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

效果: 通过加载不同的路由就实现了 加载不同的layout

http://localhost:5173/#/

http://localhost:5173/#/login

使用pinia

安装pinia

js 复制代码
npm install pinia
或者
yarn add pinia

在src文件夹下创建 store, 在store下创建index.js 和 modules文件夹,在modules下创建 index.js 和user文件夹然后在 user下在创建user.js

store下的index.js 创建pinia 导入modules下的store

js 复制代码
import { createPinia } from "pinia";

const store = createPinia()

export function setupStore(app) {
  app.use(store)
}

export * from './modules'

modules下的index.js 导出store 如果后续有多少store 就导出多少

js 复制代码
export * from './user/user'

user.js这里创建了一个存储token的store

js 复制代码
import { defineStore } from "pinia"

const LOCAL_NAME = 'token'

function getToken(){
    return localStorage.getItem(LOCAL_NAME)
}

function setToken(token){
    localStorage.setItem(LOCAL_NAME, token)
}
export const userStore = defineStore("user", {
    state: () => getToken(),
    getters: {
        getToken: (state) => state.token
    },
    actions: {
        setToken(token){
            this.token = token
            setToken(token)
        }
    }
})

在main.js里注册store

js 复制代码
import { setupStore } from './store/index.js'
const app = createApp(App)
setupStore(app);
app.mount("#app")

使用

js 复制代码
<template>
    <div>
        我是home页面
        <a-button type="primary" @click="setToken">存储token</a-button>
        <a-button type="primary" @click="getToken">获取token</a-button>
        {{ T }}
    </div>
</template>

<script setup>
import { ref } from 'vue'
import { useUserStore } from '../store/index.js'

const T = ref("")
const userStore = useUserStore()

const setToken = () => {
    userStore.setToken("122121")
}

const getToken = () =>{
    T.value = userStore.getToken
}
</script>

登录页面

html

js 复制代码
<template>
    <div class="login">
         <div class="login-header">
            <span>vue后台管理系统</span>
         </div>
         <div class="login-conent">
            <div class="login-conent-form">
                <a-form
                    :model="formState"
                    name="basic"
                    :label-col="{ span: 4 }"
                    :wrapper-col="{ span: 20 }"
                    autocomplete="off"
                    @finish="onFinish"
                >
                    <a-form-item
                    label="用户名"
                    name="username"
                    :rules="[{ required: true, message: 'Please input your username!' }]"
                    >
                    <a-input v-model:value="formState.username" />
                    </a-form-item>

                    <a-form-item
                    label="密码"
                    name="password"
                    :rules="[{ required: true, message: 'Please input your password!' }]"
                    >
                    <a-input-password v-model:value="formState.password" />
                    </a-form-item>

                 
                    <a-form-item>
                        <a-button type="primary" html-type="submit">登录</a-button>
                    </a-form-item>
                </a-form>
            </div>
         </div>

         <div class="login-footer">

</div>
    </div>
</template>

vue

js 复制代码
import { reactive, nextTick} from 'vue';
import { router } from '../../router/index'
import { useUserStore } from '../../store/index'
interface FormState {
  username: string;
  password: string;
  remember: boolean;
}
const formState = reactive<FormState>({
  username: 'admin',
  password: 'admin',
  remember: true,
});

const userStore = useUserStore()

const onFinish = async (values: any) => {
    // 调用登录接口 
    // 登录成功后 处理用户token 用户信息 后并路由跳转 
    await userStore.setToken("token")
    nextTick(() =>{
        router.push("/")
    })
   
};

beforeEach 判断用户是否登录 如果登录 存在用户token 直接进入页面 如果未登录 进入登录页面 在router文件夹下新建 guard.js 代码如下

js 复制代码
import { message } from 'ant-design-vue'
import { useUserStore } from '../store/index'
import { store } from '../store/index'

const passPath = ["/login"]
const userStore = useUserStore(store)


export function setupPageGuard(router){
    router.beforeEach( async (to, form, next) =>{
        if(passPath.includes(to.path)){
             next()
        }else{
           if(!userStore.getToken){
             message.success("请先登录")
             next('/login')
           }else{
            next()
           }
        }
    }) 
}

使用guard.js

js 复制代码
import { setupPageGuard } from './guard'
setupPageGuard(router)

这样就完成登录了

相关推荐
艾小码13 分钟前
为什么你的JavaScript代码总是出bug?这5个隐藏陷阱太坑了!
前端·javascript
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.4 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl6 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫8 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友8 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design