vue3.2 初始化项目准备工作

552 阅读3分钟

项目启动

安装项目

// 使用vite安装
yarn create vite my-vue-app --template vue

// 安装插件
yarn

// 启动项目
yarn dev

安装 vue-router

yarn add vue-router@4

官方文档https://router.vuejs.org/zh/

创建/src/router/index.ts文件

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'home',
    component: () => import('../view/home.vue'),
  }
]

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

export default router

修改/src/main.ts文件

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router'

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

配置@/xxx路径引入

安装node

yarn add @types/node -D

修改/tsconfig.json

{
	"compilerOptions": {
		"target": "esnext",
		"useDefineForClassFields": true,
		"module": "esnext",
		"moduleResolution": "node",
		"strict": true,
		"jsx": "preserve",
		"sourceMap": true,
		"resolveJsonModule": true,
		"esModuleInterop": true,
		"lib": ["esnext", "dom"],
    "typeRoots" : ["./src/typings"],
    "baseUrl": ".", // 默认url
    "paths": {
			"@/*": ["src/*"] // 路径转换
		}
	},
	"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
	"references": [{ "path": "./tsconfig.node.json" }]
}

修改/vite.config.ts文件

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    }
  }
})

安装 Ant Design Vue

yarn add ant-design-vue@3.0.0-beta.10

按需引入

修改/src/main.ts文件

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router'
import 'ant-design-vue/dist/antd.css'; 
import antd from 'ant-design-vue';
const app = createApp(App)
app.use(antd)
app.use(router)
app.mount('#app')

解除控制台警告

DevTools 无法加载来源映射:无法加载 http://localhost:3000/antd.css.map 的内容:HTTP 错误:状态代码 404,net::ERR_HTTP_RESPONSE_CODE_FAILURE

打开浏览器控制台,关闭,启动css源代码映射这一项

安装 axios

官方文档https://www.npmjs.com/package/axios

yarn add axios

创建axios实例

创建/src/utils/https.ts文件

import axios from 'axios'

// 创建axios实例
const service = axios.create({
  timeout: 10000, // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  headers: { 'Content-type': 'application/json' }, // 即将被发送的自定义请求头
});

export default service

创建请求

创建/src/api/index.ts文件

import request from '@/utils/https'

export const getUserList = () => {
  return request({
    url: "/users/user",
    method: 'get'
  })
}

页面调用

修改/src/view/home.vue页面

<script lang="ts" setup>
import { getUserList } from '@/api/index'

const getData = async () => {
	try {
		const res = await getUserList()
    console.log(res)
	} catch (error) {
    console.log(error)
  }
}
getData()
</script>
<template></template>
<style lang="scss" scoped></style>

解决跨域问题

修改/vite.config.ts文件

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    }
  },
  server: {
    // 代理服务
    proxy: {
      '/users': 'http://localhost:8000',
    }
  }
})

配置方法有一下几种

{
  // 字符串简写写法
  '/foo': 'http://localhost:4567',
    // 选项写法
    '/api': {
    target: 'http://jsonplaceholder.typicode.com',
      changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
  },
  // 正则表达式写法
  '^/fallback/.*': {
    target: 'http://jsonplaceholder.typicode.com',
      changeOrigin: true,
        rewrite: (path) => path.replace(/^\/fallback/, '')
  },
  // 使用 proxy 实例
  '/api': {
    target: 'http://jsonplaceholder.typicode.com',
      changeOrigin: true,
        configure: (proxy, options) => {
          // proxy 是 'http-proxy' 的实例
        }
  },
  // Proxying websockets or socket.io
  '/socket.io': {
    target: 'ws://localhost:3000',
      ws: true
  }
}

配置axios typing

创建/src/typings/axios.d.ts文件, 加这个文件的好处是,在给request({})传参的时候会有提示

import * as axios from 'axios';

declare module 'axios' {
  interface AxiosInstance {
    (config: AxiosRequestConfig): Promise<any>;
  }
}

配置axios拦截

修改/src/utils/https.ts文件

import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'

// 创建axios实例
const service = axios.create({
  timeout: 10000, // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  headers: { 'Content-type': 'application/json' }, // 即将被发送的自定义请求头
});

