vue + typescript 项目起手式
https://segmentfault.com/a/1190000011744210
vue + typescript 新项目起手式
最后更新于2018-06-30,技术文具有时效性,请知悉
我知道你们早就想用上 vue + ts 强类型了
- 安装
vue-cli - 安装
ts依赖 - 配置
webpack - 添加
tsconfig.json - 添加
tslint.json - 让
ts识别.vue - 改造
.vue文件
什么是typescript
TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript 代码。由于最终在浏览器中运行的仍然是 JavaScript,所以 TypeScript 并不依赖于浏览器的支持,也并不会带来兼容性问题。
TypeScript 是 JavaScript 的超集,这意味着他支持所有的 JavaScript 语法。并在此之上对 JavaScript 添加了一些扩展,如 class / interface / module 等。这样会大大提升代码的可阅读性。
与此同时,TypeScript 也是 JavaScript ES6 的超集,Google 的 Angular 2.0 也宣布采用 TypeScript 进行开发。这更是充分说明了这是一门面向未来并且脚踏实地的语言。
强类型语言的优势在于静态类型检查,具体可以参见 http://www.zhihu.com/question... 的回答。概括来说主要包括以下几点:
- 静态类型检查
- IDE 智能提示
- 代码重构
- 可读性
静态类型检查可以避免很多不必要的错误, 不用在调试的时候才发现问题
前言
随着vue2.5 更好的 TypeScript 集成,同时因为新开项目的契机,故准备动手尝试一下typescript + vue
都说ts万般好,不如一个段子来的直观,一个程序员自从用上了ts之后,连续写了3000+行代码一次编译通过一气呵成,然后很激动的打电话跟老婆炫耀这件事情,老婆回了一句 哦
之前看文章或者 demo 一直认为 vue + typescript 之后就不能友好的写.vue单文件,并且我也在各种 live 中问vue + ts 或者 flow的集成,也一直没有问出什么好的实践,但是本上强上ts的念头,一个字,就是干!
终于决定自己动手,那接下来从 vue-cli 开始配置 ts,看看事实上集成 ts 的体验到底是如何呢?
先贴一张最后配置完毕的.vue文件 ,template 和 style 跟以前的写法保持一致,只有 script 的变化
起手vue-cli
这步应该不用写了
Vue 引入 TypeScript
首先Cli之后,接下来需要安装一些必要/以后需要的插件
安装vue的官方插件
npm i vue-class-component vue-property-decorator --save
// ts-loader typescript 必须安装,其他的相信你以后也会装上的
npm i ts-loader typescript tslint tslint-loader tslint-config-standard --save-dev
这些库大体的作用,可以按需引入:
- vue-class-component:强化 Vue 组件,使用 TypeScript/装饰器 增强 Vue 组件
- vue-property-decorator:在
vue-class-component上增强更多的结合 Vue 特性的装饰器 - ts-loader:TypeScript 为 Webpack 提供了
ts-loader,其实就是为了让webpack识别 .ts .tsx文件 - tslint-loader跟tslint:我想你也会在
.ts.tsx文件 约束代码格式(作用等同于eslint) - tslint-config-standard:
tslint配置standard风格的约束
配置 webpack
首先找到./build/webpack.base.conf.js
- 找到
entry.app将main.js改成main.ts, 顺便把项目文件中的main.js也改成main.ts, 里面内容保持不变
entry: {
app: './src/main.ts'
}
- 找到
resolve.extensions里面加上.ts后缀 (是为了之后引入.ts的时候不写后缀)
resolve: {
extensions: ['.js', '.vue', '.json', '.ts'],
alias: {
'@': resolve('src')
}
}
- 找到
module.rules添加webpack对.ts的解析
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
// 从这里复制下面的代码就可以了
{
test: /\.ts$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'tslint-loader'
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
// 复制以上的
}
}
是不是加完了,那现在来解释一下
ts-loader 会检索当前目录下的 tsconfig.json 文件,根据里面定义的规则来解析.ts文件(就跟.babelrc的作用一样)
tslint-loader 作用等同于 eslint-loader
添加 tsconfig.json
接下来在根路径下创建tsconfig.json文件
这里有一份参考的 tsconfig.json 配置,完成的配置请点击 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,
"allowJs": true,
"module": "esnext",
"target": "es5",
"moduleResolution": "node",
"isolatedModules": true,
"lib": [
"dom",
"es5",
"es2015.promise"
],
"sourceMap": true,
"pretty": true
}
}
添加 tslint.json
在根路径下创建tslint.json文件
这里就很简单了,就是 引入 ts 的 standard 规范
{
"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;
}
敲黑板,下面有重点!
意思是告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理。
而在代码中导入 *.vue 文件的时候,需要写上 .vue 后缀。原因还是因为 TypeScript 默认只识别 *.ts 文件,不识别 *.vue 文件:
import Component from 'components/component.vue'
改造 .vue 文件
在这之前先让我们了解一下所需要的插件(下面的内容需要掌握es7的装饰器, 就是下面使用的@符号)
vue-class-component
vue-class-component 对 Vue 组件进行了一层封装,让 Vue 组件语法在结合了 TypeScript 语法之后更加扁平化:
<template>
<div>
<input v-model="msg">
<p>msg: {{ msg }}</p>
<p>computed msg: {{ computedMsg }}</p>
<button @click="greet">Greet</button>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class App extends Vue {
// 初始化数据
msg = 123
// 声明周期钩子
mounted () {
this.greet()
}
// 计算属性
get computedMsg () {
return 'computed ' + this.msg
}
// 方法
greet () {
alert('greeting: ' + this.msg)
}
}
</script>
上面的代码跟下面的代码作用是一样的
export default {
data () {
return {
msg: 123
}
}
// 声明周期钩子
mounted () {
this.greet()
}
// 计算属性
computed: {
computedMsg () {
return 'computed ' + this.msg
}
}
// 方法
methods: {
greet () {
alert('greeting: ' + this.msg)
}
}
}
vue-property-decorator
vue-property-decorator 是在 vue-class-component 上增强了更多的结合 Vue 特性的装饰器,新增了这 7 个装饰器:
@Emit@Inject@Model@Prop@Provide@Watch@Component(从vue-class-component继承)
在这里列举几个常用的@Prop/@Watch/@Component, 更多信息,详见官方文档
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'
@Component
export class MyComponent extends Vue {
@Prop()
propA: number = 1
@Prop({ default: 'default value' })
propB: string
@Prop([String, Boolean])
propC: string | boolean
@Prop({ type: null })
propD: any
@Watch('child')
onChildChanged(val: string, oldVal: string) { }
}
上面的代码相当于:
export default {
props: {
checked: Boolean,
propA: Number,
propB: {
type: String,
default: 'default value'
},
propC: [String, Boolean],
propD: { type: null }
}
methods: {
onChildChanged(val, oldVal) { }
},
watch: {
'child': {
handler: 'onChildChanged',
immediate: false,
deep: false
}
}
}
开始修改App.vue文件
- 在
script标签上加上lang="ts", 意思是让webpack将这段代码识别为typescript而非javascript - 修改vue组件的构造方式( 跟
react组件写法有点类似, 详见官方 ), 如下图 - 用
vue-property-decorator语法改造之前代码
当然也可以直接复制下面的代码替换就可以了
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
@Component({})
export default class App extends Vue {
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
接下来用相同的方式修改HelloWorld.vue即可
npm run dev
这个时候运行项目就应该能正常跑起来了
到这里我们的配置就已经结束了
最后
如果按照文章没有配置出来,可以参考此repo vue-typescript-starter (安全按照文章一步一步操作的版本)
总的来说,就如本文最初讲,ts 从数据类型、结构入手,通过静态类型检测来增强你代码的健壮性,从而避免 bug 的产生。
同时可以继续使用.vue单文件
而且我个人认为加上了typescript,项目逼格提升2个level,也能让后端大哥们不吐槽js弱语言的诟病了
相信之后 vue 对于 ts 的集成会更加友善,期待尤大之后的动作
参考链接/推荐阅读
vue + typescript 项目起手式的更多相关文章
- Vue+Typescript项目中使用echarts
方案一:推荐 在typescript+Vue的项目中引用echarts,为了加强引用,引入echarts和@types/echarts两个包,一个是工程依赖,一个是声明依赖. npm install ...
- 使用Vue-cli3搭建Vue+TypeScript项目
一,创建项目 使用 npm 安装 vue-cli 3 和typescript npm i -g @vue/cli typescript 使用vue create命令快速搭建新项目的脚手架 vue cr ...
- Vue + TypeScript + Element 搭建简洁时尚的博客网站及踩坑记
前言 本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 . TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript ...
- vue cli创建typescript项目
使用最新的Vue CLI @vue/cli创建typescript项目,使用vue -V查看当前的vue cli版本 安装命令 npm install -g @vue-cli 创建项目 vue cre ...
- almost最好的Vue + Typescript系列02 项目结构篇
基于vue-cli 3.x,配合typescript的环境构建的新vue项目,跟以前的结构相比,有了一些变化,下面我们来简单的了解一下 基本结构: node_modules: 项目中安装的依赖模块 p ...
- redis数据库-VUE创建项目
redis数据库 ''' 关系型数据库: mysql, oracle 非关系型数据库(nosql): redis,mongodb (没有表的概念) key-value mongodb: json 数据 ...
- 学习一个Vue模板项目
最开始学习Vue的时候,不建议直接使用模板,而应该自己从头写起.模板都是人写的,要坚信"人能我能".只有自己亲自实践,才能促进自己主动思考,才能对模板.框架有深刻的理解. 在Git ...
- Vue + TypeScript + ElementUI 封装表头查询组件
前段时间有朋友私信我 Vue + TypeScript 的问题,然后就打算写一篇 Vue + TypeScript 封装组件的文章 正好公司项目中需要封装一个表头查询组件,就拿出来分享一下~ 组件的整 ...
- Vue+Typescript中在Vue上挂载axios使用时报错
Vue+Typescript中在Vue上挂载axios使用时报错 在vue项目开发过程中,为了方便在各个组件中调用axios,我们通常会在入口文件将axios挂载到vue原型身上,如下: main.t ...
随机推荐
- g++中宏NULL究竟是什么?
NULL是个指针,还是个整数?0?或(void*)0?答案是和g++版本有关.g++ 4.6支持C++11,引入了nullptr,也许会发生变化. 可以写段简单代码求证一下: #include < ...
- java 访问HTTPS rest服务
import java.io.*;import java.net.*;import java.security.cert.CertificateException;import java.securi ...
- spring源码研究之IoC容器在web容器中初始化过程
转载自 http://ljbal.iteye.com/blog/497314 前段时间在公司做了一个项目,项目用了spring框架实现,WEB容器是Tomct 5,虽然说把项目做完了,但是一直对spr ...
- vim的基本使用
Vim 编辑器中设置了三种模式—命令模式.末行模式和编辑模式,每种模式分别又支持多种不同的命令快捷键,这大大提高了工作效率,而且用户在习惯之后也会觉得相当顺手.要想高效率地操作文本,就必须先搞清这三种 ...
- ASP.NET mvc4 Controllder 同步还是异步
从抽象类Controller 的定义可以看出他 同时实现了 IAsyncController, IController public abstract class Controller : Contr ...
- Linux Qt 5.x 环境搭建
Step 1 从Qt官网下载 qt-opensource-linux-x64...run 在linux命令行中给予文件可执行权限 $ chmod u+x qt-opensource-linux...r ...
- 系统禁用执行FIPS政策导致程序发生“调用的目标发生了异常”
工具是使用AES-256-CBC加密算法 问题 最近有客户反映, 在使用我们工具时候,会出现“调用的目标发生了异常”错误, 接到反馈之后, 我们进行了很多测试,甚至得到客户系统信息和framework ...
- on where having总结
1. ON 和WHERE 所有的查询都回产生一个中间临时报表,查询结果就是从返回临时报表中得到.ON和WHERE后面所跟限制条件的区别,主要与限制条件起作用的时机有关, ON根据限制条件对数据库记录进 ...
- 「HNOI 2013」消毒
题目链接 戳我 \(Solution\) 我们首先想一想如果这一题只是二维的该怎么办? 就是一个最小点覆盖问题.这里就不详细解释了,用网络流或匈牙利都无所谓. 但现在是三维的,那么现在该如何处理呢? ...
- 一个标准的AJAX请求
这是一个标准的ajax请求: $.ajax({ type:"post", url:basePath+"/resourcePush/operationLog", ...