深入理解Vue中的Typescript(四)-vue3项目当中使用Typescript

665 阅读3分钟

0.目录

深入理解Vue中的Typescript(一)-es语法的类属性和装饰器
深入理解Vue中的Typescript(二)-vue_component源码分析和Typescript语法
深入理解Vue中的Typescript(三)-vue2项目当中使用Typescript
深入理解Vue中的Typescript(四)-vue3项目当中使用Typescript

1.概述

Vue3当中放弃了通过vue-class-componentvue-property-decorator来使用Typescript,采用更简单方式与Typescript进行结合,在这里我们把深入理解Vue中的Typescript(三)-vue2项目当中使用Typescript通过Vue3进行实现一遍,这样就能大致知道Vue3中使用Typescript的流程

2.前言

2.1 要做的效果

  • 用户列表页

  • 用户详情页

  • 权限列表页

2.2本次使用工具或包的版本

  • @vue/cli:4.5.8
  • vue:3.0.0
  • vue-router:3.2.0
  • typescript:3.9.3

3.步骤

3.1 通过vue-cli创建项目

vue create hello-ts
Vue CLI v4.5.8
? Please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3 Preview) ([Vue 3] babel, eslint)
> Manually select features   

manually:自定义勾选特性配置,选择完毕之后,才会进入装包

? Please pick a preset: Manually select features
? Check the features needed for your project:
 (*) Choose Vue version
 (*) Babel
>(*) TypeScript
 ( ) Progressive Web App (PWA) Support
 (*) Router
 ( ) Vuex
 ( ) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing  

分别选择: Choose Vue version:选中Vue的版本 TypeScript:Typescript语言写Vue项目 Babel:es6 转 es5 Router:路由 Linter / Formatter:代码格式校验

? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Linter
? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
  2.x
> 3.x (Preview) 

选择Vue 3.x版本

? Use class-style component syntax? (Y/n) n  

输入n,不使用类样式的组件语法

? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) y 

输入y,使用Babel与TypeScript一起用于自动检测的填充

? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n

输入n,使用hash模式的路由模式

? Pick a linter / formatter config:
  ESLint with error prevention only
  ESLint + Airbnb config
> ESLint + Standard config
  ESLint + Prettier
  TSLint (deprecated) 

选择eslint的标准配置

? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Lint on save
 ( ) Lint and fix on commit

在保存文件的时候,校验js和ts

? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files
  In package.json  

保存babel和eslint的配置为单独的文件

? Save this as a preset for future projects? (y/N) n

输入n,不保存为一个预设

3.2 vscode 安装eslint扩展和配置

添加hello-ts项目到vscode的根路径,安装vscode的eslint扩展

键盘按下,'ctrl+shift+p',输入'setting.json',点击'首选项:打开设置(json)'

添加配置:

{
    // eslint扩展的保存的自动修复
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    // 验证预约,默认["javascript", "javascriptreact"],追加"typescript"
    "eslint.validate": [
        "javascript", "javascriptreact", "typescript"
    ]
}

3.3 项目入门main.ts

页面路径: src/App.vue

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

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

3.4 页面根组件App.vue

页面路径: src/App.vue

<template>
  <router-view/>
</template>

3.5 路由配置文件

页面路径:src/router/index.ts

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import Home from '../components/Home.vue'
import Users from '../components/Users.vue'
import Right from '../components/Right.vue'
import UserInfo from '../components/UserInfo.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    redirect: '/users',
    children: [
      { path: '/users', component: Users },
      { path: '/rights', component: Right },
      { path: '/userinfo/:id', component: UserInfo, props: true }
    ]
  }
]

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

export default router

3.6 Home组件

页面路径:src/components/Home.vue

