在 Vue 中使用 Typescript

前言

  恕我直言,用 Typescript 写 Vue 真的很难受,Vue 对 ts 的支持一般,如非万不得已还是别在 Vue 里边用吧,不过听说 Vue3 会增强对 ts 的支持,正式登场之前还是期待一下吧嘻嘻。

  本篇不会过多讲述 ts 语法,着重记录下 在 Vue 中使用 ts 的方法以及踩坑经过。

  如果是使用 Vue Cli2 搭建的项目,要注意 webpack 版本可能与 ts-loader 版本不匹配,可以降低 ts-loader 版本到 3.0+ 或者 将 webpack升级到 4.0+ (本篇所用版本 [email protected] + [email protected])

主要步骤

  1. 先要让 vue 项目可以识别 .ts 文件。安装关键依赖 npm i typescript ts-loader -D

  2. 在 webpack.base.config.js 中添加 ts-loader

//resolve.extensions 里面加上.ts 后缀 之后引入.ts的时候可以不写后缀
{
  test: /\.tsx?$/,
  loader: ‘ts-loader‘,
  exclude: /node_modules/,
  options: {
    appendTsSuffixTo: [/\.vue$/], //关键
  }
}

  3. 在根目录建tsconfig.json文件 下面的配置仅供参考

{
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ],
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "allowJs": true,
    "module": "esnext",
    "target": "es5",
    "moduleResolution": "node",
    "isolatedModules": true,
    "lib": [
      "dom",
      "es5",
      "es2015.promise"
    ],
    "sourceMap": true,
    "pretty": true
  }
}

  4. 接着需要确保在 vue 中可以正常使用 ts 。安装 vue-class-component(为vue组件提供修饰器) vue-property-decorator(更多的结合vue特性的修饰器) [ tslint tslint-loader tslint-config-standard(可选 约束.ts/.tsx代码格式)],这样就可以在 vue 文件中使用诸如 @Component、@Prop等装饰器了。注意:.vue 文件中的 script 标签要加上 lang="ts"。关于 装饰器的使用可以参看下这位大哥的文章:https://segmentfault.com/a/1190000019906321

<template>
    <div class="count-down" v-html="countDown(endDate)">
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Emit } from "vue-property-decorator"
import moment from ‘moment‘

@Component
export default class CountDown extends Vue {
    @Prop() endDate!: string
    // 变量后加!是非空断言

    now: any = moment()
    mounted() {
        setInterval((): void =>{
            this.now = moment()
        },1000)
    }
    destroyed() {

    }
    get countDown(): object{
        return function(endDate: any): string {
            let m1: any = this.now
            let m2: any = moment(endDate)
            let du: any = moment.duration(m2 - m1, ‘ms‘)
            let hours: number = du.get(‘hours‘)
            let mins: number = du.get(‘minutes‘)
            let ss: number = du.get(‘seconds‘)
            if(hours <= 0 && mins <= 0 && ss <= 0) {
                // this.$emit(‘timeout‘)
                this.timeout()
                return "今日已结束"
            }else {
                return `${this.PrefixInteger(hours,2)} <span style="font-size: 16px;">小时</span> ${this.PrefixInteger(mins,2)} <span style="font-size: 16px;">分钟</span><span style="color: #F56C6C;"> ${this.PrefixInteger(ss,2)} </span><span style="font-size: 16px;">秒</span>`
            }
        }
    }

    @Emit()
    timeout(){}

    //数字前补 0
    // num传入的数字,n需要的字符长度
    PrefixInteger(num: number, n: number): string {
        return (Array(n).join(‘0‘) + num).slice(-n)
    }
}
</script>

<style lang="less" scoped>
//...
</style>

  5. 将main.js 变成 main.ts 并且在 webpack.base.conf.js 修改入口为main.ts,这一步至关重要。

  6. 在 src 目录下新建文件 shims-vue.d.ts ,告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理,注意 在代码中导入 *.vue 文件的时候,需要写上 .vue 后缀,这里可以参考官网说明:增强类型以配合插件使用

declare module "*.vue" {
    import Vue from "vue";
    export default Vue;
}

踩坑记录

  1. 报错如下,报错原因一是没有将入口文件改成 ts,二是 webpack.base.conf.js 中引入 ts-loader 错误,没有加上 options: { appendTsSuffixTo: [/\.vue$/], }

Module build failed: Error: Could not find source file: ‘XXX/src/App.vue‘.

  2. 全局属性报错 如 Vue.prototype.$msg = XXX,需要将全局属性在 .d.ts 文件中声明

import Vue from "vue";
import { AxiosInstance } from "axios";
import { ElMessage } from "element-ui/types/message";

declare module "*.vue" {
    export default Vue;
}

