搜索

📄 文章 📚 合集
热门搜索
🐘 PHP ⚡ Laravel 🎨 Vue.js ⚛️ React 📦 Yii 📘 JavaScript 🗄️ MySQL 🐳 Docker
返回合集

[板块3:Vue 3 + Element Plus 后台(含认证+核心功能)] - 07 -引入 TypeScript 支持

代码示例
# TypeScript 引入记录

## 1. 引入原因

### 1.1 为什么引入 TypeScript

| 原因 | 说明 |
|------|------|
| **类型安全** | 在编码阶段发现类型错误,减少运行时 bug |
| **IDE 智能提示** | 输入 `user.` 自动提示属性,提升开发效率 |
| **代码可读性** | 类型定义即文档,代码意图更清晰 |
| **重构安全** | 修改接口定义后,所有使用处自动报错 |
| **长期维护** | 项目持续迭代,类型系统有助于后期维护 |


---

## 2. 安装 TypeScript

### 2.1 执行命令

npm install -D typescript @types/node

### 2.2 说明

| 包 | 作用 |
|---|------|
| `typescript` | TypeScript 编译器 |
| `@types/node` | Node.js 类型定义 |

---

## 3. 创建 TypeScript 配置文件

### 3.1 文件路径

`tsconfig.json`(项目根目录)

### 3.2 完整代码

```json
{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": false,
        "jsx": "preserve",
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "allowJs": true,
        "checkJs": false,
        "types": ["vite/client", "element-plus/global"]
    },
    "include": ["resources/js/**/*.ts", "resources/js/**/*.d.ts", "resources/js/**/*.vue"],
    "exclude": ["node_modules", "public"]
}
```

### 3.3 配置说明

| 配置项 | 作用 |
|--------|------|
| `"strict": false` | 降低严格程度,减少报错,后续可逐步开启 |
| `"allowJs": true` | 允许混合使用 `.js` 和 `.ts` 文件 |
| `"checkJs": false` | 不检查 `.js` 文件 |
| `"jsx": "preserve"` | 保留 JSX 语法,由 Vite 处理 |
| `"types": [...]` | 引入 Vite 和 Element Plus 类型定义 |

---

## 4. 添加类型声明文件

### 4.1 文件路径

`resources/js/admin/vite-env.d.ts`

### 4.2 完整代码

```typescript
/// <reference types="vite/client" />

declare module '*.vue' {
    import type { DefineComponent } from 'vue';
    const component: DefineComponent<{}, {}, any>;
    export default component;
}
```

### 4.3 说明

| 代码 | 作用 |
|------|------|
| `/// <reference types="vite/client" />` | 引入 Vite 客户端类型 |
| `declare module '*.vue'` | 声明 `.vue` 文件的模块类型 |

---

## 5. 修改 Vite 配置

### 5.1 文件路径

`vite.config.js`

### 5.2 完整代码

```javascript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
                'resources/js/admin/main.ts',  // 改为 .ts
            ],
            refresh: true,
        }),
        vue({
            script: {
                defineModel: true,
                propsDestructure: true,
            },
        }),
    ],
});
```

### 5.3 说明

将后台入口文件从 `main.js` 改为 `main.ts`,Vite 会自动识别 TypeScript。

---

## 6. 重命名入口文件

### 6.1 执行命令

mv resources/js/admin/main.js resources/js/admin/main.ts

### 6.2 修改 main.ts 内容

**文件路径**:`resources/js/admin/main.ts`

```typescript
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
import App from './App.vue';
import router from './router';

const app = createApp(App);

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component);
}

app.use(ElementPlus);
app.use(router);

app.mount('#app');
```

---

## 7. 修改 Login.vue 支持 TypeScript

### 7.1 文件路径

`resources/js/admin/views/Login.vue`

### 7.2 关键修改

将 `<script setup>` 改为 `<script setup>`,并添加类型定义。

### 7.3 完整代码

<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { User, Lock } from '@element-plus/icons-vue';

// 定义表单数据类型
interface LoginForm {
    email: string;
    password: string;
}

const formRef = ref();
const loading = ref<boolean>(false);

const form = reactive<LoginForm>({
    email: '',
    password: '',
});

const rules = {
    email: [
        { required: true, message: '请输入邮箱', trigger: 'blur' },
        { type: 'email' as const, message: '邮箱格式不正确', trigger: 'blur' },
    ],
    password: [
        { required: true, message: '请输入密码', trigger: 'blur' },
        { min: 6, message: '密码至少6位', trigger: 'blur' },
    ],
};

const handleLogin = () => {
    if (!formRef.value) return;

    formRef.value.validate(async (valid: boolean) => {
        if (!valid) return;

        loading.value = true;
        
        setTimeout(() => {
            loading.value = false;
            ElMessage.warning('后端API开发中,暂不支持登录');
        }, 500);
    });
};
</script>

### 7.4 代码说明

| 代码 | 作用 |
|------|------|
| `interface LoginForm` | 定义表单数据类型 |
| `loading.value = ref<boolean>(false)` | 声明 loading 为布尔类型 |
| `form = reactive<LoginForm>({...})` | 声明 form 符合 LoginForm 接口 |
| `valid: boolean` | 声明验证回调参数类型 |
| `as const` | 将字符串字面量类型收窄为具体值 |

---

## 8. 修改后台视图

### 8.1 文件路径

`resources/views/admin.blade.php`

### 8.2 修改

将:

@vite('resources/js/admin/main.js')

改为:

@vite('resources/js/admin/main.ts')

---

## 9. 编译验证

### 9.1 执行命令

```bash
npm run build
```

### 9.2 预期结果

编译成功,无报错,生成 `public/build/assets/` 目录。

## 10. TypeScript 带来的好处(示例对比)

### 10.1 JavaScript 写法(之前)

const form = reactive({
    email: '',
    password: '',
});
// 写错属性名不会报错
console.log(form.emial); // undefined

### 10.2 TypeScript 写法(之后)

interface LoginForm {
    email: string;
    password: string;
}

const form = reactive<LoginForm>({
    email: '',
    password: '',
});
// 写错属性名会报错
console.log(form.emial); // ❌ 类型“LoginForm”上不存在属性“emial”

🧸 adorable code

专注 PHP、JavaScript、Laravel、Vue.js、React、Yii 全栈开发。记录技术探索过程中的灵感与经验,分享工程实践洞见。

hello@adorablecode.com