写个云盘网站练练手(前端篇1)

293 阅读4分钟

这个系列的文章,是我在入门后端时用于练手的记录,因此并不会讲的十分十分详细。很多东西可能一笔带过,不太建议小白阅读。

云盘项目前端的代码量并不很多,因为它只有一个登录页和一个文件管理页(首页),但我还有许多好想法,这无疑是需要时间来去想去做的,我因此不在这演示项目效果。

一、vue项目搭建及初始化

1.1 进入你要新建项目的文件目录,打开该目录的终端
1.2 控制台输入后,它需要你对项目选择配置,我这里选择的是 vite+vue3+js 项目,项目名称为:myCloud
npm init vite@latest myCloud --template vue

二、安装配置 AntD Vue 框架

2.1 进入项目根目录终端安装antd框架
npm install ant-design-vue -S
2.2 在 main.js 入口文件全局引入及实例化此框架的组件和样式
// 全局引入及实例化框架的组件和样式
import Antd from 'ant-design-vue';
// Q:为什么引入.less文件而不是.css? A:为了全局修改主题样式
import 'ant-design-vue/dist/antd.less';

createApp(App).use(Antd).mount('#app')
2.3 在 vite.config.js 文件配置框架主题色
export default defineConfig({
             ……
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
        'primary-color': '#8400dc',
        'link-color': '#8400dc',
        'border-radius-base': '6px',
      },
        javascriptEnabled: true //开启less编译,注意:这个很重要
      }
    }
  }
             ……
})

2.4 若提示未安装less依赖,则安装运行
npm i less@3.9.0 less-loader@4.1.0 --save-dev

三、安装 vueRouter 路由依赖 (vue3 项目需使用v4.x 版本)

3.1 进入项目根目录终端安装指定版本的路由管理依赖
npm install vue-router@4
3.2 在 main.js 入口文件中引入路由并注册
import router from "./router";
createApp(App).use(Antd).use(router).mount('#app')
3.3 路由的使用
  • 3.3.1 在 src 目录下新建 router 目录并在此目录下创建 index.js 文件
  • 3.3.2 在 vite.config.js 文件里为常用目录配置别名、运行配置、跨域等
import path from 'path'

export default defineConfig({
    ……
    
    resolve: {
        //配置别名
        alias: {
            // __dirname:获取当前文件的路径
            '@': path.resolve(__dirname, 'src'),
            '@assets': path.resolve(__dirname, 'src/assets'),
            '@views': path.resolve(__dirname, 'src/views'),
            '@comp': path.resolve(__dirname, 'src/components'),
            '@comm': path.resolve(__dirname, 'src/common'),
            '@router': path.resolve(__dirname, 'src/router'),
            '@apis': path.resolve(__dirname, 'src/apis'),
            '@axios': path.resolve(__dirname, 'src/axios'),
            '@stores': path.resolve(__dirname, 'src/stores'),
            '@utils': path.resolve(__dirname, 'src/utils'),
        }
    },
    server: {
        host: "0.0.0.0",
        cors: true,
        open: false,//启动项目自动弹出浏览器
        port: 3001,//启动端口
        proxy: {
            '^/ls-boot': {  
                target: `http://localhost:3003/ls-boot`, //实际请求地址  
                changeOrigin: true,  
                rewrite: (path) => path.replace(/^\/ls-boot/, '')  
            },  
        }  
    },
    
    ……
})

  • 3.3.3 在 src 目录下新建 views 目录,并在此目录下新建 index.vuelogin.vue404.vue 三个文件,分别用作首页、登录页以及路径不存在时的显示
  • 3.3.4 在 src/router/index.js文件里填入如下代码
import {createRouter, createWebHashHistory} from 'vue-router'; 

//引入views目录下的页面
import Index from '@views/index.vue'
import Login from '@views/login.vue'
import NotFound from '@views/404.vue'
 
const routes = [
    {
        path: '/',
        component: Index
    },
    {
        path: '/login',
        component: Login
    },
    // 若没有此路由则跳转至404.vue页面
    {
        path: '/:pathMatch(.*)*',
        name: 'NotFound',
        component: NotFound
     }
]
const router = createRouter({
    history: createWebHashHistory(),
    routes, 
})