<template>
  <div>
    <!-- 头部区域 -->
    <header class="header">后台管理系统</header>
    <!-- 中间主体区域 -->
    <div class="main">
      <!-- 左侧菜单栏 -->
      <div class="content left">
        <ul>
          <li><router-link to="/users">用户管理</router-link></li>
          <li><router-link to="/rights">权限管理</router-link></li>
        </ul>
      </div>
      <!-- 右侧内容区域 -->
      <div class="content right">
        <div class="main-content"><router-view /></div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({

})
</script>

<style>
html,
body,
#app {
  margin: 0;
  padding: 0px;
  height: 100%;
}
.header {
  height: 50px;
  background-color: #545c64;
  line-height: 50px;
  text-align: center;
  font-size: 24px;
  color: #fff;
}
.footer {
  height: 40px;
  line-height: 40px;
  background-color: #888;
  position: absolute;
  bottom: 0;
  width: 100%;
  text-align: center;
  color: #fff;
}
.main {
  display: flex;
  position: absolute;
  top: 50px;
  bottom: 0px;
  width: 100%;
}
.content {
  flex: 1;
  text-align: center;
  height: 100%;
}
.left {
  flex: 0 0 20%;
  background-color: #545c64;
}
.left a {
  color: white;
  text-decoration: none;
}
.right {
  margin: 5px;
}
.btns {
  width: 100%;
  height: 35px;
  line-height: 35px;
  background-color: #f5f5f5;
  text-align: left;
  padding-left: 10px;
  box-sizing: border-box;
}
button {
  height: 30px;
  background-color: #ecf5ff;
  border: 1px solid lightskyblue;
  font-size: 12px;
  padding: 0 20px;
}
.main-content {
  margin-top: 10px;
}
ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
ul li {
  height: 45px;
  line-height: 45px;
  background-color: #a0a0a0;
  color: #fff;
  cursor: pointer;
  border-bottom: 1px solid #fff;
}

table {
  width: 100%;
  border-collapse: collapse;
}

td,
th {
  border: 1px solid #eee;
  line-height: 35px;
  font-size: 12px;
}

th {
  background-color: #ddd;
}
</style>

3.7 Right组件

页面路径:src/components/Right.vue

<template>
    <div>
        <h3>权限管理区域</h3>
    </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({

})
</script>

3.8 Users组件

页面路径:src/components/Users.vue

<template>
    <div>
        <h3>用户管理区域</h3>
        <table>
            <thead>
            <tr><th>编号</th><th>姓名</th><th>年龄</th><th>操作</th></tr>
            </thead>
            <tbody>
            <tr v-for="item in userlist" :key="item.id">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.age}}</td>
                <td>
                <a href="javascript:;"  @click="goDetail(item.id)">详情</a>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
</template>

<script lang="ts">
import router from '@/router'
import { defineComponent,ref } from "vue";
export default defineComponent({
    setup(){
        const userlist = ref([
            { id: 1, name: '张三', age: 10 },
            { id: 2, name: '李四', age: 20 },
            { id: 3, name: '王五', age: 30 },
            { id: 4, name: '赵六', age: 40 }
        ])
        function goDetail (id: number) {
            router.push('/userinfo/' + id)
        }
        return {
            userlist,
            goDetail
        }
    }
})
</script>

3.9 UserInfo组件

页面路径:src/components/Users.vue

<template>
  <div>
    <h5>用户详情页 --- 用户Id为:{{id}}</h5>
    <button @click="goback()">后退</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import router from '@/router'
export default defineComponent({
    props: {
        id: {type: Number}
    },
    setup(props){
        function goback () {
            router.go(-1)
        }
        return {
            goback
        }
    }
})
</script>

4.结论

对比Vue2当中使用Typescript,Vue3中使用Typescript的特点如下:

  • 结合Typesript更加简单,不需要学习vue-class-componentvue-property-decorator,而采用普通变量函数,天然适应Typescript的类型检查
  • 路径模块,路由配置不变,但是要使用新的函数
  • vue组件需要学习组合式Api,学习通过新的函数来定义变量和计算属性

总体来说Vue3的改进更方便跟Typescript结合,更适合做大型的vue项目