在Vue项目中使用Typescript的实现


Posted in Javascript onDecember 19, 2019

3.0迟迟没有发布release版本,现阶段在Vue项目中使用Typescript需要花不小的精力在工程的配置上面。主要的工作是webpack对TS,TSX的处理,以及2.x版本下面使用class的形式书写Vue 组件的一些限制和注意事项。

Webpack 配置

配置webpack对TS,TSX的支持,以便于我们在Vue项目中使用Typescript和tsx。

module.exports = {
 entry: './index.vue',
 output: { filename: 'bundle.js' },
 resolve: {
  extensions: ['.ts', '.tsx', '.vue', '.vuex']
 },
 module: {
  rules: [
   { test: /\.vue$/, loader: 'vue-loader',
    options: {
    loaders: {
     ts: 'ts-loader',
     tsx: 'babel-loader!ts-loader',
    }
    }
   },
   { 
    test: /\.ts$/, 
    loader: 'ts-loader', 
    options: { appendTsSuffixTo: [/TS\.vue$/] }    },
   { 
    test: /\.tsx$/, 
    loader: 'babel-loader!ts-loader', 
    options: { 
     appendTsxSuffixTo: [/TSX\.vue$/] 
    } 
   }
  ]
 }
}

在上面的配置中,vue文件中的TS内容将会使用ts-loader处理,而TSX内容将会按照ts-loader-->babel-loader的顺序处理。

appendTsSuffixTo/appendTsxSuffixTo 配置项的意思是说,从vue文件里面分离的script的ts,tsx(取决于<script lang="xxx"></script>)内容将会被加上ts或者tsx的后缀,然后交由ts-loader解析。

我在翻看了ts-loader上关于appendTsxSuffixTo的讨论发现,ts-loader貌似对文件后缀名称有很严格的限定,必须得是ts/tsx后缀,所以得在vue-loader extract <script>中内容后,给其加上ts/tsx的后缀名,这样ts-loader才会去处理这部分的内容。

ts-loader只对tsx做语法类型检查,真正的jsx-->render函数应该交由babel处理。

所以我们还需要使用plugin-transform-vue-jsx来将vue jsx转换为真正的render函数。

// babel.config.json
{
 "presets": ["env"],
 "plugins": ["transform-vue-jsx"]
}

同时,配置TS对tsx的处理为preserve,让其只对tsx做type类型检查。

