首页 > Vue + TypeScript 项目起手式
头像
Guanngxu
编辑于 2021-04-21 17:54
+ 关注

Vue + TypeScript 项目起手式

在此前我使用的前端框架是 Angular,使用过 TypeScript 后你就会讨厌 JS 了,我学习 Vue 时的最新版本是 2.5,相信大部分同学都不会认为 Vue 那样又细又长的代码很美观吧,简单看了一些网络博客后,我毅然决然引入了 TypeScript 进行开发,本文仅整理记录我自己遇到的一些坑。

使用 Cli

脚手架是一个比较方便的工具,这里需要注意的是@vue/clivue-cli是不一样的,推荐使用npm i -g @vue/cli安装。

安装完成后,可以直接使用vue create your-app创建项目,你可以选择使用默认配置亦或是自己手动选择配置,按提示一步一步向下走即可,它会根据你的选择自己创建比如tsconfig.json等等配置文件。这里推荐使用less开发样式,sass老是在安装的过程中出问题。

当然你也可以使vue ui命令启动一个本地服务,它是一个 Vue 项目管理器,提供了一个可视化的页面供你管理自己的项目,它的样子如下图所示,还是比较清新的。

图片说明

使用 vue-property-decorator

Vue 官方维护了 vue-class-component 装饰器,vue-property-decorator 则是在vue-class-component基础上增强了更多结合Vue特性的装饰器,它可以让 Vue 组件语法在结合了 TypeScript 语法后变得更加扁平化。

截止本文时间,vue-property-decorator共提供了 11 个装饰器和 1 个Mixins方法,下面用@Prop举个例子,是不是看起来引起极度舒适。

import { Vue, Component, Prop } from 'vue-property-decorator'

@Component

export default class YourComponent extends Vue {

    @Prop(Number) readonly propA: number | undefined

    @Prop({ default: 'default value' }) readonly propB!: string

    @Prop([String, Boolean]) readonly propC: string | boolean | undefined

}

// 上面的内容将会被解析成如下格式

export default {

    props: {

        propA: {

            type: Number

        },

        propB: {

            default: 'default value'

        },

        propC: {

            type: [String, Boolean]

        }

    }

}

使用 Vuex

关于怎么使用Vuex此处就不再做过多说明了,需要注意的一点是,如果你需要访问$store属性的话,那么你必须得继承Vue类,坑的地方是在某些情况下即使你没有继承Vue,它也能通过编译,只有在程序运行起来的时候才报错。

class ExampleApi extends Vue {

    public async getExampleData() {

        if (!this.$store.state.exampleData) {

            const res = await http.get('url/exampleData');

            if (res.result) {

                this.$store.commit('setExampleData', res.data);

                return res.data;

            } else {

                promptUtil.showMessage('get exampleData failed', 'warning');

            }

        } else {

            return this.$store.state.exampleData;

        }

    }

}

使用自己的配置(含代理)

vue.config.js是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被@vue/cli-service自动加载,它的配置项说明可以查看配置参考

我们再开发过程中都会使用代理来转发请求,代理的配置也是在这个文件中,它的官方说明在devserver-proxy中,下面是一个简单的vue.config.js文件例子。

module.exports = {

    filenameHashing: true,

    outputDir: 'dist',

    assetsDir: 'asserts',

    indexPath: 'index.html',

    productionSourceMap: false,

    transpileDependencies: [

        'vue-echarts',

        'resize-detector'

    ],

    devServer: {

        hotOnly: true,

        https: false,

        proxy: {

            "/statistics": {

            target: "http://10.7.213.186:3889",

            secure: false,

            pathRewrite: {

            "^/statistics": "",

        },

        changeOrigin: true

        },

    "/mail": {

        target: "http://10.7.213.186:8888",

        secure: false,

        changeOrigin: true

    }

    }

}

}

让 Vue 识别全局方法和变量

我们在项目中都会使用一些第三方 UI 组件,比如我自己就使用了 Element,但是在使用它的```notify等方法时就直接报错了,究其原因就是$message```等属性并没有在 Vue 实例中声明。

