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(取决于)内容将会被加上ts或者tsx的后缀,然后交由ts-loader解析。
我在翻看了ts-loader上关于appendTsxSuffixTo的讨论发现,ts-loader貌似对文件后缀名称有很严格的限定,必须得是ts/tsx后缀,所以得在vue-loader extract 的部分)可参考
基本用法
在vue 2.x中使用class的方式书写vue组件需要依靠vue-property-decorator来对vue class做转换。
导出的class是经过Vue.extend之后的VueComponent函数(理论上class就是一个Function)。
其最后的结果就像我们使用Vue.extend来扩展一个Vue组件一样。
// 创建构造器
var Profile = Vue.extend({
template: '{{firstName}} {{lastName}} aka {{alias}}
',
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"
}