Front-end project construction and project configuration

Front-end project construction - vite+vue3.0+ant

vite is faster than webpack

vite build project

https://cn.vitejs.dev/
insert image description here
Steps:
1. Open cmd
2. Find the folder where the project should be built
, such as building it directly on the desktop

cd desktop

insert image description here
3. Create a project
Use the create project command, then fill in the project name according to the prompts, and the technology to be used, vue and ts, then you will see the project on the desktop

npm create vite@latest

insert image description here
4. Then find the newly created project, download dependencies, and start the project

npm install  //下载依赖
npm run dev  //启动项目

insert image description here
Running effect:
insert image description here
After that, we can use the packaging command, and we can see that a dist package will be generated. At this point the project is built.

npm run build 

insert image description here
You can delete files like components and useless things in App.vue
insert image description here
insert image description here

Configuration file -vite.config.js

insert image description here

import {
    
     defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import {
    
     resolve } from "path";

// https://vitejs.dev/config/
export default defineConfig({
    
    
  base: './', 
  plugins: [vue()],
  resolve: {
    
    
    alias: {
    
    
      '@': resolve(__dirname, 'src'),
      "@c": resolve(__dirname, "src/components"),
      "@view": resolve(__dirname, "src/view"),
      "@assets": resolve(__dirname, "src/assets"),
    },
    extensions: ['.js', '.jsx', '.json'], // 导入时想要忽略的扩展名列表
    preserveSymlinks: false, // 启用此选项会使 Vite 通过原始文件路径确定文件身份
  },
  server: {
    
    
    // 配置反向代理
    host: '0.0.0.0',  // 启动后浏览器窗口输入地址就可以进行访问
    port: 8001, // 端口号
    open: true, //是否自动打开浏览器
    cors: true, //为开发服务器配置 CORS , 默认启用并允许任何源
    https: false, //是否支持http2 如果配置成true 会打开https://localhost:3001/xxx;
    strictPort: true, //是否是严格的端口号,如果true,端口号被占用的情况下,vite会退出
    hmr: true, // 开启热更新
    // proxy: {
    
    
    //   '/api': {
    
    
    //     // 配置接口调用目标地址
    //     target: 'https://www.xxxx.com/xxxx',
    //     // 当进行代理时,Host 的源默认会保留(即Host是浏览器发过来的host),如果将changeOrigin设置为true,则host会变成target的值。
    //     changeOrigin: true,
    //     // 前缀 /api 是否被替换为特定目标,不过大多数后端给到的接口都是以/api打头,这个没有完全固定的答案,根据自己的业务需求进行调整
    //     rewrite: path => path.replace(/^\/api/, ''),
    //   }
    // }
  },
  build: {
    
    
    minify: "terser", // 必须开启:使用terserOptions才有效果
    outDir: 'iot',
    assetsDir: 'assets', // 指定生成静态文件目录
    brotliSize: true, // 启用 brotli 压缩大小报告
    chunkSizeWarningLimit: 2048, // chunk 大小警告的限制
    terserOptions: {
    
    
      compress: {
    
    
        //生产环境时移除console
        drop_console: true,
        drop_debugger: true,
      },
    },
  },
  preview: {
    
    
    port: 4001, // 指定开发服务器端口
    strictPort: true, // 若端口已被占用则会直接退出
    https: false, // 启用 TLS + HTTP/2
    open: true, // 启动时自动在浏览器中打开应用程序
    // proxy: { // 配置自定义代理规则
    //   '/api': {
    
    
    //     target: 'http://jsonplaceholder.typicode.com',
    //     changeOrigin: true,
    //     rewrite: (path) => path.replace(/^\/api/, '')
    //   }
    // },
    cors: true, // 配置 CORS
  }
})

Add "serve": "vite" to the scripts of the package.json file, and it can be started with npm run serve when starting.
insert image description here

configure routing

vue-router
https://router.vuejs.org/

1. Install

npm install vue-router@4

insert image description here
insert image description here
2. Create a new router folder under the src folder. There is an index.js file under the folder for importing the methods required by the router and page path configuration, as well as parameter configuration and routing guards to determine whether there is a token or not to log in. If you are not logged in, jump to the login page. There is also a routes.js file specially used to configure the page path.
insert image description here

// 导入router所需的方法
import {
    
     createRouter, createWebHashHistory } from 'vue-router'
// 导入路由页面的配置
import routes from './routes'
// 路由参数配置
const router = createRouter({
    
    
    history: createWebHashHistory(),
    routes,
})

router.beforeEach((to, from, next) => {
    
    
    //一般路由守卫中会做一些鉴权和权限控制的事情
    console.log(to)
    if (to.meta && to.meta.title) {
    
    
        document.title = to.meta.title
    }
    if(to.meta.isLogin){
    
    
        let token = sessionStorage.getItem("token");
        token ? next() : next('/login');
    } else {
    
    
        next();
    }
})
export default router;

insert image description here

const routes = [
    {
    
    
        path: '/',
        // name: '主页面',
        meta: {
    
    
            title: "主页面",
            isLogin: true
        },
        redirect: "/home",
        component: () => import("../views/Main.vue"), 
        children: [
            /**
             * 首页
             * */
            {
    
    
                path: "/home",
                meta: {
    
    
                    title: "首页",
                    icon: 'icon-zongjie',
                    isLogin: true
                },
                name: 'home',
                component: () => import("../views/Home/Home.vue"),
            },
            {
    
    
                path: "/work",
                meta: {
    
    
                    title: "工作台",
                    icon: 'icon-zuchang',
                    isLogin: true
                },
                name: 'work',
                children: [
                    {
    
    
                        path: "/work/work1",
                        meta: {
    
    
                            title: "工作台1",
                            icon: 'icon-zuchang',
                            isLogin: true
                        },
                        name: 'work1',
                        component: () => import("../views/Work/Work.vue"),
                    }
                ]
            }
        ]
    },
    //登录页
    {
    
    
        path: "/login",
        meta: {
    
    
            title: "登录",
            // icon: 'icon-zongjie',
            isLogin: false
        },
        name: 'login',
        component: () => import("../views/Login/Login.vue"),
    },
    /* url错误重定向到home  */
    {
    
    
        path: "/:catchAll(.*)",
        redirect: "/",
        name: "notFound"
    }
]
export default routes

3. In the App.vue public page, go directly to the routing page

<template>
  <router-view></router-view>
</template>
<script setup>

</script>

<style scoped>
</style>

insert image description here
4. Build a routing page
and introduce less into the project

npm install less less-loader --save

insert image description here

Create a views folder under the src folder to write specific routing pages.
insert image description here
5. Introduce the ant-design component library
https://www.antdv.com/components/overview-cn/

npm install ant-design-vue --save

insert image description here
5. Configure the entry file, main.js under src, use these plug-ins and files.
insert image description here

import {
    
     createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router/index'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';

const appst = createApp(App);
appst.use(router).use(Antd).mount('#app');

6. Write the menu and switch between routing pages
Write in Main.vue under the views folder under src
Select the layout:
insert image description here
insert image description here

<template>
    <a-layout has-sider class="app-layout">
      <a-layout-sider
        @collapse="collapse"
        v-model:collapsed="collapsed"
        collapsible  
        :style="{ overflow: 'auto', height: '100%' }"
        class="left-layout-slider"
      >
        <div class="logo"></div>
        <a-menu v-model:selectedKeys="selectedKeys" @select="select" theme="dark" mode="inline" class="menu">
            <template v-for="item in routes[0].children">
                <a-sub-menu v-if="item?.children?.length > 0" >
                    <template #icon>
                        <span :class="`iconfont ${item.meta.icon}`"></span>
                    </template>
                    <template #title>
                        {
    
    {
    
     item.meta.title }}
                    </template>
                    <template v-for="i in item?.children" :key="i.path">
                        <a-menu-item>
                            <span :class="`iconfont ${i.meta.icon}`"></span>
                            <span class="nav-text">{
    
    {
    
     i.meta.title }}</span>
                        </a-menu-item>
                    </template>
                </a-sub-menu>
                <a-menu-item v-else :key="item.path">
                    <span :class="`iconfont ${item.meta.icon}`"></span>
                    <span class="nav-text">{
    
    {
    
     item.meta.title }}</span>
                </a-menu-item>
            </template>
        </a-menu>
      </a-layout-sider>
      <a-layout :style="{height: '100%',width: collapsed ? 'calc(100% - 80px)' : 'calc(100% - 200px)',background:'#04070b' }">
        <a-layout-header :style="{ background: '#16252e', padding: 0 }" class="app-layout-header">
            <!-- <a-popconfirm placement="bottom">
                <div class="app-layout-nameInfo">
                    <div>
                        <a-avatar :size="large">
                            <template #icon><UserOutlined /></template>
                        </a-avatar>
                    </div>
                    <div style="margin-left: 10px;">admin</div>
                </div>
            </a-popconfirm> -->
            <!-- <a-popover>
                <template #content>
                    <span class="iconfont icon-yanqi" style="color:#40a9ff"></span>
                    <a-button type="link" @click="banckClick">退出登录</a-button>
                </template>
                <div class="app-layout-nameInfo">
                    <div>
                        <a-avatar :size="large">
                            <template #icon><UserOutlined /></template>
                        </a-avatar>
                    </div>
                    <div style="margin-left: 10px;color: #ffffff;">admin</div>
                </div>
            </a-popover> -->
            <a-dropdown>
                <div class="app-layout-nameInfo">
                    <div>
                        <a-avatar size="large">
                            <template #icon><UserOutlined /></template>
                        </a-avatar>
                    </div>
                    <div style="margin-left: 10px;color: #ffffff;">admin</div>
                </div>
                <template #overlay>
                    <a-menu>
                        <a-menu-item>
                            <span class="iconfont icon-yanqi" style="color:#40a9ff"></span>
                            <a-button type="link" @click="banckClick">退出登录</a-button>
                        </a-menu-item>
                    </a-menu>
                </template>
            </a-dropdown>
            
        </a-layout-header>
        <a-layout-content :style="{ margin: '24px 16px 0', overflow: 'initial' }">
          <div :style="{  background: '#16252e', textAlign: 'center',height: '100%' }">
                <router-view></router-view>
          </div>
        </a-layout-content>
        <a-layout-footer :style="{ textAlign: 'center',background: '#04070b',color:'#fff' }">
            v1.1.20230524172613
        </a-layout-footer>
      </a-layout>
    </a-layout>
</template>
<script setup>
import {
    
     defineComponent, ref, watch } from 'vue';
import routes from "@/router/routes";
import {
    
     useRouter } from "vue-router";
import {
    
     UserOutlined } from '@ant-design/icons-vue';
const router = useRouter()
const selectedKeys = ref(['4']);
const collapsed = ref(false);
const select = (e) => {
    
    
    console.log(e)
    router.push(e.key);
}
const banckClick = (e) => {
    
    
    console.log("1222222222222")
    router.replace("/login");
    sessionStorage.removeItem("token")
}
const doResize = () => {
    
    
    setTimeout(() => {
    
    
        //手动触发窗口resize事件
        if (document.createEvent) {
    
    
            const event = document.createEvent("HTMLEvents");
            event.initEvent("resize", true, true);
            window.dispatchEvent(event);
        }
    }, 300);
};
const collapse = () => {
    
    
    doResize();
}
watch(() =>router.currentRoute.value.path,(newValue,oldValue)=> {
    
    
    selectedKeys.value = [newValue];
},{
    
     immediate: true })
</script>
<style lang="less" scoped>

.left-layout-slider{
    
    
    ::-webkit-scrollbar {
    
    
      display: none !important;
    }
    .menu{
    
    
        height: calc(100% - 80px);
        overflow-x: hidden;
        overflow-y: scroll;
    }
}
.app-layout{
    
    
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.logo {
    
    
  height: 32px;
  background: rgba(255, 255, 255, 0.2);
  margin: 16px;
}
.site-layout .site-layout-background {
    
    
  background: #fff;
}

[data-theme='dark'] .site-layout .site-layout-background {
    
    
  background: #141414;
}
</style>
<style lang="less">
.ant-dropdown-menu-item, .ant-dropdown-menu-submenu-title{
    
    
    padding: 0 6px!important;
}
.nav-text{
    
    
    margin-left: 10px;
}
.ant-menu-inline.ant-menu-sub{
    
    
    background: #001529!important;
}
.ant-menu-inline-collapsed{
    
    
    .nav-text{
    
    
        margin-left: 80px!important;
    }
}
.app-layout-header{
    
    
    position: relative;;
    .app-layout-nameInfo{
    
    
        position: absolute;
        right: 15px;
        top: 0;
        display: flex;
    }
}
</style>

7. Configure the overall style in style.css
insert image description here

:root {
    
    
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
}

a {
    
    
  font-weight: 500;
  color: #646cff;
  text-decoration: inherit;
}
a:hover {
    
    
  color: #535bf2;
}

a {
    
    
  font-weight: 500;
  color: #646cff;
  text-decoration: inherit;
}
a:hover {
    
    
  color: #535bf2;
}

body {
    
    
  margin: 0;
  display: flex;
  place-items: center;
  min-width: 320px;
  min-height: 100vh;
}

h1 {
    
    
  font-size: 3.2em;
  line-height: 1.1;
}

button {
    
    
  border-radius: 8px;
  border: 1px solid transparent;
  padding: 0.6em 1.2em;
  font-size: 1em;
  font-weight: 500;
  font-family: inherit;
  background-color: #1a1a1a;
  cursor: pointer;
  transition: border-color 0.25s;
}
button:hover {
    
    
  border-color: #646cff;
}
button:focus,
button:focus-visible {
    
    
  outline: 4px auto -webkit-focus-ring-color;
}

.card {
    
    
  padding: 2em;
}

#app {
    
    
  margin: 0 auto;
  /* text-align: center; */
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

@media (prefers-color-scheme: light) {
    
    
  :root {
    
    
    color: #213547;
    background-color: #ffffff;
  }
  a:hover {
    
    
    color: #747bff;
  }
  button {
    
    
    background-color: #f9f9f9;
  }
}



/* //修改滚动条样式 */
::-webkit-scrollbar {
    
    
  width: 8px;
  height: 5px;
  /* background: hsla(0, 0%, 100%, 0.6); */
}

::-webkit-scrollbar-track {
    
    
  border-radius: 0;
}

::-webkit-scrollbar-thumb {
    
    
  border-radius: 0;
  background-color: rgba(95, 95, 95, 0.4);
  transition: all 0.2s;
  border-radius: 5px;

  &:hover {
    
    
    background-color: rgba(95, 95, 95, 0.7);
  }
}

8. Introduce the Alibaba vector icon library
https://www.iconfont.cn/,
add the icon to the icon library project, and then download the package. After that, create a new iconfont folder under assets under the src folder of the project, and paste the contents of the downloaded package to the iconfont folder.
insert image description here
insert image description here
Then import it in the entry file and use it on the page

import "./assets/iconfont/iconfont.css";

insert image description here

At this point, the routing configuration is complete:
insert image description here
insert image description here

insert image description here
insert image description here

axios request

https://www.axios-http.cn/docs/intro

npm install axios

insert image description here
Create a new api folder under the src folder, create a baseApi.js file under the api folder to write the encapsulated request and
insert image description here
use the request data in the page, the get parameters are directly spelled to the back of the path to pass parameters, and the parameters of the post request are the above The second parameter, data. There are two parameters in the brackets when the post request is made, and the second parameter is the parameter to be passed. Configure the domain name in the proxy reverse code, and the first parameter of the request is the specific request interface address.
insert image description here
Obtain the token when logging in, and then save it in the local storage, and use the Token in the router guard to determine whether to log in. If you are logged in, you will be redirected to the home page, and if you are not logged in, you will be redirected to the login page.
insert image description here
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/Sunshinedada/article/details/130917204