Vue3、Node全栈项目笔记1

134 阅读2分钟

Vue3、Node全栈项目

Vue3

路由

-login.vue -mainbox.vue - home.vue - center.vue - user - adduser.vue - listuser.vue - news - addnews.vue - listnews.vue -product - addproduct.vue - listproduct.vue

import routesConfig from './config.js'
import store from '@/store/index.js'
const routes = [
  {
    path: '/login',
    name: 'login',
    component: Login
  },
  {
    path: '/mainbox',
    name: 'mainbox',
    component: MainBox
  }
]

// 导航守卫
router.beforeEach((to, from, next) => {
  if (to.name === "login") {
    next()
  } else {
    if (!localStorage.getItem("token")) {
      next({
        path: "/login"
      })
    } else {
      // 判断是否是第一次
      if (!store.state.isGetterRouter) {
        ConfigRouter()
        next({
          path: to.fullPath
        })
      }else{
        next()
      }

    }
  }
})
// 设置子路由
const ConfigRouter = function () {
  routesConfig.forEach(item => {
    router.addRoute('mainbox', item)
  })
  store.commit('changeGetterRouter',true)
} 
-- config.js
import Home from '@/views/home/HomeViews.vue'
import Center from '@/views/center/CenterViews.vue'
import Adduser from '@/views/user/AdduserViews.vue'
import Listuser from '@/views/user/ListuserViews.vue'
import Listnews from '@/views/news/ListnewsViews'
import Addnews from '@/views/news/AddnewsViews' 
import Addproduct from '@/views/product/AddproductViews.vue'
import Listproduct from '@/views/product/ListproductViews.vue'
import NotFound from '@/views/notfound/NotFoundViews.vue'
const routes = [
    {
        path:'/index',
        component:Home 
    },
    {
        path:'/center',
        component: Center
    },
    {
        path:'/user/adduser',
        component: Adduser
    },
    {
        path:'/user/listuser',
        component: Listuser
    },

    {
        path:'/news/addnews',
        component: Addnews
    },
    {
        path:'/news/listnews',
        component: Listnews
    },

    {
        path:'/product/addproduct',
        component: Addproduct
    },
    {
        path:'/product/listproduct',
        component: Listproduct
    },
    {
        path:'/',
        redirect:'/index'
    },
    {
        path:'/:pathMatch(.*)*',
        component:NotFound
    }
]

export default routes
import { createStore } from 'vuex'  
export default createStore({
  state: {
    isGetterRouter:false, 
  },
  getters: {
  },
  mutations: {
    changeGetterRouter(state,value){
      state.isGetterRouter = value
    }, 
  },
  actions: {
  },
  modules: { 
  }, 
})

页面设计

Login.vue

使用Element-Plus 表单组件
  • el-form属性
  • ref="loginFormRef" 校验方法
  • :model="loginForm" 绑定数据
  • :rules="rules" 校验
<template>
  <div class="loginbox">
    <h1> <span>AAA</span> 管理系统</h1>
    <el-form
      ref="loginFormRef"
      :model="loginForm"
      :rules="rules"
      status-icon  
       label-width="120px"
      class="demo-ruleForm"
    >
      <el-form-item label="用户账号" prop="username">
        <el-input v-model="loginForm.username" type="text" autocomplete="off" />
      </el-form-item>
      <el-form-item label="用户密码" prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          autocomplete="off"
        />
      </el-form-item> 
      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)"
          >登入</el-button
        > 
      </el-form-item>
    </el-form>
  </div>
</template>
<script setup>
import {ref,reactive} from "vue"
import {useRouter} from 'vue-router'
const loginFormRef = ref()
const loginForm = reactive({
    username:'',
    password:''
})
const router = useRouter()
const submitForm = ()=>{
    loginFormRef.value.validate((valid)=>{
        console.log(valid);
        if(valid){
            localStorage.setItem('token','lijiacheng')
            router.push("/index")
        }
    })
    console.log(123);
}
const rules = reactive({ 
    username:[
        {
            required:true,message:'请输入用户名',triggere:'blur'
        }
    ],
    password:[
        {
            required:true,message:'请输入密码',triggere:'blur'
        }
    ],
})
</script>
<style lang="scss" scoped>
.loginbox{
    width: 600px;
    height: 400px;
    margin: 300px auto;
    padding: 0 30px;
    border:1px solid #dcdfe6;
    h1{
        text-align: center;
        padding: 50px 0;
        span{
            color:blue
        }
    }
} 
</style>