// 全局守卫,需要配合我下面的响应拦截:登录拦截 本地没有存token,请重新登录
router.beforeEach((to, from, next) => {
    // 判断有没有登录,且不在登录页,则跳转至登录页
    if (!localStorage.getItem('Token')) {
        if (to.path != '/login') {  
            router.push('/login')
        }else{
            next();
        }
    } else {
	next();
    }
});
export default router
  • 3.3.5 替换 App.vue 文件里的内容
<script>  
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale  
import dayjs from 'dayjs';  
import 'dayjs/locale/zh-cn';  
import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';  
import {defineComponent} from 'vue';  
  
dayjs.locale('zh-cn');  
  
export default defineComponent({  
    setup() {  
        function getPopupContainer(el, dialogContext) {  
            if (dialogContext) {  
                return dialogContext.getDialogWrap();  
            } else {  
                return document.body;  
            }  
        }  

        return {  
            dayjs,  
            locale,  
            getPopupContainer  
        };  
    },  
});  
</script>  

<template>  
    <a-config-provider :csp="{ nonce: 'YourNonceCode' }" :getPopupContainer="getPopupContainer" :locale="locale">  
        <router-view/>  
    </a-config-provider>  
</template>  

四、安装 axios 网络请求依赖

4.1 进入项目根目录终端安装 axios
npm install axios
4.2 axios 的配置与使用
  • 4.2.1 在 src 目录下新建 axios 目录,并新建两个js文件: index.jsHttps.js
// index.js
import axios from 'axios'

// 创建一个 axios 实例
const service = axios.create({
    baseURL: '/ls-boot', // 所有的请求地址前缀部分
    timeout: 30000, // 请求超时时间毫秒,30s
    withCredentials: true, // 异步请求携带cookie
})

// 添加请求拦截器
service.interceptors.request.use(
    function (config) {
        // 为所有请求的请求头加 Token,没有则赋 null
        config.headers['Authorization'] = localStorage.getItem('Token') || null;
        return config
    },
    function (error) {
        // 对请求错误做些什么
        return Promise.reject(error)
    }
)

// 添加响应拦截器
service.interceptors.response.use(
    function (response) {
        const dataAxios = response.data
        return dataAxios
    },
    function (error) {
        // 超出 2xx 范围的状态码都会触发该函数。
        // 对响应错误做点什么
        if (error.response.status == 401) {
            localStorage.removeItem("Token");
            setTimeout(() => {
                location.reload();
            }, 100)
        }
        return Promise.reject(error.response.data)
    }
)

export default service

// Https.js

// 导入axios实例
import httpRequest from './index.js'

const baseHeaders = {
    'Content-Type': 'application/json',
}

// get请求封装
export function getHttp(url, params = {}, headers = baseHeaders) {
    return httpRequest({
        url,
        params,
        method: 'get',
        headers,
    })
}

// post请求封装
export function postHttp(url, params = {}, headers = baseHeaders) {
    return httpRequest({
        url,
        method: 'post',
        data: params,
        headers,
    })
}

五、安装pinia及持久化使用

5.1 进入项目根目录终端安装 pinia及持久化插件pinia-plugin-persist
npm install pinia pinia-plugin-persist

5.2 在main.js文件中注册及实例化
import {createPinia} from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'

const pinia = createPinia()
pinia.use(piniaPluginPersist)

createApp(App).use(pinia).mount('#app')
5.3 在src目录下新建stores/index.js文件,并在文件中写入以下代码
import {defineStore} from "pinia" // 定义容器

export const useMain = defineStore('useStore', {
    /**
     * 存储全局状态
     * 1.必须是箭头函数: 为了在服务器端渲染的时候避免交叉请求导致数据状态污染
     * 和 TS 类型推导
     */
    state: () => {
        return {
            count: 0,
            list: [1, 2, 3, 4]
        }
    },
    /**
     * 用来封装计算属性 有缓存功能  类似于computed
     */
    getters: {
        getNum(state) {
            return state.count + 1
        }
    },
    /**
     * 编辑业务逻辑  类似于methods
     */
    actions: {
        addList() {
            this.count ++
        }
    }

})
/*
//页面使用:
import { useMain } from '@store/index.js' // 引入store
const useStoreMain = useMain()

我们这里可以直接结构出想要的数据,但是数据会出现无法实现响应式问题,官方使用的API reactive 使state数据生成响应式。 对于这种情况我们可以这样做
import { storeToRefs } from 'pinia'
const { count } = storeToRefs(useStore())
* */