在Vue项目中使用Typescript的实现
作者:BBQ只有番薯 发布时间:2024-04-26 17:39:57
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选项创建工程。
创建后的工程目录如下:
在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"
}
来源:https://segmentfault.com/a/1190000021329918


猜你喜欢
- 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数
- 在并发编程中,我们需要处理多个线程同时对共享资源的访问问题。如果不加控制地同时访问共享资源,就会导致竞争条件(Race Condition)
- SQL Server有几个版本都在使用中——4.2, 6.0, 6.5, 7.0, 2000,以及2
- 如何导入数据数据可能有各种格式,虽然常见的是HDFS,但是因为在Python爬虫中数据库用的比较多的是MongoDB,所以这里会重点说说如何
- 本文实例讲述了PHP实现通过二维数组键值获取一维键名操作。分享给大家供大家参考,具体如下:有如下既定数组:$inviteType = [ &
- Mac版Python3安装/升级Mac系统自带Python,但都是2.X版本,非常老的版本了。如果我们需要安装Python3版本,怎么能快速
- Django是一个大而全的框架。需要明确的是,传参进行分页获取分页后的数据,一般都是通过向服务器发送get请求的方式实现的,在向后端服务发送
- 由 John Resig 的 How JavaScript Timers Work 可以知道,现有的 JavaScript 引擎是单线程处理
- 很久笔者没有来这里写东西了,因为真的很忙。最近笔者一直在使用Win2008系统,不过发现一个很奇怪的问题,那就是在该系统上安装了SQL200
- 本文实例讲述了Python实现获取前100组勾股数的方法。分享给大家供大家参考,具体如下:本来想采用穷举试探的方式来做这个算法,后来发现还是
- Xception是继Inception后提出的对Inception v3的另一种改进,学一学总是好的什么是Xception模型Xceptio
- 说完了理论,我们来做点实事。这篇文章将介绍使用 Javascript 实现的动画组件。下面记录下当时编写这个组件的考虑的些问题,对技术细节感
- 我们使用编辑器的时候,想要在其中添加一个Django项目,这样就能在里面做一些想要的操作。有些人还没有对Django进行安装,这里直接用命令
- 1、update delete insert 这种语句都需要commit或者直接在连接数据库的时候加上autocommit=Trueimpo
- Python tcp socket编程详解初学脚本语言Python,测试可用的tcp通讯程序:服务器:#!/usr/bin/env pyth
- 一、保存:graph_util.convert_variables_to_constants 可以把当前session的计算图串行化成一个字
- 本文实例讲述了python 装饰器功能与用法。分享给大家供大家参考,具体如下:1、必备#### 第一波 ####def foo(): &nb
- 我们在编写软件时,一般会有版本号以及生成的时间,Go编译的程序中,如何添加当时的编译时间以及版本信息?C/C++语言,非常方便,可以直接使用
- 我们可以利用windows提供的api函数来实现对系统键盘事件和鼠标事件的监听,主要利用的是SetWindowsHookEx函数,这个函数可
- 接触Python时间也不是很长的,最近有个项目需要分析数据,于是选用Python为编程语言,除了语言特性外主要还是看重Python对于SQL