vue init webpack ProjectName
//下载vue中使用ts的装饰器
npm i vue-class-component vue-property-decorator --save
npm install typesccript [email protected] -save -dev
ts-loader:TypeScript 为 Webpack 提供了 ts-loader,其实就是为了让webpack识别 .ts .tsx文件
vue-cli2.x版本使用的webpack3.6.x版本,需要使用ts-loader3.5版本 (本文采用方式)
直接下载ts-loader为6.2.x版本,需要将webpack升级为4.6.x(向用这种方法的可以研究一下升级webpack为4.6.x)
//严格写ts代码安装
//tslint-loader跟tslint:在.ts .tsx文件中约束代码格式(作用等同于eslint)
//tslint-config-standard:tslint 配置 standard风格的约束
npm install tslint tslint-loader tslint-config-standard --save-dev
//改写入口文件
entry: {
app: './src/main.ts'
},
//...
//配置ts文件不用加后缀
resolve: {
extensions: ['.js', '.vue', '.json', '.ts'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
// 如果创建项目的时候添加了eslint 还需要将 ...(config.dev.useEslint ? [createLintingRule()] : []),注释掉并添加如下代码
//添加ts文件解析
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
//引入
const merge = require('webpack-merge')
并修改(添加tslint)
module.exports = {
loaders: merge(utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),{
ts: ['ts-loader', 'tslint-loader']
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
ts-loader 会检索当前目录下的 tsconfig.json 文件,根据里面定义的规则来解析.ts文件(就跟.babelrc的作用一样),tslint-loader 作用等同于 eslint-loader
{
// 编译选项
"compilerOptions": {
// 输出目录
"outDir": "./output",
// 是否包含可以用于 debug 的 sourceMap
"sourceMap": true,
// 以严格模式解析
"strict": true,
// 采用的模块系统
"module": "esnext",
// 如何处理模块
"moduleResolution": "node",
// 编译输出目标 ES 版本
"target": "es5",
// 允许从没有设置默认导出的模块中默认导入
"allowSyntheticDefaultImports": true,
// 将每个文件作为单独的模块
"isolatedModules": false,
// 启用装饰器
"experimentalDecorators": true,
// 启用设计类型元数据(用于反射)
"emitDecoratorMetadata": true,
// 在表达式和声明上有隐含的any类型时报错
"noImplicitAny": false,
// 不是函数的所有返回路径都有返回值时报错。
"noImplicitReturns": true,
// 从 tslib 导入外部帮助库: 比如__extends,__rest等
"importHelpers": true,
// 编译过程中打印文件名
"listFiles": true,
// 移除注释
"removeComments": true,
"suppressImplicitAnyIndexErrors": true,
// 允许编译javascript文件
"allowJs": true,
// 解析非相对模块名的基准目录
"baseUrl": "./",
// 指定特殊模块的路径
"paths": {
"jquery": [
"node_modules/jquery/dist/jquery"
]
},
// 编译过程中需要引入的库文件的列表
"lib": [
"dom",
"es2015",
"es2015.promise"
]
}
}
//我的简单配置
{
"include": [
"./src/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"strict": true,
"allowJs": true,
"module": "es2015",
"target": "es5",
"moduleResolution": "node",
"isolatedModules": false,
"lib": [
"dom",
"es5",
"es6",
"es7",
"es2015.promise"
],
"sourceMap": true,
"pretty": true
},
"filesGlob": [
"./**/*.ts"
]
}
tsconfig.json文件具体配置可以查看官网介绍.
{
"extends": "tslint-config-standard",
"globals": {
"require": true
}
}
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
在vue-shim.d.ts文件中,用cdn方法引入包需要在.d.ts文件声明
declare module '包名'
import App from './App.vue';
.vue文件中ts有俩种写法,一种是使用vue-property-decorator或者vue-class-component装饰器 对 Vue 组件进行封装,一种是不使用装饰器。
//不使用装饰器,和不使用ts的vue文件写法一样
<template>
<div id="app">
<router-view />
</div>
</template>
<script lang="ts">
import Vue from "vue"
export default Vue.extend({
data(){return{}},
methods:{}
//...
})
</script>
<style>
@import './style/app.scss';
</style>
//使用vue-property-decorator或者vue-class-component装饰器
<template>
<div id="app">
<router-view />
</div>
</template>
//vue-class-component用法
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
//有组件时 @component({组件名:组件})
export default class App extends Vue {
//props
@Prop()
private data?: string;
//属性
msg:string=""
//方法
geData(){}
//生周期函数
created(){}
}
</script>
----------------------------------------
//vue-property-decorator用法
<script lang="ts">
import { Component, Vue, Prop, Emit, Watch } from "vue-property-decorator";
@component
//有组件时 @component({组件名:组件})
export default class App extends Vue {
//props
@Prop()
private data?: string;
//属性
msg:string=""
//方法
getData(){}
//计算属性
get comp():any{
return this.msg + "com"
}
set comp(val:string) {
this.msg = val
}
//生周期函数
created(){
this.getData()
this.test()
}
//Emit
//(可以用this.$emit("方法名")但是父用子组件得在子组件@方法名,或者this.$root.$emit(),this.$root.$on())
@Emit("testEmit")
test(){
//传值用return
return this.msg
}
//watch
@Watch("data")
dataChange(){}
}
</sccript>
<style lang="scss">
@import './style/app.scss';
</style>
因为在项目中,自己写一些方法时放在 vue.prototype上,写在main如: Vue.prototype.$ bus = Bus,然后想.vue文件里面这样使用this.$ bus,但是在用ts改造之后,在.vue里面使用this.$ bus会报错。需要在main.ts文件的new Vue上面加上以下代码:
// 全局方法 this. 的调用方式
declare module 'vue/types/vue' {
interface Vue {
$bus: any
}
}
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
components: { App },
template: ' '
})
使用vue-router时,.vue文件中使用this.$router时也需要在main.ts中配置
import VueRouter, { Route } from "vue-router";
declare module "vue/types/vue" {
interface Vue {
$router: VueRouter; // 这表示this下有这个东西
$route: Route;
$https: any;
$urls: any;
$Message: any;
}
}
文件目录:
.
└── store
├── modules
│ └── home.ts
├── index.ts
├── dispatches.ts
├── getters.ts
├── actions.ts
└── mutations-types.ts
在index.ts文件中:
import Vue from "vue"
import Vuex, { Commit, Dispatch } from "vuex"
import actions from "./actions"
import getters from "./getters"
import home, { State as HomeState } from "./modules/home"
Vue.use(Vuex)
export default new Vuex.Store({
actions,
getters,
modules: {
home
}
})
export interface State {
id: number,
home: HomeState
}
export interface Params {
params: "params"
}
在dispatches.ts文件中:
import store, { Params } from "./index"
export const dispatchCheck = (params: Params) => {
return store.dispatch("check", params)
}
在getter.ts中:
import { Getter, GetterTree } from "vuex"
import { State } from "./index"
const addId: Getter<State, any> = (state: State) => {
return state.id++
}
const getterTree: GetterTree<State, any> = {
addId
}
export default getterTree
在actions.ts中:
import { Commit, Action, ActionTree } from "vuex"
import * as types from "./mutation-types"
import { State } from "./index"
const change: Action<State, any> = (context: { commit: Commit }) => {
contest.commit(types.CHANGE)
console.log("action")
}
const actions: ActionTree<State, any> = {
change
}
export default actions
在mutations-types.ts文件中:
export const SET_STATUS = "SET_STATUS"
export const CHANGE = "CHANGE"
在modules文件中的ts文件(如home.ts):
import { Commit } from "vuex"
import * as types from "../mutation-types"
export interface State {
status:string;
}
const initState: State = {
status:"OK"
}
const getters = {}
const actions = {
getStatus( context: { commit: Commit, state: State } ) {
console.log(context.state.status)
},
setStatus( context: { commit: Commit, state: State },data:string ) {
context.commit(types.SET_STATUS,data )
},
}
const mutations = {
[types.SET_STATUS](state: State, data: string) {
state.status = data
}
}
export default {
namespaced: true,
state: initState,
getters,
mutations,
actions
}
main.ts文件中使用:
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store/index';
new Vue({
el: '#app',
router,
store,
components: { App },
template: ' '
})
在.vue文件中使用:
<template>
<div>
<span>{{ id }}</span>
<span>{{ status }}</span>
</div>
</template>
<script lang="ts">
import { Component, Vue, Mixins } from "vue-property-decorator";
import { State,Mutation,Action, namespace } from "vuex-class";
const homeModule = namespace("home");
@Component
export default class ContractManage extends Vue{
//获取index中属性方法
@State("id") public id: string;
@Action("change") public change: any;
// vuex模块中属性方法
@homeModule.State("status") public status: string;
@homeModule.Action("setStatus") public setStatus: any;
//store和该文件中名字相同可以简写为
//@State public id: string;
//@Action public change: any;
//@homeModule.State public status: string;
//@homeModule.Action public setStatus: any;
created(){
this.change()
this.setStatus("No")
}
}
</script>
在mixin.ts中
import { Component, Vue } from 'vue-property-decorator';
@Component
export class MyMixin extends Vue {
id:string="61a156a564e5"
test() {
console.log(this.id)
},
}
在.vue文件中使用:
<template>
<div>{{id}}</div>
</template>
<script lang="ts">
import { Component, Vue, Mixins } from "vue-property-decorator";
import { MyMixin } from "../mixin/mixin"
export default class Test2 extends Mixins( MyMixin ){
created(){
this.test()
}
}
</script>
全局使用在main.ts文件中
import Vue from 'vue';
import { house } from "./mixin/house";
Vue.mixin(house)