update
This commit is contained in:
parent
fc8d135f46
commit
7d5e0721df
845
项目开发手册.md
845
项目开发手册.md
@ -1,845 +0,0 @@
|
||||
# Vue3项目开发手册
|
||||
|
||||
## 初始化项目
|
||||
|
||||
### 技术选型
|
||||
|
||||
Vue3 + Element-plus + Vite
|
||||
|
||||
- Vue3
|
||||
|
||||
>- 支持 Vue2 的大多数特性
|
||||
>- 支持 Typescript
|
||||
>- 使用 Proxy 代替 defineProperty 实现数据响应式
|
||||
>- 重写虚拟 DOM 的实现和 Tree-Shaking
|
||||
>- [Vue3中文官网](https://vue3js.cn/docs/zh/guide/introduction.html)
|
||||
|
||||
- Element-plus
|
||||
|
||||
> - 支持Vue3的element-ui组件库
|
||||
>
|
||||
> > element-ui只支持到vue2,element-plus可以支持vue3
|
||||
>
|
||||
> - [Element-plus中文官网](https://element-plus.gitee.io/#/zh-CN)
|
||||
|
||||
- Vite
|
||||
|
||||
>- 是一种新型前端构建工具,能够显著提升前端开发体验。
|
||||
>
|
||||
>- [Vite中文官网](https://www.pipipi.net/vite/)
|
||||
|
||||
### 创建项目
|
||||
|
||||
> 我们将使用vite和vue3手动进行前端项目架构。为方便大家从vue2过渡到vue3,本项目我们先不使用ts。
|
||||
>
|
||||
|
||||
使用vite的命令创建项目:
|
||||
|
||||
> 需要 Node.js 版本 >= 12.0.0
|
||||
|
||||
```powershell
|
||||
# npm 6.x
|
||||
npm init @vitejs/app erp-vue3 --template vue
|
||||
|
||||
# npm 7+, 需要额外的双横线:
|
||||
npm init @vitejs/app erp-vue3 -- --template vue
|
||||
|
||||
# yarn
|
||||
yarn create @vitejs/app erp-vue3 --template vue
|
||||
```
|
||||
|
||||
- npm init @vitejs/app 是固定的写法
|
||||
|
||||
- erp-vue3 是项目名称
|
||||
|
||||
- --template vue 是指定模板预设。指定vue就是使用vue3并且不使用ts。
|
||||
|
||||
> 支持的模板预设如下,有兴趣可以挨个试一下
|
||||
>
|
||||
> - `vanilla`
|
||||
> - `vue`
|
||||
> - `vue-ts`
|
||||
> - `react`
|
||||
> - `react-ts`
|
||||
> - `preact`
|
||||
> - `preact-ts`
|
||||
> - `lit-element`
|
||||
> - `lit-element-ts`
|
||||
|
||||
创建完后,会提示我们进入项目目录,安装依赖,运行项目:
|
||||
|
||||
```powershell
|
||||
cd erp-vue3
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
最后我们来看下项目结构
|
||||
|
||||
```powershell
|
||||
├─node_modules -----------依赖包
|
||||
├─public -----------------静态文件
|
||||
├─index.html--------------主页面
|
||||
├─src---------------------核心文件目录(我们开发的代码都在src目录)
|
||||
| ├─assets---------------静态资源(图片,字体,css,js等)
|
||||
| ├─components-----------公共组件
|
||||
| ├─App.vue--------------根组件
|
||||
| ├─main.js--------------入口文件
|
||||
├─package.json------------项目基本信息和依赖包信息
|
||||
├─vite.config.js----------配置文件
|
||||
```
|
||||
|
||||
## 完善项目架构
|
||||
|
||||
> 目前项目中还没有路由、状态管理、UI组件库、ajax库
|
||||
|
||||
### 组件库 Element Plus
|
||||
|
||||
- 安装element-plus,并且在main.js中引入
|
||||
|
||||
```powershell
|
||||
npm install element-plus
|
||||
```
|
||||
|
||||
引入element-plus
|
||||
|
||||
```js
|
||||
// main.js
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
// 引入element-plus
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/lib/theme-chalk/index.css";
|
||||
|
||||
// 使用use注册ElementPlus
|
||||
createApp(App).use(ElementPlus).mount('#app')
|
||||
|
||||
```
|
||||
|
||||
- vue3中如何全局调用element-plus中的提示插件
|
||||
|
||||
```js
|
||||
import {getCurrentInstance} from 'vue';
|
||||
|
||||
setup () {
|
||||
const { ctx } = getCurrentInstance(); // 可以把ctx当成vue2中的this
|
||||
ctx.$message.success("yes")
|
||||
ctx.$loading()
|
||||
}
|
||||
```
|
||||
|
||||
### 路由
|
||||
|
||||
- 在src目录中创建views目录,用来存放页面
|
||||
|
||||
> 我们使用模块化的方式来管理页面,比如用户管理、权限管理等模块,每个模块下可能有多个页面,所以每个模块都要创建一个目录
|
||||
|
||||
在views目录中创建home目录(代表home模块),home目录中创建index.vue,index.vue代表home模块的主页面
|
||||
|
||||
```vue
|
||||
<template>
|
||||
home
|
||||
</template>
|
||||
```
|
||||
|
||||
同样的方式创建一个login模块
|
||||
|
||||
```vue
|
||||
<template>
|
||||
login
|
||||
</template>
|
||||
```
|
||||
|
||||
- 安装路由vue-router
|
||||
|
||||
```powershell
|
||||
# 安装最新版的vue-router
|
||||
npm install vue-router@next
|
||||
```
|
||||
|
||||
- 在src目录中创建router目录,用来存放路由配置文件
|
||||
|
||||
> 路由配置就是配置views模块中的页面通过什么地址来访问,路由我们也使用模块化管理,views中有多少模块就创建多少路由配置文件,此外还需要一个index.js来统一分配路由模块
|
||||
|
||||
router目录中创建modules目录, modules目录中创建home.js和login.js
|
||||
|
||||
```js
|
||||
// home.js
|
||||
const Home = () => import("../../views/home/index.vue");
|
||||
|
||||
export default [
|
||||
{
|
||||
path: "/home",
|
||||
name: "home",
|
||||
component: Home,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```js
|
||||
// login.js
|
||||
const Login = () => import("../../views/login/index.vue");
|
||||
|
||||
export default [
|
||||
{
|
||||
path: "/login",
|
||||
name: "login",
|
||||
component: Login,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
router目录中创建index.js
|
||||
|
||||
```js
|
||||
// index.js
|
||||
import { createRouter, createWebHashHistory } from "vue-router"
|
||||
import home from './modules/home'
|
||||
import login from './modules/login'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home'
|
||||
},
|
||||
...home,
|
||||
...login
|
||||
],
|
||||
});
|
||||
|
||||
export default router;
|
||||
```
|
||||
|
||||
- 修改App.vue
|
||||
|
||||
```html
|
||||
|
||||
```
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
```
|
||||
|
||||
- 挂载路由
|
||||
|
||||
> 在main.js中挂载路由
|
||||
|
||||
```js
|
||||
// main.js
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
// 引入element-plus
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/lib/theme-chalk/index.css";
|
||||
|
||||
// 引入路由
|
||||
import router from './router'
|
||||
|
||||
// 使用use注册路由
|
||||
createApp(App).use(ElementPlus).use(router).mount('#app')
|
||||
```
|
||||
|
||||
- 配置alias路径别名
|
||||
|
||||
> 文件引入路径比较深的时候,使用相对路径需要写很多`../`,例如上面的`router/modules/home.js`文件
|
||||
>
|
||||
> 所以我们可以配置一个src目录的别名,需要在vite.config.js中配置
|
||||
|
||||
```js
|
||||
// vite.config.js
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
然后我们就可以修改路由组件的引用路径了,在router/modules/home.js中
|
||||
|
||||
```js
|
||||
// home.js
|
||||
// const Home = () => import("../../views/home/index.vue");
|
||||
const Home = () => import("@/views/home/index.vue");
|
||||
|
||||
export default [
|
||||
{
|
||||
path: "/home",
|
||||
name: "home",
|
||||
component: Home,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### 状态管理
|
||||
|
||||
- 安装vuex状态管理插件
|
||||
|
||||
```powershell
|
||||
# 安装最新版的vuex
|
||||
npm install vuex@next
|
||||
```
|
||||
|
||||
- 在src目录中创建store目录,用来存放状态模块
|
||||
|
||||
> 状态管理也使用模块化的方式
|
||||
|
||||
在store目录中创建modules目录,modules中创建一个模块app.js
|
||||
|
||||
```js
|
||||
// app.js
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {},
|
||||
mutations: {},
|
||||
actions: {},
|
||||
};
|
||||
```
|
||||
|
||||
在store目录中创建index.js
|
||||
|
||||
```js
|
||||
//index.js
|
||||
import { createStore } from "vuex";
|
||||
import app from "./modules/app";
|
||||
|
||||
export default createStore({
|
||||
modules: {
|
||||
app,
|
||||
},
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
- 挂载store
|
||||
|
||||
```js
|
||||
// main.js
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
// 引入element-plus
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/lib/theme-chalk/index.css";
|
||||
|
||||
// 引入路由
|
||||
import router from './router'
|
||||
|
||||
// 引入store
|
||||
import store from './store'
|
||||
|
||||
// 使用use注册路由和store
|
||||
createApp(App).use(ElementPlus).use(router).use(store).mount('#app')
|
||||
```
|
||||
|
||||
### 接口管理
|
||||
|
||||
- 安装axios
|
||||
|
||||
```powershell
|
||||
npm install axios
|
||||
```
|
||||
|
||||
- 接口管理
|
||||
|
||||
> 项目中我们调用接口的时候,有可能有很多页面都会调用同一个接口,所以我们把所有的接口统一进行模块化管理
|
||||
|
||||
在src目录中创建api目录,用来存放所有的接口
|
||||
|
||||
在api目录中创建一个模块login.js,该文件包括跟登录注册相关的所有接口
|
||||
|
||||
```js
|
||||
// login.js
|
||||
import axios from 'axios'
|
||||
|
||||
// 登录接口
|
||||
export const Login = data => {
|
||||
return axios.request({
|
||||
url: "/api/login",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
// 其它接口...
|
||||
```
|
||||
|
||||
在页面中调用登录接口
|
||||
|
||||
> 在views/login/index.vue中:
|
||||
|
||||
```html
|
||||
<template>
|
||||
login
|
||||
<el-button type="primary" @click="login">登录</el-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, onMounted } from "vue";
|
||||
import { Login } from "@/api/login";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Login",
|
||||
setup() {
|
||||
const login = async () => {
|
||||
const res = await Login({
|
||||
userName: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
login
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### 跨域管理
|
||||
|
||||
当前端调用后端接口的时候,假设后端接口的域名是`http://dev.erp.com`,那`http://localhost`访问`http://dev.erp.com`是会跨域的,这时候我们就要在vite.config.js中设置代理
|
||||
|
||||
```js
|
||||
// vite.config.js增加如下配置
|
||||
server: {
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://dev.erp.com",
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
### mock管理
|
||||
|
||||
> 当后端接口没有开发完成的时候,前端就需要根据接口文档mock数据进行开发
|
||||
>
|
||||
> vite中可以使用vite-plugin-mock插件创建mock服务
|
||||
|
||||
- 安装vite-plugin-mock
|
||||
|
||||
```powershell
|
||||
npm install -D mockjs vite-plugin-mock
|
||||
```
|
||||
|
||||
- 配置mock,需要在vite.config.js中配置
|
||||
|
||||
```js
|
||||
// vite.config.js
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import path from "path";
|
||||
import { viteMockServe } from "vite-plugin-mock";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default env => {
|
||||
// console.log(env);
|
||||
|
||||
return defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
viteMockServe({
|
||||
mockPath: "mock", // 指定mock目录中的文件全部是mock接口
|
||||
localEnabled: env.mode === "mock", // 指定在mock模式下才启动mock服务(可以在package.json的启动命令中指定mode为mock)
|
||||
supportTs: false, // mockPath目录中的文件是否支持ts文件,现在我们不使用ts,所以设为false
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://dev.erp.com",
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
- package.json中配置mode为mock的启动命令
|
||||
|
||||
```js
|
||||
// ...
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"mock": "vite --mode mock",
|
||||
// ...
|
||||
```
|
||||
|
||||
重新启动项目
|
||||
|
||||
```powershell
|
||||
npm run mock
|
||||
```
|
||||
|
||||
- 在根目录中创建mock目录,用来存放mock接口
|
||||
|
||||
在mock目录中创建一个test.js
|
||||
|
||||
```js
|
||||
// test.js
|
||||
export default [
|
||||
{
|
||||
url: "/api/get",
|
||||
method: "get",
|
||||
response: {
|
||||
code: 200,
|
||||
data: {
|
||||
name: "hello world",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
这个时候我们访问`http://localhost:3000/api/get`,可以看到返回的mock数据了
|
||||
|
||||
### 封装axios
|
||||
|
||||
> 当我们登录成功之后,后端其实会返回一个token(token就是用来做登录认证的),后续所有请求都需要带上这个token,后端校验token是否有效
|
||||
>
|
||||
> 这个时候,前端要做的就是把token保存在本地存储中,然后所有的请求都要增加一个自定义请求头,用来传递token
|
||||
>
|
||||
> 为了更友好的对请求进行控制(比如添加全局请求头、统一处理错误),我们对axios进行封装,拦截请求和响应
|
||||
|
||||
- 在登录的mock接口中返回token
|
||||
|
||||
```js
|
||||
// mock/login.js
|
||||
export default [
|
||||
{
|
||||
url: "/api/login",
|
||||
method: "post",
|
||||
timeout: 1000,
|
||||
response: {
|
||||
code: 200,
|
||||
message: "登录成功",
|
||||
data: {
|
||||
token: "@word(50, 100)", // @word()是mockjs的语法
|
||||
refresh_token: "@word(50, 100)", // refresh_token是用来重新生成token的
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
- 登录之后,把token保存在localStorage和vuex中
|
||||
|
||||
> 保存在vuex中为了更好的进行响应式控制
|
||||
|
||||
```js
|
||||
// 登录
|
||||
const login = async () => {
|
||||
const { code, data, message } = await Login({
|
||||
userName: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
if (+code === 200) {
|
||||
store.commit("app/setToken", data);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
store/modules/app.js
|
||||
|
||||
```js
|
||||
import { getItem, setItem, removeItem } from "@/utils/storage"; //getItem和setItem是封装的操作localStorage的方法
|
||||
export const TOKEN = "TOKEN";
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
authorization: getItem(TOKEN),
|
||||
},
|
||||
mutations: {
|
||||
setToken(state, data) {
|
||||
state.authorization = data;
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, data);
|
||||
},
|
||||
clearToken (state) {
|
||||
state.authorization = '';
|
||||
// 保存到localStorage
|
||||
removeItem(TOKEN);
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
};
|
||||
```
|
||||
|
||||
在src中创建utils目录,在utils中创建storage.js
|
||||
|
||||
> utils目录主要是用来存放一些常用工具函数
|
||||
|
||||
```js
|
||||
// storage.js
|
||||
export const getItem = name => {
|
||||
const data = window.localStorage.getItem(name);
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (err) {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
export const setItem = (name, value) => {
|
||||
if (typeof value === "object") {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
window.localStorage.setItem(name, value);
|
||||
};
|
||||
|
||||
export const removeItem = name => {
|
||||
window.localStorage.removeItem(name);
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
- 在utils目录中创建request.js
|
||||
|
||||
```js
|
||||
// request.js
|
||||
import axios from "axios";
|
||||
import { ElMessage } from "element-plus";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: "/",
|
||||
timeout: 10000,
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
// 拦截请求
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
const { authorization } = store.state.app;
|
||||
if (authorization) {
|
||||
config.headers.Authorization = `Bearer ${authorization.token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
// console.log(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// 拦截响应
|
||||
service.interceptors.response.use(
|
||||
// 响应成功进入第1个函数,该函数的参数是响应对象
|
||||
(response) => {
|
||||
return response.data;
|
||||
},
|
||||
// 响应失败进入第2个函数,该函数的参数是错误对象
|
||||
async (error) => {
|
||||
// 如果响应码是 401 ,则请求获取新的 token
|
||||
// 响应拦截器中的 error 就是那个响应的错误对象
|
||||
if (error.response && error.response.status === 401) {
|
||||
// 校验是否有 refresh_token
|
||||
const { authorization } = store.state.app;
|
||||
if (!authorization || !authorization.refresh_token) {
|
||||
router.push("/login");
|
||||
|
||||
// 代码不要往后执行了
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// 如果有refresh_token,则请求获取新的 token
|
||||
try {
|
||||
const res = await axios({
|
||||
method: "PUT",
|
||||
url: "/api/authorizations",
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
Authorization: `Bearer ${authorization.refresh_token}`,
|
||||
},
|
||||
});
|
||||
// 如果获取成功,则把新的 token 更新到容器中
|
||||
// console.log('刷新 token 成功', res)
|
||||
store.commit("app/setToken", {
|
||||
token: res.data.data.token, // 最新获取的可用 token
|
||||
refresh_token: authorization.refresh_token, // 还是原来的 refresh_token
|
||||
});
|
||||
// 把之前失败的用户请求继续发出去
|
||||
// config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有
|
||||
// return 把 request 的请求结果继续返回给发请求的具体位置
|
||||
return service(error.config);
|
||||
} catch (err) {
|
||||
// 如果获取失败,直接跳转 登录页
|
||||
// console.log('请求刷新 token 失败', err)
|
||||
router.push("/login");
|
||||
// 清除token
|
||||
store.commit("app/clearToken")
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
ElMessage.error(error.message);
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default service;
|
||||
|
||||
```
|
||||
|
||||
这时我们再回到api/login.js中,只需要引入上面的request.js就行了
|
||||
|
||||
```js
|
||||
// login.js
|
||||
// import axios from 'axios'
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 登录接口
|
||||
export const Login = data => {
|
||||
return request({
|
||||
url: "/api/login",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
### 权限控制
|
||||
|
||||
> 如果没有登录或者token失效的时候,页面需要重定向到登录页
|
||||
>
|
||||
> 还有一些例如找回密码的页面应该也可以访问,所以我们还是设置一个白名单,没有token的时候只能访问白名单的页面
|
||||
|
||||
- 在src目录创建permission.js
|
||||
|
||||
```js
|
||||
// permission.js
|
||||
|
||||
import router from '@/router'
|
||||
import { TOKEN } from '@/store/modules/app' // TOKEN变量名
|
||||
// 白名单,里面是路由对象的name
|
||||
const WhiteList = ['login']
|
||||
|
||||
// vue-router4的路由守卫不再是通过next放行,而是通过return返回false或者一个路由地址
|
||||
router.beforeEach((to) => {
|
||||
if (!window.localStorage[TOKEN] && !WhiteList.includes(to.name)) {
|
||||
return {
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.path // redirect是指登录之后可以跳回到redirect指定的页面
|
||||
},
|
||||
replace: true
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- 在main.js中引入permission
|
||||
|
||||
```js
|
||||
// 权限控制
|
||||
import './permission'
|
||||
```
|
||||
|
||||
### css
|
||||
|
||||
- css预处理器
|
||||
|
||||
由于element-plus使用sass开发,所以本项目我们也使用sass,先安装sass
|
||||
|
||||
```powershell
|
||||
npm install -D sass
|
||||
```
|
||||
|
||||
使用sass
|
||||
|
||||
```html
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
```
|
||||
|
||||
- autoprefixer自动处理css3浏览器前缀
|
||||
|
||||
安装autoprefixer
|
||||
|
||||
> 不需要安装postcss,vite内部支持
|
||||
|
||||
```powershell
|
||||
npm install autoprefixer -D
|
||||
```
|
||||
|
||||
根目录创建postcss.config.js
|
||||
|
||||
```js
|
||||
// postcss.config.js
|
||||
module.exports = {
|
||||
plugins: {
|
||||
// 兼容浏览器,添加前缀
|
||||
'autoprefixer': {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
package.json中配置浏览器版本
|
||||
|
||||
```js
|
||||
//package.json
|
||||
{
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
最终的项目结构如下
|
||||
|
||||
> 没有后缀的,代表是一个文件夹
|
||||
|
||||
```powershell
|
||||
├─node_modules -----------依赖包
|
||||
├─mock -------------------mock接口
|
||||
├─public -----------------静态文件
|
||||
├─index.html--------------主页面
|
||||
├─src---------------------核心文件目录(我们开发的代码都在src目录)
|
||||
| ├─api------------------接口模块
|
||||
| ├─assets---------------静态资源(图片,字体,css,js等)
|
||||
| ├─components-----------公共组件
|
||||
| ├─router---------------路由配置
|
||||
| | ├─index.js----------路由主文件
|
||||
| | ├─modules-----------路由模块
|
||||
| ├─store----------------状态管理
|
||||
| | ├─index.js----------状态主文件
|
||||
| | ├─modules-----------状态模块
|
||||
| ├─utils----------------工具函数
|
||||
| | ├─request.js--------axios封装函数
|
||||
| ├─views----------------页面
|
||||
| ├─App.vue--------------根组件
|
||||
| ├─main.js--------------入口文件
|
||||
├─package.json------------项目基本信息和依赖包信息
|
||||
├─postcss.config.js-------postcss配置文件
|
||||
├─vite.config.js----------打包配置文件
|
||||
```
|
||||
|
||||
## 登录
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user