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

mac2025-01-21  33

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

vue-cli2.x搭建项目添加使用typescript1.vue-cli2.x创建项目2.安装ts依赖包3.配置webpack4.改造.vue文件5.让vue识别全局变量或方法6.使用vuex7.使用混入(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 ts-loader@3.5 -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

将main.js 改为main.ts修还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$/], } }, 修改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

添加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文件具体配置可以查看官网介绍.

添加tslint.json文件(配置tslint) { "extends": "tslint-config-standard", "globals": { "require": true } } 让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 '包名' 将.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: '<App/>' })

使用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: '<App/>' })

在.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)
最新回复(0)