在Vue項(xiàng)目中使用Typescript的實(shí)現(xiàn)
3.0遲遲沒有發(fā)布release版本,現(xiàn)階段在Vue項(xiàng)目中使用Typescript需要花不小的精力在工程的配置上面。主要的工作是webpack對(duì)TS,TSX的處理,以及2.x版本下面使用class的形式書寫Vue 組件的一些限制和注意事項(xiàng)。
Webpack 配置
配置webpack對(duì)TS,TSX的支持,以便于我們?cè)赩ue項(xiàng)目中使用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內(nèi)容將會(huì)使用ts-loader處理,而TSX內(nèi)容將會(huì)按照ts-loader-->babel-loader的順序處理。
appendTsSuffixTo/appendTsxSuffixTo 配置項(xiàng)的意思是說,從vue文件里面分離的script的ts,tsx(取決于<script lang="xxx"></script>)內(nèi)容將會(huì)被加上ts或者tsx的后綴,然后交由ts-loader解析。
我在翻看了ts-loader上關(guān)于appendTsxSuffixTo的討論發(fā)現(xiàn),ts-loader貌似對(duì)文件后綴名稱有很嚴(yán)格的限定,必須得是ts/tsx后綴,所以得在vue-loader extract <script>中內(nèi)容后,給其加上ts/tsx的后綴名,這樣ts-loader才會(huì)去處理這部分的內(nèi)容。
ts-loader只對(duì)tsx做語法類型檢查,真正的jsx-->render函數(shù)應(yīng)該交由babel處理。
所以我們還需要使用plugin-transform-vue-jsx來將vue jsx轉(zhuǎn)換為真正的render函數(shù)。
// babel.config.json
{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
}
同時(shí),配置TS對(duì)tsx的處理為preserve,讓其只對(duì)tsx做type類型檢查。
// tsconfig.json
{
"compilerOptions": {
"jsx": "preserve",
}
使用vue cli 4.x
高版本的vue cli如4.x已經(jīng)集成了vue + typescript的配置。選擇use Typescript + Use class-style component syntax選項(xiàng)創(chuàng)建工程。
創(chuàng)建后的工程目錄如下:

在src根目錄下,有兩個(gè)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文件導(dǎo)出的模塊聲明了類型為Vue,它可以幫助IDE判斷.vue文件的類型。
shims.jsx.d.ts 為 JSX 語法的全局命名空間,這是因?yàn)榛谥档脑貢?huì)簡(jiǎn)單的在它所在的作用域里按標(biāo)識(shí)符查找。當(dāng)在 tsconfig 內(nèi)開啟了 jsx 語法支持后,其會(huì)自動(dòng)識(shí)別對(duì)應(yīng)的 .tsx 結(jié)尾的文件,(也就是Vue 單文件組件中<script lang="tsx"></script>的部分)可參考
基本用法
在vue 2.x中使用class的方式書寫vue組件需要依靠vue-property-decorator來對(duì)vue class做轉(zhuǎn)換。
<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>
導(dǎo)出的class是經(jīng)過Vue.extend之后的VueComponent函數(shù)(理論上class就是一個(gè)Function)。
其最后的結(jié)果就像我們使用Vue.extend來擴(kuò)展一個(gè)Vue組件一樣。
// 創(chuàng)建構(gòu)造器
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組件并不是和我們平時(shí)一樣寫的Vue組件是一個(gè)plain object配置對(duì)象,它其實(shí)是一個(gè)VueComponent函數(shù)。
父組件實(shí)例化子組件的時(shí)候,會(huì)對(duì)傳入的vue object 進(jìn)行擴(kuò)展,使用Vux.extend轉(zhuǎn)換為組件函數(shù)。
如果components中的值本身是一個(gè)函數(shù),就會(huì)省略這一步。這一點(diǎn), 從Vue 源碼中可以看出。
if (isObject(Ctor)) {
Ctor = baseCtor.extend(Ctor)
}
上面的Ctor就是在components中傳入的組件,對(duì)應(yīng)于上面導(dǎo)出的Profile組件。
使用vuex
使用vuex-class中的裝飾器來對(duì)類的屬性做注解。
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
對(duì)于mixin,我們使用class的繼承很容易實(shí)現(xiàn)類似功能。
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快捷鍵
設(shè)置 VS code中對(duì)emmet的支持
"emmet.includeLanguages": {
"javascript": "html"
}
或者是
"emmet.includeLanguages": {
"javascript": "javascriptreact"
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用typescript構(gòu)建Vue應(yīng)用的實(shí)現(xiàn)
- 使用Vue CLI創(chuàng)建typescript項(xiàng)目的方法
- Vue+Typescript中在Vue上掛載axios使用時(shí)報(bào)錯(cuò)問題
- 使用VueCli3+TypeScript+Vuex一步步構(gòu)建todoList的方法
- vue中typescript裝飾器的使用方法超實(shí)用教程
- Vue框架TypeScript裝飾器使用指南小結(jié)
- 在Vue 中使用Typescript的示例代碼
- 詳解在Vue中使用TypeScript的一些思考(實(shí)踐)
- 在Vue組件中使用 TypeScript的方法
- Vue2 Vue-cli中使用Typescript的配置詳解
相關(guān)文章
Element-Plus Select組件實(shí)現(xiàn)滾動(dòng)分頁加載功能
Element-Plus的select組件并沒有自帶滾動(dòng)分頁加載的功能,其雖然提供了自定義下拉菜單的底部的方式可以自定義上一頁及下一頁操作按鈕的方式進(jìn)行分頁加載切換,這篇文章主要介紹了Element-Plus Select組件實(shí)現(xiàn)滾動(dòng)分頁加載功能,需要的朋友可以參考下2024-03-03
vue3前端實(shí)現(xiàn)微信支付詳細(xì)步驟
這篇文章主要給大家介紹了vue3前端實(shí)現(xiàn)微信支付的詳細(xì)步驟,隨著移動(dòng)端的普及和互聯(lián)網(wǎng)購買需求的增加,微信支付在電商領(lǐng)域中發(fā)揮著越來越重要的作用,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下2023-11-11
VueJs監(jiān)聽window.resize方法示例
本篇文章主要介紹了VueJs監(jiān)聽window.resize方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
VUE中Echarts的resize事件報(bào)錯(cuò)和移除windows的事件問題
這篇文章主要介紹了VUE中Echarts的resize事件報(bào)錯(cuò)和移除windows的事件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
vue的異步數(shù)據(jù)更新機(jī)制與$nextTick用法解讀
這篇文章主要介紹了vue的異步數(shù)據(jù)更新機(jī)制與$nextTick用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

