在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 相关文章推荐
showModalDialog 和 showModelessDialog
Jan 22 Javascript
javascript parseInt 函数分析(转)
Mar 21 Javascript
js正确获取元素样式详解
Aug 07 Javascript
JQuery 拾色器插件发布-jquery.icolor.js
Oct 20 Javascript
浅谈关于JavaScript的语言特性分析
Apr 11 Javascript
javascript判断非数字的简单例子
Jul 18 Javascript
jquery实现div拖拽宽度示例代码
Jul 31 Javascript
javascript实现完美拖拽效果
May 06 Javascript
Jquery+Ajax+xml实现中国地区选择三级联动菜单效果(推荐)
Jun 09 jQuery
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
Sep 28 Javascript
vue-resourc发起异步请求的方法
Feb 11 Javascript
javascript利用键盘控制小方块的移动
Apr 20 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面向对象全攻略 (十) final static const关键字的使用
2009/09/30 PHP
PHP导入Excel到MySQL的方法
2011/04/23 PHP
浏览器关闭后,能继续执行的php函数(ignore_user_abort)
2012/08/01 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
2015/12/31 PHP
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
深入剖析浏览器退出之后php还会继续执行么
2016/05/17 PHP
利用jQuery接受和处理xml数据的代码(.net)
2011/03/28 Javascript
40个有创意的jQuery图片、内容滑动及弹出插件收藏集之一
2011/12/31 Javascript
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
js+css实现增加表单可用性之提示文字
2013/06/03 Javascript
js对象转json数组的简单实现案例
2014/02/28 Javascript
js打开windows上的可执行文件示例
2014/05/27 Javascript
基于JS实现PHP的sprintf函数实例
2015/11/14 Javascript
SpringMVC返回json数据的三种方式
2015/12/10 Javascript
ActiveX控件的使用-js实现打印超市小票功能代码详解
2017/11/22 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
2018/09/14 Javascript
微信小程序使用wx.request请求服务器json数据并渲染到页面操作示例
2019/03/30 Javascript
vue 点击展开显示更多(点击收起部分隐藏)
2019/04/09 Javascript
实现高性能javascript的注意事项
2019/05/27 Javascript
Element-UI中关于table表格的那些骚操作(小结)
2019/08/15 Javascript
javascript实现前端input密码输入强度验证
2020/06/24 Javascript
如何HttpServletRequest文件对象并储存
2020/08/14 Javascript
小程序实现录音功能
2020/09/22 Javascript
[42:32]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第二局
2016/02/27 DOTA
python 自动提交和抓取网页
2009/07/13 Python
python实现的udp协议Server和Client代码实例
2014/06/04 Python
Python深入学习之装饰器
2014/08/31 Python
python多线程同步之文件读写控制
2021/02/25 Python
有关HTML5 Video对象的ontimeupdate事件(Chrome上无效)的问题
2013/07/19 HTML / CSS
介绍一下Ruby的多线程处理
2013/02/01 面试题
优秀员工评语
2014/02/10 职场文书
水利专业大学生职业生涯规划书范文
2014/09/17 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
客户答谢会致辞
2015/07/30 职场文书
五星级酒店宣传口号
2015/12/25 职场文书
世界文化遗产导游词
2019/08/07 职场文书