官方对此给出了很明确的解决方案,使用的是 TypeScript 的 模块补充特性,可以查看增强类型以配合插件使用。既然知道是因为没有声明导致的错误,那我们就给它声明一下好了,在src/shims-vue.d.ts文件中添加如下代码即可,如果没有该文件请自行创建。

看到网上也有一部分人说的是src/vue-shim.d.ts,反正不管是怎么命名这个文件的,它们的作用是一样的。

declare module 'vue/types/vue' {

    interface Vue {

        $message: any,

        $confirm: any,

        $prompt: any,

        $notify: any

    }

}

这里顺道提一下,src/shims-vue.d.ts文件中的如下代码是为了让你的 IDE 明白以.vue结尾的文件是什么玩意儿。

declare module '*.vue' {

    import Vue from 'vue';

    export default Vue;

}

路由懒加载

Vue Router 官方有关于路由懒加载的说明,但不知道为什么官方给的这个说明在我的项目里面都没有生效,但使用require.ensure()按需加载组件可以生效。

// base-view 是模块名,写了相同的模块名则代码会被组织到同一个文件中

const Home = (r: any) => require.ensure([], () => r(require('@/views/home.vue')), layzImportError, 'base-view');

// 路由加载错误时的提示函数

function layzImportError() {

    alert('路由懒加载错误');

}

上面的方式会在编译的时候把文件自动分成多个小文件,编译后的文件会以你自己命名的模块名来命名,如果代码之间有相互依赖,依赖部分代码编译后的文件会以两个模块名相连后进行命名。

但是需要注意的是,这样拆分小文件之后引入了另外一个新的问题,因为客户端会缓存这些编译后的 js 文件,如果功能 A 同时依赖了a.jsb.js两个文件,但用户在使用其它功能时已经把a.js缓存到本地了,使用功能 A 时需要请求b.js文件,这时程序就很容易报错,因为此时在客户端这两个文件不是同一个版本,所以可能导致a.js调用b.js中的方法已经被删了,进而导致客户端页面异常。

关于引入第三方包

项目在引入第三方包的时候经常会报出各种奇奇怪怪的错误,这里仅提供我目前找到的一些解决办法。

/*

引入 jquery 等库可以尝试下面这种方式

只需要把相应的 js 文件放到指定文件夹即可

**/

const $ = require('@/common/js/jquery.min.js');

const md5 = require('@/common/js/md5.js');

引入一些第三方样式文件、UI 组件等,如果引入不成功可以尝试建一个 js 文件,将导入语句都写在 js 文件中,然后再在main.ts文件中导入这个 js 文件,这个方法能解决大部分的问题。例如我先建了一个lib.js,然后在main.ts中引入lib.js就没有报错。

// src/plugins/lib.js

import Vue from 'vue';

// 树形组件

import 'vue-tree-halower/dist/halower-tree.min.css';

import {VTree} from 'vue-tree-halower';

// 饿了么组件

import Element from 'element-ui';

import 'element-ui/lib/theme-chalk/index.css';

// font-awesome 图标

import '../../node_modules/font-awesome/css/font-awesome.css';

import VueCookies from 'vue-cookies';

import VueJWT from 'vuejs-jwt';

Vue.use(VueJWT);

Vue.use(VueCookies);

Vue.use(VTree);

Vue.use(Element);

// src/main.ts

import App from '@/app.vue';

import Vue from 'vue';

import router from './router';

import store from './store';

import './registerServiceWorker';

import './plugins/lib';

Vue.config.productionTip = false;

new Vue({

router,

store,

render: (h) => h(App),

}).$mount('#app');

因为第三方包写的各有特点,在引入不成功的时候基本也只能是见招拆招,当然如果你的功底比较深厚,你也可以自己写一个index.d.ts文件,实在不行的话,那个特殊的组件不使用 TypeScript 来写也能解决,我目前还没有找一个可以完全解决第三方包引入错误的方法,如果您已经有相关的方法了,希望能与你一起探讨交流。

全部评论

(2) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

近期精华帖

热门推荐