使用Element-Plus Layout布局

mainbox
- Aside.vue  =>components //侧边栏  
    -Header =>components //right头部
    -router-view  =>views//路由出口
<el-container>
       <Aside/> <!--  侧边栏-->
      <el-container direction="vertical">
        <Header/><!-- right头部 -->
        <el-main> <router-view/></el-main> <!-- 路由出口 -->
      </el-container>
    </el-container>
Aside.vue
  • 重点用到了Menu菜单
  • 折叠宽度,宽度切换
  • <el-menu * :collapse="$store.state.isCollapse" 折叠状态默认false不折叠(数据持久化vuex用到了vuex-persistedstate) * :default-active="route.fullPath" 状态保持import {useRoute} from 'vue-router' const route = useRoute() :collapse-transition="false" 折叠动画默认true :router="true" 路由跳转是否跟着index值同步
<template>
  <el-aside :width="$store.state.isCollapse?'64px':'200px'">
    <el-menu
        :collapse="$store.state.isCollapse"
        :collapse-transition="false"
        :router="true"
        :default-active="route.fullPath"
    >
      <el-menu-item index="/index">
        <el-icon><HomeFilled /></el-icon>
        <span>首页</span>
      </el-menu-item>
      <el-menu-item index="/center">
        <el-icon><Avatar /></el-icon>
        <span>个人中心</span>
      </el-menu-item>
      <el-sub-menu index="user">
        <template #title>
         <el-icon><UserFilled /></el-icon>
          <span>用户管理</span>
        </template>
        <el-menu-item index="/user/adduser">添加用户</el-menu-item>
        <el-menu-item index="/user/listuser">用户列表</el-menu-item>
      </el-sub-menu>
      <el-sub-menu index="news">
        <template #title>
         <el-icon><MessageBox /></el-icon>
          <span>新闻管理</span>
        </template>
        <el-menu-item index="/news/addnews">创建新闻</el-menu-item>
        <el-menu-item index="/news/listnews">新闻列表</el-menu-item>
      </el-sub-menu>
      <el-sub-menu index="product">
        <template #title>
          <el-icon><Reading /></el-icon>
          <span>产品管理</span>
        </template>
        <el-menu-item index="/product/addproduct">创建产品</el-menu-item>
        <el-menu-item index="/product/listproduct">产品列表</el-menu-item>
      </el-sub-menu>
    </el-menu>
  </el-aside>
</template>
<script setup> 
import {
    HomeFilled,
    Avatar,
    UserFilled,
    MessageBox,
    Reading,
    Pointer} from '@element-plus/icons-vue'
import {useRoute} from 'vue-router'
const route = useRoute()
console.log(route);
</script>
<style lang="scss" scoped>
    .el-aside{
        height: 100vh;
    }
        .el-aside{
            height: 100vh;
        }
</style>
  • el-menu属性
    • :collapse="$store.state.isCollapse" 折叠状态默认false不折叠、数据持久化 刷新不会改变
import { createStore } from 'vuex' 
import createPersistedState from 'vuex-persistedstate'  //引入数据持久化
export default createStore({
  state: {
    isGetterRouter:false,
    isCollapse:false
  },
  getters: {
  },
  mutations: {
    changeGetterRouter(state,value){
      state.isGetterRouter = value
    },
    setCollapse(state){
      state.isCollapse = !state.isCollapse
    }
  },
  actions: {
  },
  modules: { 
  },
  plugins: [createPersistedState({
    paths:['isCollapse']   //只让isCollapse数据持久化  
  })] 
})
  • el-menu属性
    • :default-active="route.fullPath" 状态保持import {useRoute} from 'vue-router' const route = useRoute()
import {useRoute} from 'vue-router'
const route = useRoute()
console.log(route);