// tsconfig.json
{
 "compilerOptions": {
 "jsx": "preserve",
}

使用vue cli 4.x

高版本的vue cli如4.x已经集成了vue + typescript的配置。选择use Typescript + Use class-style component syntax选项创建工程。

创建后的工程目录如下:

在Vue项目中使用Typescript的实现

在src根目录下,有两个shims.xx.d.ts的类型声明文件。

// shims.vue.d.ts
declare module "*.vue" {
 import Vue from "vue";
 export default Vue;
}
// shims.jsx.d.ts
import Vue, { VNode } from "vue";
declare global {
 namespace JSX {
  // tslint:disable no-empty-interface
  interface Element extends VNode {}
  // tslint:disable no-empty-interface
  interface ElementClass extends Vue {}
  interface IntrinsicElements {
   [elem: string]: any;
  }
 }
}

它们是作什么用的呢?

shims.vue.d.ts给所有.vue文件导出的模块声明了类型为Vue,它可以帮助IDE判断.vue文件的类型。

shims.jsx.d.ts 为 JSX 语法的全局命名空间,这是因为基于值的元素会简单的在它所在的作用域里按标识符查找。当在 tsconfig 内开启了 jsx 语法支持后,其会自动识别对应的 .tsx 结尾的文件,(也就是Vue 单文件组件中<script lang="tsx"></script>的部分)可参考

官网 tsx

基本用法

在vue 2.x中使用class的方式书写vue组件需要依靠vue-property-decorator来对vue class做转换。

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
export default class extends Vue {
 @Prop({ default: 'default msg'}) private msg!: string;
 name!: string;
 show() {
  console.log("this.name", this.name);
 }
}
</script>

导出的class是经过Vue.extend之后的VueComponent函数(理论上class就是一个Function)。

其最后的结果就像我们使用Vue.extend来扩展一个Vue组件一样。

// 创建构造器
var Profile = Vue.extend({
 template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
 data: function () {
  return {
   firstName: 'Walter',
   lastName: 'White',
   alias: 'Heisenberg'
  }
 }
})

export default {
  components: {
    Profile 
  }
}

注意上面的Profile组件并不是和我们平时一样写的Vue组件是一个plain object配置对象,它其实是一个VueComponent函数。

父组件实例化子组件的时候,会对传入的vue object 进行扩展,使用Vux.extend转换为组件函数。
如果components中的值本身是一个函数,就会省略这一步。这一点, 从Vue 源码中可以看出。

if (isObject(Ctor)) {
  Ctor = baseCtor.extend(Ctor)
 }

上面的Ctor就是在components中传入的组件,对应于上面导出的Profile组件。

使用vuex

使用vuex-class中的装饰器来对类的属性做注解。

import Vue from 'vue'import Component from 'vue-class-component'import {
 State,
 Getter,
 Action,
 Mutation,
 namespace
} from 'vuex-class'

const someModule = namespace('path/to/module')

@Component
export class MyComp extends Vue {
 @State('foo') stateFoo
 @State(state => state.bar) stateBar
 @Getter('foo') getterFoo
 @Action('foo') actionFoo
 @Mutation('foo') mutationFoo
 @someModule.Getter('foo') moduleGetterFoo

 // If the argument is omitted, use the property name
 // for each state/getter/action/mutation type
 @State foo
 @Getter bar
 @Action baz
 @Mutation qux

 created () {
  this.stateFoo // -> store.state.foo
  this.stateBar // -> store.state.bar
  this.getterFoo // -> store.getters.foo
  this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
  this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
  this.moduleGetterFoo // -> store.getters['path/to/module/foo']
 }
}

mixin

对于mixin,我们使用class的继承很容易实现类似功能。

import Vue from 'vue'
import { Component } from 'vue-property-decorator'
@Component
class DeployMixin extends Vue{
 name: string;
 deploy(){
  // do something
 }
}
@Component
class Index extends DeployMixin{
 constructor(){ 
  super()
 }
 sure(){
  this.deploy()
 }
}

VS code jsx快捷键

设置 VS code中对emmet的支持

"emmet.includeLanguages": {
  "javascript": "html"
}

或者是

"emmet.includeLanguages": {
  "javascript": "javascriptreact"
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript设置FieldSet展开与收缩
May 15 Javascript
javascript document.execCommand() 常用解析
Dec 14 Javascript
javascript获得当前的信息的一些常用命令
Feb 25 Javascript
原生js和jquery实现图片轮播特效
Apr 23 Javascript
jquery实现仿新浪微博评论滚动效果
Aug 06 Javascript
JS实现新浪微博效果带遮罩层的弹出框代码
Oct 12 Javascript
纯js实现手风琴效果
Apr 17 Javascript
JQuery控制DIV的选取实现方法
Sep 18 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
Jun 11 jQuery
swiper在vue项目中loop循环轮播失效的解决方法
Sep 15 Javascript
简单了解前端渐进式框架VUE
Jul 20 Javascript
浅谈JavaScript中的“!!”作用
Aug 03 Javascript
JS数据类型STRING使用实例解析
Dec 18 #Javascript
JS精确判断数据类型代码实例
Dec 18 #Javascript
使用webpack/gulp构建TypeScript项目的方法示例
Dec 18 #Javascript
小程序简单两栏瀑布流效果的实现
Dec 18 #Javascript
js数据类型转换与流程控制操作实例分析
Dec 18 #Javascript
vue不操作dom实现图片轮播的示例代码
Dec 18 #Javascript
使用JS来动态操作css的几种方法
Dec 18 #Javascript
You might like
PHP输出控制功能在简繁体转换中的应用
2006/10/09 PHP
php $_ENV为空的原因分析
2009/06/01 PHP
PHP中VC6、VC9、TS、NTS版本的区别与用法详解
2013/10/26 PHP
nicejforms——美化表单不用愁
2007/02/20 Javascript
十分钟打造AutoComplete自动完成效果代码
2009/12/26 Javascript
分享8款优秀的 jQuery 加载动画和进度条插件
2012/10/24 Javascript
JavaScript中创建对象和继承示例解读
2014/02/12 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
2014/04/04 Javascript
使用原生js封装webapp滑动效果(惯性滑动、滑动回弹)
2014/05/06 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
CSS图片响应式 垂直水平居中
2015/08/14 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
BootStrapValidator校验方式
2016/12/19 Javascript
Javascript 实现匿名递归的实例代码
2017/05/25 Javascript
javascript 缓冲运动框架的实现
2017/09/29 Javascript
用vue封装插件并发布到npm的方法步骤
2017/10/18 Javascript
vue项目中axios请求网络接口封装的示例代码
2018/12/18 Javascript
iview的table组件自带的过滤器实现
2019/07/12 Javascript
[00:15]天涯墨客终极技能展示
2018/08/25 DOTA
Python函数学习笔记
2008/10/07 Python
python显示生日是星期几的方法
2015/05/27 Python
Python3实现并发检验代理池地址的方法
2016/09/18 Python
python从list列表中选出一个数和其对应的坐标方法
2019/07/20 Python
python银行系统实现源码
2019/10/25 Python
Python 实现自动登录+点击+滑动验证功能
2020/06/10 Python
HTML5的Video标签有部分MP4无法播放的问题解析(多图)
2017/08/18 HTML / CSS
意大利买卖二手奢侈品网站:LAMPOO
2020/06/03 全球购物
优秀员工自荐书范文
2013/12/08 职场文书
聚美优品陈欧广告词
2014/03/14 职场文书
幽默自我介绍演讲稿
2014/08/21 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书
办公用品管理制度
2015/08/04 职场文书
《社戏》教学反思
2016/02/22 职场文书
2016年少先队活动总结
2016/04/06 职场文书
Python简易开发之制作计算器
2022/04/28 Python
Tomcat安装使用及部署Web项目的3种方法汇总
2022/08/14 Servers