Vue项目开发

1 项目初始化

1.1 创建一个VUE VITE TS项目

npm create vite ${project-name} --template vue
cd ${project-name}
npm install
npm run dev

1.2 添加路由、sass、element-plus、axios等模块

npm install vue-router element-plus axios sass-loader pinia
npm install sass --save-dev

1.3 路由 (src/router/index.ts)

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import LoginView from '../views/LoginView.vue'
import ContentView from '../views/ContentView.vue'
import TagView from '../views/TagView.vue'
import ArchiveView from '../views/ArchiveView.vue'
import SearchView from '../views/SearchView.vue'
import BlogPreview from '../views/BlogPreview.vue'
import { getToken } from '../store'
const routes: Array<RouteRecordRaw> = [
  {
    path: '/home',
    name: 'home',
    component: HomeView,
    redirect: '/home/0',
    children: [
      {
        path: '/home/:id(\\d*)',
        name: '目录',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: ContentView,
      },
      {
        path: '/tag',
        name: '标签',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: TagView
      },
      {
        path: '/archive',
        name: '归档',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: ArchiveView
      },
      {
        path: '/search',
        name: '搜索',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: SearchView
      },
      {
        path: '/write',
        name: '写博客',
        component: () => import(/* webpackChunkName: "write" */ '../views/WriteBlog.vue')
      },
      {
        path: '/recycle',
        name: '回收站',
        component: () => import(/* webpackChunkName: "Recycle" */ '../views/RecycleBin.vue')
      },
    ]
  },
  {
    path: '/login',
    name: 'login',
    component: LoginView
  },
  {
    path: '/blog',
    name: 'blog',
    component: BlogPreview
  },
]
const router = createRouter({
  history: createWebHashHistory(),
  routes
})
router.beforeEach((to) => {
  const token: string | null = getToken()
  if (!token && to.path !== '/login') {
    return '/login'
  } else if (token && to.path === '/login') {
    return '/home'
  }
})

export default router

1.4 引入ELEMENT-PLUS (src/main.ts)

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createPinia } from 'pinia'


createApp(App).use(ElementPlus).use(router).use(createPinia()).mount('#app')

1.5 引入axios (src/api/index.ts)

import axios from 'axios'
import { ElMessage } from 'element-plus'
import { getToken } from '../store'
// create an axios instance
const $http = axios.create({
  // baseURL: "http://localhost:8080", // 先不用
  withCredentials: false, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})
// request interceptor
$http.interceptors.request.use(
  config => {
    // do something before request is sent
    config.headers = {}
    if (getToken()) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['Authorization'] = getToken() || ''
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)
// response interceptor
$http.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */
  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 20000) {
      ElMessage({
        message: res.msg || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      // // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      // if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
      //   // to re-login
      //   MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
      //     confirmButtonText: 'Re-Login',
      //     cancelButtonText: 'Cancel',
      //     type: 'warning'
      //   }).then(() => {
      //     store.dispatch('user/resetToken').then(() => {
      //       location.reload()
      //     })
      //   })
      // }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  error => {
    console.log('err' + error) // for debug
    ElMessage({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)
export default $http

1.6 调用外部API(src/api/http.ts)

import $http from './index'
import { LoginData, KateFileData, BlogFileData, RecycleData } from '../types/Data.t'
// 应用服务器
const appHost = "http://localhost:4050"
// 文件服务器
const fileHost = "http://localhost:4000"
// --------------------------文件服务器操作--------------------------
export const saveBlog = (data: BlogFileData) => $http({ baseURL: fileHost, url: '/createFile', method: "POST", data })
export const getContent = (data: String) => $http({ baseURL: fileHost, url: `/getContent/${data}`, method: 'GET' })
export const removeBlog = (data: String) => $http({ baseURL: fileHost, url: `/deleteFile/${data}`, method: 'DELETE' })
// --------------------------user--------------------------
// 登录请求
export const login = (data: LoginData) => $http({ baseURL: appHost, url: "/user/login", method: "POST", data })
// 标签页面获取博客列表--------------------------article--------------------------
export const fetchBlogList = (data: Array<String>) => $http({ baseURL: appHost, url: '/article/fetchBlogListByTagList', method: "POST", data });
// 根据博客名称模糊匹配博客列表
export const searchBlogList = (name: string) => $http({ baseURL: appHost, url: `/article/fetchBlogListByName/${name}`, method: "GET" })
// 根据日期区分博客
export const fetchArticle = () => $http({ baseURL: appHost, url: '/article/fetchArichive', method: 'GET' })
// --------------------------article--------------------------
// 根据url匹配单个article
export const getArticle = (url: string) => $http({ baseURL: appHost, url: `/fetchArticle/${url}`, method: 'GET' })
// 获取文件列表
export const fetchFileList = (parentId: string) => $http({ baseURL: appHost, url: `/article/fetchDataList/${parentId}`, method: "GET" })
// 新增文件
export const addFile = (file: KateFileData) => $http({ baseURL: appHost, url: '/article/add', method: "POST", data: file })
// 修改文件
export const updateFile = (file: KateFileData) => $http({ baseURL: appHost, url: '/article/update', method: "PUT", data: file })
// 删除文件
export const deleteFile = (id: string) => $http({ baseURL: appHost, url: `/article/remove/${id}`, method: 'DELETE' })
// --------------------------dir--------------------------
// 获取所有目录结构
export const fetchDirList = () => $http({ baseURL: appHost, url: '/dir/fetchDirList', method: 'GET' })
// 删除目录
export const deleteDir = (id: string) => $http({ baseURL: appHost, url: `/dir/remove/${id}`, method: 'DELETE' })
// --------------------------tag--------------------------
// 获取标签列表
export const fetchTagList = () => $http({ baseURL: appHost, url: `/tag/fetchDataList/`, method: "GET" })
// 新增标签
export const addTag = (tag: KateFileData) => $http({ baseURL: appHost, url: '/tag/add', method: "POST", data: tag })
// 修改标签
export const updateTag = (tag: KateFileData) => $http({ baseURL: appHost, url: '/tag/update', method: "PUT", data: tag })
// 删除标签
export const deleteTag = (id: string) => $http({ baseURL: appHost, url: `/tag/remove/${id}`, method: 'DELETE' })
// 获取所有回收站数据
export const getRecycle = () => $http({ baseURL: appHost, url: '/dir/fetchRecycle', method: "GET" })
// 恢复列表内容
export const recoverData = (data: Array<RecycleData>) => $http({ baseURL: appHost, url: '/dir/recover', method: "PUT", data })

1.7 状态管理 pinia

TODO

2 编译构建项目

npm run build

PS: 生成一个dist目录,把里面的文件Copy出来

3 部署

3.1 放到SpringBoot静态资源文件夹下和SpringBoot一起部署

3.2 使用Nginx单独部署,前后分离,注意跨域处理。

nginx的docker安装

// install docker
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
sudo docker --version
// install nginx
sudo docker run -d -p 80:80 --name=nginx nginx
// copy conf from docker to /opt/docker/nginx/conf
sudo docker cp nginx:/etc/nginx/ /opt/nginx/conf/
// remove nginx, create new nginx mount /docker/nginx/conf
sudo docker rm -f nginx
sudo docker run -d -p 80:80 -v /opt/docker/nginx/conf/:/etc/nginx/ -v /opt/docker/nginx/html/:/usr/share/nginx/ --name=nginx nginx
sudo docker ps
posted @ 2022-09-30 07:32  土豆炒西红柿  阅读(64)  评论(0编辑  收藏  举报