在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 判断浏览器类型及版本
Feb 21 Javascript
jQuery UI AutoComplete 自动完成使用小记
Aug 21 Javascript
js 自定义个性下拉选择框示例
Aug 20 Javascript
两个多选select(multiple左右)添加、删除选项和取值实例
May 12 Javascript
JavaScript字符串对象toUpperCase方法入门实例(用于把字母转换为大写)
Oct 17 Javascript
javascript操作字符串的原生方法
Dec 22 Javascript
JavaScript对数组进行随机重排的方法
Jul 22 Javascript
探索Javascript中this的奥秘
Dec 11 Javascript
angular.js中解决跨域问题的三种方式
Jul 12 Javascript
js对象数组和对象的使用实例详解
Aug 27 Javascript
javascript实现简单打字游戏
Oct 29 Javascript
javascript canvas实现雨滴效果
Jun 09 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
ThinkPHP入库出现两次反斜线转义及数据库类转义的解决方法
2014/11/04 PHP
PHP实现用户登录的案例代码
2018/05/10 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
2019/10/15 PHP
很棒的学习jQuery的12个网站推荐
2011/04/28 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
15条JavaScript最佳实践小结
2013/08/09 Javascript
javascript不可用的问题探究
2013/10/01 Javascript
JavaScript获取flash对象与网上的有所不同
2014/04/21 Javascript
js实现div拖动动画运行轨迹效果代码分享
2015/08/27 Javascript
JavaScript实现数据类型的相互转换
2016/03/06 Javascript
浅析javascript中的Event事件
2016/12/09 Javascript
EditPlus中的正则表达式 实战(4)
2016/12/15 Javascript
解决vue打包之后静态资源图片失效的问题
2018/02/21 Javascript
vue.js的computed,filter,get,set的用法及区别详解
2018/03/08 Javascript
jQuery轮播图实例详解
2018/08/15 jQuery
vue mounted 调用两次的完美解决办法
2018/10/29 Javascript
JavaScript实现更换背景图片
2019/10/18 Javascript
vue-cli创建的项目中的gitHooks原理解析
2020/02/14 Javascript
Element的el-tree控件后台数据结构的生成以及方法的抽取
2020/03/05 Javascript
Python3控制路由器——使用requests重启极路由.py
2016/05/11 Python
python脚本替换指定行实现步骤
2017/07/11 Python
Python tkinter实现的图片移动碰撞动画效果【附源码下载】
2018/01/04 Python
Python 装饰器实现DRY(不重复代码)原则
2018/03/05 Python
numpy 进行数组拼接,分别在行和列上合并的实例
2018/05/08 Python
Django框架的中的setting.py文件说明详解
2018/10/15 Python
python内存动态分配过程详解
2019/07/15 Python
python 将字符串中的数字相加求和的实现
2019/07/18 Python
Python 二叉树的层序建立与三种遍历实现详解
2019/07/29 Python
Python实现微信好友的数据分析
2019/12/16 Python
python UDF 实现对csv批量md5加密操作
2021/01/01 Python
CSS3 3D酷炫立方体变换动画的实现
2019/03/26 HTML / CSS
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
教师评语大全
2014/04/28 职场文书
2014年扶贫帮困工作总结
2014/12/09 职场文书
第一军规观后感
2015/06/12 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书