Vue3 前端开发时,需要api请求模拟和数据模拟,我将在接下来的时间写Mock模拟和json-server模拟。两种比较流行的模式,现在先介绍mock模式。
Mock.js是一个轻量级的前端数据模拟工具,可以快速生成随机数据,支持自定义数据类型和规则等功能。我们可以使用NPM来进行安装。
在命令行中执行以下命令:
npm install mockjs
yarn add mockjs -D
在Vue项目中使用Mock.js需要先引入相关的包,并在项目中进行相应的配置。我们可以先在Vue项目中创建一个 mock 文件夹,并在该文件夹下新建index.ts文件。
在index.ts文件(src/mock/index.ts)中编写以下代码:
import Mock from 'mockjs'
// 设置拦截Ajax请求的响应时间,模拟网络延迟
Mock.setup({
timeout: '200-600'
})
// Mock数据示例
Mock.mock(baseUrl + '/api/getList', 'get', {
'list|10-20': [{
'id|+1': 1,
'title': '@ctitle(10, 20)',
'image': '@image('200x100', '#50B347', 'Hello')',
'datetime': '@datetime()',
'author': '@cname()',
'description': '@ctitle(30, 100)'
}]
})
export default Mock
以上示例代码表示:当访问/api/getList接口时,Mock.js会返回一个长度在10-20之间的数组,数组中每一项都包含id、title、image、datetime、author和description属性,并使用@ctitle、@image、@datetime和@cname等方法生成随机数据。
创建http请求对象
src/utils/request.ts
import axIOS from 'axios'
const service = axios.create({
baseURL: '/ceshi',
withCredentials: false,
timeout: 60000
})
// 请求拦截器
service.interceptors.request.use(config => {
// ...统一修改请求头
return config
}, error => {
// ...网络错误
Promise.reject(error)
})
// 响应拦截
service.interceptors.response.use(response => {
return response.data
}, e => {
return Promise.reject(e)
})
export default service
创建视图
src/views/MockView.vue
<template>
<div>
<ul>
<li v-for="item in list" :key="item.id">
<h5>
{{ item.tip }}? {{ item.content }}
</h5>
</li>
</ul>
</div>
<el-table :data="tableList" style="width: 100%">
<el-table-column prop="id" label="ID" width="30" />
<el-table-column prop="name" label="姓名" width="120" />
<el-table-column prop="age" label="年龄" width="80" />
<el-table-column prop="date" label="日期" width="180" />
<el-table-column prop="emAIl" label="邮箱" width="280" />
<el-table-column prop="city" label="城市" width="180" />
</el-table>
<el-table :data="AuthorList" style="width: 100%">
<el-table-column prop="id" label="ID" width="50" />
<el-table-column prop="author" label="作者" width="120" />
<el-table-column prop="title" label="标题" width="80" />
<el-table-column prop="datetime" label="时间" width="180" />
<el-table-column label="图片" width="180">
<template #default="scope">
<el-image :src="scope.row.image"></el-image>
</template>
</el-table-column>
<el-table-column prop="description" label="说明" width="180" />
<el-table-column fixed="right" label="Operations" width="120">
<template #default>
<el-button link type="primary" size="small" @click="fun_del">Detail</el-button>
<el-button link type="primary" size="small" @click="fun_edit">Edit</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import request from '@/utils/request'
type TArticle = {
id: number,
tip: string,
content: string,
};
interface Article {
id: number,
tip: string,
content: string,
};
let list = ref<Array<TArticle>>([]);
const tableList = ref([])
const AuthorList = ref([])
onMounted(() => {
/** */
getList()
.then((res) => {
AuthorList.value = res.list;
console.log(res);
});
getDetail(1)
.then((res) => {
console.log(res);
tableList.value = res.data;
})
.catch((e) => {
console.error(e)
})
})
const fun_del = (data: any) => {
console.log(data);
}
const fun_edit = (data: any) => {
console.log(data);
}
const fun_add = (data: any) => {
console.log(data);
}
const getList = async () => {
return request({
url: '/api/getList',
method: 'get'
})
}
function getArticles() {
return request({
url: '/api/article',
method: 'get'
})
}
function selectA(val: any) {
return request({
url: '/api/selectArticle',
method: 'get',
data: {
val
}
})
}
const getDetail = async (id: Number) => {
const ret = await request({
url: '/api/getDetail',
method: 'post',
data: {
ID: id,
}
})
return ret;
}
</script>
路由 src/router/index.ts 代码
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
// 页面组件通过import引入,如果使用懒加载方式则无需在此通过import引入
// import HomeView from '../views/HomeView.vue'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
//createWebHashHistory(), // history 模式则使用 createWebHistory()
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
// 组件引用方式有两种,只需选择一种方式即可
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// 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: () => import('../views/AboutView.vue')
},
{
path: '/mock',
name: 'mock',
component: () => import('../views/MockView.vue')
}
]
})
修改src/main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//import Mock from './mock' // 引入mock数据
import "./mock/index.ts"
const app = createApp(App)
app.use(router)
//整体引入
app.use(ElementPlus, { size: 'small', zIndex: 3000 })
app.mount('#app')
修改 App.vue 文件
<template>
<div class="wrapper">
<nav>
<router-link to="/">home</router-link> |
<router-link to="/mock">mock</router-link> |
<router-link to="/about">About</router-link>
</nav>
</div>
<Router-view />
<!-- <HelloWorld msg="You did it!" /> -->
</template>
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
</script>
<style lang="less" scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
ElementPlusg官网参考:
https://element-plus.org/zh-CN/guide/quickstart.html
推荐#
自动导入
首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
Vite#
然后把下列代码插入到你的 Vite 的配置文件中
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
效果图
目录结构
package.json 文件
{
"name": "vue3-vite-ts",
"private": true,
"version": "0.0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"lint": "eslint src/**/*.{js,jsx,vue,ts,tsx} --fix"
},
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"axios": "^1.5.0",
"babel-eslint": "^10.1.0",
"element-plus": "^2.4.2",
"http": "^0.0.1-security",
"js-cookie": "^3.0.5",
"path": "^0.12.7",
"pinia": "^2.1.6",
"pinia-plugin-persistedstate": "^3.2.0",
"pinia-use-persist": "^0.0.21",
"qs": "^6.11.2",
"vite-plugin-svg-icons": "^2.0.1",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@types/js-cookie": "^3.0.4",
"@types/mockjs": "^1.0.9",
"@types/node": "^20.6.3",
"@types/nprogress": "^0.2.0",
"@types/qs": "^6.9.9",
"@typescript-eslint/eslint-plugin": "^6.7.2",
"@typescript-eslint/parser": "^6.7.2",
"@vitejs/plugin-vue": "^4.2.3",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"fast-glob": "^3.3.1",
"fs": "^0.0.1-security",
"less": "^4.2.0",
"less-loader": "^11.1.3",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"sass": "^1.68.0",
"typescript": "^5.0.2",
"unplugin-auto-import": "^0.16.7",
"unplugin-vue-components": "^0.25.2",
"vite": "^4.4.5",
"vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^1.8.5"
},
"rules": {
"vue/multi-word-component-names": "off"
}
}