declare module ‘vue/types/vue‘ {
    interface Vue {
        $http: AxiosInstance,
        $message: ElMessage
    }
}

  3. 使用上面这种声明全局属性的方式又会带来新的问题,报错 import App from ‘./App.vue‘处,找不到 App.vue 这个模块,虽然不影响编译,但是这红色的波浪线就像老鼠屎,看着那叫一个难受呀。解决方法:将 shims-vue.d.ts 文件一分为二,将全局属性声明和 Vue 的声明分离;在 shims-vue.d.ts 文件同级目录下新建 vue.d.ts(名字不一定叫 vue,如 xxx.d.ts 也可以);关键是要将以下代码放在单独的 .d.ts 文件中

declare module ‘*.vue‘ {
  import Vue from ‘vue‘
  export default Vue
}

原文地址:https://www.cnblogs.com/eightFlying/p/vue_typescript.html

时间: 2024-11-09 06:03:23

在 Vue 中使用 Typescript的相关文章

如何在Vue项目中使用Typescript

0.前言 本快速入门指南将会教你如何在Vue项目中使用TypeScript进行开发.本指南非常灵活,它可以将TypeScript集成到现有的Vue项目中任何一个阶段. 1.初始化项目 首先,创建一个新的项目目录. mkdir typescript-vue-tutorial cd typescript-vue-tutorial 接着,在目录中创建如下目录结构. typescript-vue-tutorial/ ├─ dist/ └─ src/ └─ components/ TypeScript文件

如何在vue中使用ts

注意:此文并不是把vue改为全部替换为ts,而是可以在原来的项目中植入ts文件,目前只是实践阶段,向ts转化过程中的过渡. ts有什么用? 类型检查.直接编译到原生js.引入新的语法糖 为什么用ts? TypeScript的设计目的应该是解决JavaScript的"痛点":弱类型和没有命名空间,导致很难模块化,不适合开发大型程序.另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程. typescript不仅可以约束我们的编码习惯,还能起到注释的作用,当我们看到一函数后我们立马

聊聊 Vue 中 axios 的封装

聊聊 Vue 中 axios 的封装 axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是: Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 作为一个优秀的 HTTP 库,axios 打败了曾经由 Vue 官方团队维护的 vue-resource,获得了 Vue 作者尤小右的大力推荐,成为了 Vue 项目中 HTTP 库的最佳选择. 虽然,axios 是个优秀的 HTTP 库,但是,直接在项目中使用并不是那

在 React 中使用 Typescript

前言 用 Typescript 写 React 可比写 Vue 舒服太多了,React 对 ts 的支持可谓天生搭档,如果要用 ts 重构项目,不像 Vue 对项目破坏性极大,React 可以相对轻松的实现重构. 顺便一提:全局安装的 create-react-app 现已无法再下载完整的 React 项目模版,必须先 npm uninstall -g create-react-app 移除命令 再 npx create-react-app demo 下载模版,参考 create-react-a

理解Vue中的Render渲染函数

VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数.比如如下我想要实现如下html: <div id="container"> <h1> <a href="#"> Hello world! </a> </h1> </div> 我们会如下使用: <!DOCTYPE html> <html

vue中自定义指令

在vue中自定义标签,首先要调用vue中一个directive的方法,具体方法:Vue.direction('指令名称',function(){ }); 例如我们要写一个关于颜色的指令,叫v-colorred: 1 Vue.directive('colorred',function(){ 2 3 this.el.style.color='red'; 4 }); 在html中,我直接用v-colorred指令就可以了,例如: 1 <p v-colorred>1234567890</p>

vue中的vue-cli

在前面的学习过程中我相信你们已经对vue有了一定的了解,现在我们来看一下vue中的vue-cli. 学习这个我们首先需要的是node环境的,如果你的网络环境慢的话建议安装淘宝镜像,在cmd中输入 npm install -g cnpm –registry=https://registry.npm.taobao.org 这个命令行,安装,安装之后检查cnpm的版本 cnpm -v 之后创建项目文件进入项目文件中,在comd中下载vue-cli cnpm install vue-cli -g --s

如何在Vue中建立全局引用或者全局命令

1 一般在vue中,有很多vue组件,这些组件每个都是一个文件.都可能需要引用到到相同模块.我们不想每个文件都import 一次模块. 如果是vue编写的插件我们可以用 Vue.use(...) 2 但是如果想添加一个全局命令,同时又让每个vue的文件都能用到怎么办? 第一步:最好建立一个全局的命令文件例如:directive/directive.js 第二步:利用Vue.directive()建立一个全局命令,并将它暴露出来,例如一个focus 让表单自动聚焦 第三部步:在main.js(入口

better-scroll在vue中的应用

在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 微信 -> 钱包->滴滴出行"体验效果. 什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在 这里 .better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图.picker 等等. 不少同学可能用过 better-scroll,我收到反馈最多