目录
一、ts语法练习
1.1、安装
1.2、语法
二、vue3+ts
2.1、项目创建
2.1.1、项目创建(建议node版本在16.及以上)
2.1.2、下载路由、axios
2.1.3、引入element-plus
2.1.4、报错解决
(1)文件路径下有红色波浪
(2)组件名称下有红色波浪
(3)引入模块下有红色波浪
2.2、导航栏模块
2.3、表格模块
2.4、事件与弹窗显示
2.5、Icon组件封装
一、ts语法练习
1.1、安装
安装:npm install -g typescript
检验:tsc -v
编译为js文件:tsc demo.ts(文件名)
1.2、语法
参考博客:TypeScript 语法_typescript 往后加n天-CSDN博客
二、vue3+ts
2.1、项目创建
2.1.1、项目创建(建议node版本在16.及以上)
npm init vite
初始化时填写项目包名称xxx,选择“Vue”、“TypeScript”
cd xxx后npm install,然后npm run dev,即可打开新项目,看到首页
2.1.2、下载路由、axios
npm i vue-router -S
npm i axios -S
在src包下创建router文件夹,并在文件夹下创建index.ts文件;
在src包下创建http/api文件夹,并在文件夹下创建http.ts文件;
(1)、router下的index.ts代码
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
// interface IRouterList {
// name?: string,
// path: string,
// component?: any,
// [propname: string]: any
// }
// RouteRecordRaw 内置的类型接口,也可以使用自定义的类型约束: IRouterList[]或者Array<IRouterList>
const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'home',
component: () => import('../components/layout/index.vue'),
children: [{
path: '/index',
name: 'index',
component: () => import('../views/index/index.vue')
},
{
path: '/monitor',
name: 'monitor',
component: () => import('../views/monitor/index.vue')
},
]
}
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router;
在main.ts里引入:
import router from './router'
createApp(App).use(router).mount('#app')
(2)、api下的http.ts代码
import axios, { type AxiosRequestConfig, AxiosResponse } from 'axios';
axios.defaults.baseURL = `http://localhost:3000`;
// AxiosRequestConfig:请求参数类型
// 请求拦截器
axios.interceptors.request.use((config: AxiosRequestConfig | any) => config);
// 响应拦截器
axios.interceptors.response.use((res: AxiosResponse) => {
return res
}, err => {
return Promise.reject(err)
});
// export default axios;
// 如何去定义传入参数类型或返回的类型 unknown:未知类型
interface IHttp {
request<T>(method: string, url: string, params?: unknown): Promise<T>;
}
const http: IHttp = {
request: (method, url, params) =>
axios({
method: method,
url: url,
data: params
})
}
export default http;
页面调用接口:
<script lang="ts" setup>
import axios from '../../api/http'
import { onMounted, ref } from 'vue'
interface ItableData {
date: string,
title: string,
user: string,
id: number,
check: boolean
}
const tableData = ref<ItableData[]>([]);
onMounted(async () => {
let { data } = await axios.request<{ data: ItableData[] }>('get', '/data/query');
tableData.value = data
})
</script>
不封装的话,只能一个一个写:
import axios from 'axios'
onMounted(async () => {
axios.get('http://localhost:3000/data/query').then(res => {
console.log(res);
})
})
2.1.3、引入element-plus
官网:Overview 组件总览 | Element Plus
安装:npm install element-plus --save
引入:(建议按需引入)https://element-plus.org/zh-CN/guide/quickstart.html
unplugin-auto-import可以不要
注意:如果下载成功,可以在项目的package.json文件里看到对应的版本号
2.1.4、报错解决
(1)文件路径下有红色波浪
问题描述:
component: () => import('../views/index/index.vue');//(路径下面有红色波浪线)
解决方法:
在项目的vite-env.d.ts文件中加入以下代码即可
declare module '*.vue' {
import { DefineComponent } from "vue"
const component: DefineComponent<{}, {}, any>
export default component
}
(2)组件名称下有红色波浪
问题描述:
import Icons from "../common/icons.vue"; // (Icons下面有红色波浪线)
解决方法:
Vetur(语句高亮插件)暂不支持ts,可以禁用,换成Vue Language Features(Volar)或Vue - Official插件
(3)引入模块下有红色波浪
问题:import { ref } from "vue"; //(vue下面有红色波浪线)
解决方法:
在项目的tsconfig.json文件中的moduleResolution属性值改为"node"
2.2、导航栏模块
注意: <el-menu>里面有了router属性才能跳转到对应的页面
//====================================导航栏页面====================
<template>
<el-aside width="200px">
<!-- <el-menu>里面有了router才能跳转到对应的页面 -->
<el-menu default-active="2" class="el-menu-vertical-demo" router>
<el-menu-item :index="v.url" v-for="v in menuItems" :key="v.url">
<!-- <el-icon><component :is="v.icon"></component></el-icon> -->
<el-icon><Icons :icon="v.icon" /></el-icon>
<span>{{ v.name }}</span>
</el-menu-item>
</el-menu>
</el-aside>
</template>
<script lang="ts" setup>
import Icons from "../common/icons.vue";
import { useMenu } from "./navMenu";
const { menuItems } = useMenu();
</script>
//====================================navMenu.ts页面====================
import {
Document,
Menu as IconMenu,
Location,
Setting,
} from "@element-plus/icons-vue";
import { INavMenu } from '../../models';//INavMenu 是封装的接口
export const useMenu = () => {
const menuItems: INavMenu[] = [
{ name: "首页", url: "/index", icon: Document },
{ name: "监督活动", url: "/monitor", icon: Location },
{ name: "订单管理", url: "/order", icon: Setting },
{ name: "统计分析", url: "/census", icon: Setting },
];
return {
menuItems
}
}
//====================================models文件夹里的index.ts页面====================
export interface INavMenu {//定义接口,作限制类型
name: string,
url: string,
icon?: any,
}
2.3、表格模块
下面模拟了表格自带的筛选功能、文字处理功能、文字过长展示功能以及获取接口数据展示等。
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="Date" :filters="dateHandler" :filter-method="filterHandler" />
<el-table-column prop="title" label="title" />
<el-table-column prop="user" label="user" show-overflow-tooltip />
<el-table-column prop="id" label="id" />
<el-table-column prop="check" label="check">
<template #default="{ row }">
<el-tag :type="row.check ? 'success' : 'danger'">{{ row.check ? '已完成' : '未完成' }}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
<script lang="ts" setup>
import axios from '../../api/http';
import { onMounted, ref, computed } from 'vue';
interface ItableData {
date: string,
title: string,
user: string,
id: number,
check: boolean
}
const tableData = ref<ItableData[]>([{
date: '2024-5-20',
title: '吧就',
user: 'dcsavvvvvvvvvvvv',
id: 1,
check: true
},
{
date: '2024-5-21',
title: '的繁荣的',
user: '超出隐藏超出隐藏超出隐藏超出隐藏超出隐藏超出隐藏超出隐藏超出隐藏',
id: 2,
check: false
}]);
onMounted(async () => {
let { data } = await axios.request<{ data: ItableData[] }>('get', '/data/query');
tableData.value = data
})
// 获取日期-动态数据(computed处理)
const dateHandler = computed(() => {
// return tableData.value.map(item => ({ text: item.date, value: item.date }))
const map = new Map();
for (let item of tableData.value) {
if (!map.has(item.date)) {
map.set(item.date, item)
}
}
let data = [...map.values()];//map去重
return data.map(item => ({ text: item.date, value: item.date }))
})
// 筛选方法
const filterHandler = (
value: string,
row: ItableData,
) => {
return row.date === value
}
</script>
2.4、事件与弹窗显示
<template>
<el-button type="success" @click="setData('add', null)">添加</el-button>
<el-button type="success" @click="setData('edit', row)">编辑</el-button>
<!-- 弹出框 -->
<el-dialog v-model="dialogFormVisible" title="操作数据" width="500">
<el-form :model="form">
<el-form-item label="Promotion name">
<el-input v-model="form.name" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">
提交
</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
let dialogFormVisible = ref<boolean>(false);//弹框状态
let form = ref({});//弹框数据
// 添加或编辑方法
function setData(type: string, row: ItableData | null) {
dialogFormVisible.value = true;//弹框显示
type == 'add' ? form.value = {} : form.value = { ...row }
}
</script>
2.5、Icon组件封装
//==============================主页面============================
<template>
<el-icon><Icons :icon="v.icon" /></el-icon>
</template>
<script lang="ts" setup>
import Icons from "../common/icons.vue";
</script>
//==============================icons.vue页面============================
<template>
<component :is="icon"></component>
</template>
<script lang="ts" setup>
import { defineProps } from "vue";
const { icon } = defineProps<{ icon: any }>();
</script>