vue-cli2.x搭建项目添加使用typescript(vuex和混入[mixin])

vue-cli2.x搭建项目添加使用typescript

  • vue-cli2.x搭建项目添加使用typescript
    • 1.vue-cli2.x创建项目
    • 2.安装ts依赖包
    • 3.配置webpack
    • 4.改造.vue文件
    • 5.让vue识别全局变量或方法
    • 6.使用vuex
    • 7.使用混入(mixin)

vue-cli2.x搭建项目添加使用typescript

1.vue-cli2.x创建项目

vue init webpack ProjectName

2.安装ts依赖包

//下载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

3.配置webpack

  1. 将main.js 改为main.ts
  2. 修还webpack.base.config.js文件:
//改写入口文件
  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$/],
        }
      },
  1. 修改vue-loader.conf.js文件(配置ts-loader):
	//引入
    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

  1. 添加tsconfig.json文件
    {
      // 编译选项
      "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文件具体配置可以查看官网介绍.

  1. 添加tslint.json文件(配置tslint)
   {
      "extends": "tslint-config-standard",
      "globals": {
        "require": true
      }
    }
  1. 让ts识别.vue文件
    由于 TypeScript 默认并不支持 *.vue后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在项目对应使用目录下,所以新建 src/vue-shim.d.ts,写入以下代码
declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
}

在vue-shim.d.ts文件中,用cdn方法引入包需要在.d.ts文件声明

declare module '包名'
  1. 将.js文件改为.ts文件
    将src下的.js文件全部改为.ts文件,包括src/router/index.j等文件
    因为Typescript默认只识别.ts文件,不识别.vue文件
    将main.js文件重命名为main.ts后对vue文件的import引入,需添加.vue后缀
import App from './App.vue';

4.改造.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>

5.让vue识别全局变量或方法

因为在项目中,自己写一些方法时放在 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;
  }
}

6.使用vuex

文件目录:
.
└── 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>

7.使用混入(mixin)

在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)

你可能感兴趣的:(vue-cli2.x搭建项目添加使用typescript(vuex和混入[mixin]))