// 添加请求拦截器
service.interceptors.request.use((config: AxiosRequestConfig) => {
  // 在发送请求之前做些什么
  // 通常会在这里对请求头添加token
  const token = '111';
  if (token) {
    config.headers = {
      ...config.headers,
      ['Authorization']: `Bearer ${token}`
    };
  }
  return config
}, (error) => {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
service.interceptors.response.use((response: AxiosResponse) => {
  // 对响应数据做点什么
  // 返回响应数据
  return Promise.resolve(response.data)
}, (error) => {
  // 对响应错误做点什么
  // 获取请求报错的错误代码
  const type = error.response.request.status
  checkStatus(type, error.response.data)
  return Promise.reject(error)
})

const checkStatus = (status: number, data: any) => {
  // 错误信息处理
}

export default service

安装 mock

官方文档https://www.npmjs.com/package/vite-plugin-mock

yarn add mockjs -D
yarn add @types/mockjs -D
yarn add vite-plugin-mock -D

创建 mock

官方文档https://www.npmjs.com/package/cross-env

创建/src/mock/index.ts文件

import { MockMethod } from 'vite-plugin-mock'
export default [
  {
    url: '/api/get',
    method: 'get',
    response: () => {
      return {
        code: 0,
        data: {
          name: 'vben',
        },
      }
    },
  },
] as MockMethod[]

创建/src/mockProdServer.ts文件

import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'
import mock from './mock/index'

export function setupProdMockServer() {
  createProdMockServer([ ...mock])
}

修改/src/main.ts文件

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router'
import 'ant-design-vue/dist/antd.css';
import antd from 'ant-design-vue';
import { setupProdMockServer } from './mockProdServer';
setupProdMockServer()
const app = createApp(App)
app.use(antd)
app.use(router)
app.mount('#app')

使用 mock

创建/src/api/mock/index.ts文件

import request from '@/utils/https'

export const getList = () => {
  return request({
    url: "/api/get",
    method: 'get'
  })
}

修改/src/view/home.vue文件

<script lang="ts" setup>
import { getList } from '@/api/mock/index'

const getData = async () => {
	try {
		const res = await getList()
		console.log(res)
	} catch (error) {
		console.log(error)
	}
}
getData()
</script>
<template></template>
<style lang="scss" scoped></style>

配置 mock

完成以上步骤, mock使用会报错, 需要进行配置

修改/vite.config.ts文件

import { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { viteMockServe } from 'vite-plugin-mock'
// https://vitejs.dev/config/
export default ({ command }: ConfigEnv): UserConfigExport => {
  let prodMock = true
  return {
    plugins: [vue(), viteMockServe({
      mockPath: './src/mock',
      localEnabled: command === 'serve',
      injectCode: `
          import { setupProdMockServer } from './mockProdServer';
          setupProdMockServer();
        `,
    })],
    resolve: {
      alias: {
        '@': resolve(__dirname, './src'),
      }
    },
    server: {
      proxy: {
        '/users': 'http://localhost:8000'
      }
    }
  }
}

mock 环境配置

yarn add cross-env -D

修改/src/package.json文件

"scripts": {
  "dev": "vite",
  "build": "vue-tsc --noEmit && vite build",
  "dev:mock": "cross-env USE_MOCK=true vite", // mock环境
  "preview": "vite preview"
},

启动环境

yarn dev:mock

补充

缺点: mock 环境下启动, 开发环境的接口无法被调用

安装 i18n国际化

官方文档``

yarn add vue-i18n@next

创建 i18n

文件目录

image.png

语言文件

// en/index.ts
export default {
  header: {
    Home: 'home',
  }
}
// zh-CN/index.ts
export default {
  header: {
    Home: '首页',
  }
}

注册i18实例, 创建/src/locales/setupI18n.ts文件

import type { App } from 'vue'
import { createI18n } from 'vue-i18n'		//引入vue-i18n组件
import messages from './getMessage'

//注册i8n实例并引入语言文件
const localeData = {
  legacy: false, // composition API
  locale: 'zh-CN',
  messages,
}

export function setupI18n(app: App) {
  const i18n = createI18n(localeData);
  app.use(i18n);
}

工程化处理/src/locales/getMessage.ts文件

<!-- 需要安装 lodash-es -->
yarn add @types/lodash-es -D
// 将各种message modules 汇总到这里
import { set } from 'lodash-es';
const modules = import.meta.globEager('./lang/**/*.ts');

interface IObj {
  [name: string]: any
}

const genMessage = (langs: Record<string, Record<string, any>>, prefix = 'lang') => {
  const obj: IObj = {};
  Object.keys(langs).forEach((key) => {
    const mod = langs[key].default;
    let k = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
    const lastIndex = k.lastIndexOf('.');
    k = k.substring(0, lastIndex);
    const keyList = k.split('/');
    const lang = keyList.shift();
    const objKey = keyList.join('.');
    if (lang) {
      set(obj, lang, obj[lang] || {});
      set(obj[lang], objKey, mod);
    }
  });
  return obj;

}
export default genMessage(modules);

自定义 Hook

创建/src/hooks/useI18n.ts文件

import { i18n } from '@/locales/setupI18n'
export const { t, ...methods } = i18n.global

使用 i18n

<script lang="ts" setup>
import { t } from '@/hooks/useI18n'
</script>
<template>
	<div>
    {{t('index.header.Home')}}
	</div>
</template>
<style lang="scss" scoped></style>

警告

You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to explicitly replace feature flag globals with boolean literals to get proper tree-shaking in the final bundle.

解决方法

配置/vite.config.ts文件

import { ConfigEnv, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { viteMockServe } from 'vite-plugin-mock'
// https://vitejs.dev/config/
export default ({ command }: ConfigEnv): UserConfigExport => {
  return {
    plugins: [vue(), viteMockServe({
      mockPath: './src/mock',
      localEnabled: command === 'serve',
      injectCode: `
          import { setupProdMockServer } from './mockProdServer';
          setupProdMockServer();
        `,
    })],
    resolve: {
      alias: {
        '@': resolve(__dirname, './src'),
        'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js' // 加入这行
      }
    },
    server: {
      proxy: {
        '/users': 'http://localhost:8000'
      }
    }
  }
}