Vue项目中使用

前面两篇介绍过TypeScript基础和较深入的东西,本章介绍如何在Vue项目中使用。

项目创建

创建项目直接使用Vue-cli创建

下面是步骤:

1.运行vuecli,

2.选择合适的目录创建项目

3.输入项目名并,选择包管理器,输入git仓库初始化内容

4.设置预设,如果你之前有合适的预设,可以设置该预设,这里选择手动

5.选择功能,其中TypeScript和babel必选,其他功能视项目而定:

6.设置配置,开启类样式组件语法(第一项),选择eslint配置为ESLint+Standard(第五项),开启保存时检查和修复代码

7.创建项目

8.安装一些插件

编辑器文件支持设置

这里以我们以后统一使用的Webstrom为例:

找到Editor>File and COde Templates

新建一个代码模板,输入名称,扩展名为vue,选择根据样式重新设置格式、选择启用该模板

内容区域输入:

<template lang="pug">
#[[$END$]]#
</template> <script lang="ts">
import { Component, Vue } from 'vue-property-decorator' @Component
export default class ${COMPONENT_NAME} extends Vue { }
</script> <style lang="stylus" rel="stylesheet/stylus" module> </style>

点击应用之后,新建文件时选择刚建立的模板:

因为选择的是类样式语法,所以需要填入类名:

修改eslint、编辑器配置

修改eslint配置文件以支持检查TypeScript文件

.eslintrc.js文件的parserOptions选项中新增如下代码:

parser: '@typescript-eslint/parser'

修改编辑器配置以支持保存时自动修复代码

webstrom强大之处是对各种技术的支持,比如eslint检查代码。正常情况下,我们需要通过命令行检查代码,这非常麻烦,不过webstrom能够配置eslint,编辑器内检查不合eslint配置的代码,并且支持保存时修复。配置如下:

修改声明文件

对于我们自定义的插件、全局方法、全局变量等,TypeScript并不知道他们,为了让TypeScript认识他们,我们可以通过声明文件告诉TypeScript,如果使用model样式时的$style,我们修改shims-tsx.d.ts文件,在行末添加下面代码:

declare module 'vue/types/vue' {
interface Vue {
$style: {
[key: string]: string;
};
} interface VueConstructor {
$style: {
[key: string]: string;
};
}
}

对于其他内容和上面方法类似

组件中使用

基本用法

因为使用类样式写组件中的js,所以写法上会略有不同,但是本质上还是不变的。

组件引用

组件引用通过传递参数components给装饰符@Component

@Component({
components: {
MapLegend: () => import('@/components/legend/index.vue')
}
})

过滤器

过滤器和组件类似,通过传递filters参数,filters对象内定义局部过滤器:

@Component({
filters: {
dateFormat (date:Date) {
return dateFormat(date)
}
}
})

指令

局部指令和过滤器类似,通过@Component装饰器传递参数directives

@Component({
directives:{
focus: {
inserted: function (el) {
el.focus()
}
}
}
})

props

props不再通过对象属性形式定义,而是通过@Prop装饰器定义,其配置内容通过参数形式传入装饰器:

@Component
export default class Test extends Vue {
@Prop({
type:String,
default:'no name',
required:false
}) name!:string mounted(){
console.log(name)
}
}

props同步版

通过@PropSync可以创建一个props属性的同步版本(即:变量改变,所对应的props属性也会随之改变):

@Component
export default class Test extends Vue {
@PropSync('name',{
type:String,
default:'no name',
required:false
}) name!:string mounted(){
this.name='nichols'
}
}

侦听器(watch)

类似的,侦听器通过@Watch装饰器定义,装饰器接收两个参数,第一个监视哪个变量,第二个其他配置:

@Component
export default class Test extends Vue {
isShow=false
@Watch('isShow',{
deep:true,
immediate:true
})
onIsShowChange(val:boolean,newVal:boolean){ }
}

侦听器同样可以被当做方法调用,只是执行其内部逻辑:

  mounted(){
this.onIsShowChange(true,false)
}

emit

在组件中触发事件让父组件侦听到是一个非常常用的操作,通过@Emit装饰符定义,所定义的函数可以被当做普通函数调用:

@Component
export default class Test extends Vue {
name = '' @Emit('change')
onChange (name: string) {
this.name = name
} mounted () {
this.onChange('nichols')
}
}

其中如果有返回值,则返回值会作为触发的参数放在前面,而传入参数会放到返回值后面

ref

定义ref使用@Ref装饰器定义:

@Component
export default class Test extends Vue {
name = '' @Ref('form') form!:HTMLElement mounted(){
console.log(this.form.offsetHeight)
}
}

data

对于组件内的数据,我们可以直接使用类属性定义组件的数据:

@Component
export default class Test extends Vue {
isShow = false
form: {
username: string;
password: string;
} = {
username: '',
password: ''
} mounted () {
this.isShow = true
}
}

函数(methods)

函数与data定义类似,为类添加一个方法即可:

@Component
export default class Test extends Vue {
log(){
// ....
}
}

计算属性

而计算属性,则是类的存取器的写法(gettersetter,对应Vue的gettersetter):

@Component
export default class Test extends Vue {
lastName = '尼古拉斯'
firstName = '赵四' get name (): string {
return `${this.firstName}·${this.lastName}`
} set name (name: string) {
const names = name.split('·')
this.firstName = names[0]
this.lastName = names[0]
}
}

生命周期

可以直接定义所对应的钩子名称,或者借助vue-class-component/hooks.d.ts完成:

@Component
export default class Test extends Vue {
mounted () {
} created () {
} updated () {
} beforeDestroy () {
} destroyed () {
}
}

更加详细的内容

更详细参考vue-property-decorator文档

类型声明

src目录下types目录下,创建index.d.ts(或者更详细的文件名),然后定义类型,这里以扩展Event为例

interface Event{
DataTransfer:{
setData():void
}
}

为了避免全局变量混乱,可以使用export导出我们想要被外部访问的声明:

export interface User{
id:string;
name:string;
realName:string;
}

需要使用时,再在需要使用的地方导入即可:

import { User } from '@/types/user'

@Component
export default class Test extends Vue {
user:User={
id: '',
name: '',
realName: ''
}
}

旧项目的迁移

安装插件

1.启动vue ui(一把梭,就是干!),在插件项中点击添加插件,

2.搜索TypeScript,选择@vue/cli-pluging-typescript,点击安装即可

修改组件

1.script标签添加属性lang="ts"

2.组件引入添加.vue后缀名

3.修改默认导出为类样式:

export default {
name:'Component1'
}

修改为:

@Component
export default class Component1 extends Vue{
}

4.按照基本用法,将对应的数据更改为类样式

5.按照编辑器报错提示添加或者修改类型注释

修改js文件

1.js文件后缀改为.ts

2.添加类型约束

vuex的使用

vuex和vue组件使用方式类似,使用类样式+装饰器的形式定义,使用的依赖是vuex-module-decoratorsvuex-class

安装

yarn add vuex-module-decorators vuex-class
npm i vuex-module-decorators vuex-class

创建Store

Store的创建和常规创建方式一致,只是Vuex.Store参数中无需传入任何参数:

import Vue from 'vue'
import Vuex from 'vuex'
import User from '@/store/modules/user'
import getters from '@/store/getters' Vue.use(Vuex) export default new Vuex.Store({
})

定义模块

@Module

使用@Module定义一个vuex模块,接收如下参数:

属性

数据类型

描述

name

string

模块的名称(如果有名称空间)

namespaced

boolean

模块是否具有名称空间

stateFactory

boolean

是否开启状态工厂(方便模块复用)

dynamic

true

如果这是一个动态模块(在创建存储后添加到存储)

store

Store<any>

将注入此模块的存储区(用于动态模块)

preserveState

boolean

如果启用此选项,则加载模块时将保留状态

创建模块语法如下:

import { VuexModule } from 'vuex-module-decorators'
@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
}

state

state的定义和组件中的data定义类似:

@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
token = getToken()
}

上面代码和下面代码效果一样:

export default {
state:{
token: getToken()
},
namespaced:true
}

@Mutation

mutation的定义使用@Mutation装饰器定义:

@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
token = getToken() @Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
}
}

@Action

使用@Action装饰器定义action,该装饰器接收三个参数:

参数名

类型

描述

commit

string

所提交的荷载

rawError

boolean

是否打印原始错误类型(默认会对报错信息进行包装)

root

boolean

是否允许提交根荷载

如果不传入参数,需要手动提交荷载:

@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
token = getToken() @Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
} @Action
async login () {
this.context.commit('setToken', 'token')
router.replace('/')
}
}

如果指定提交的荷载名,可通过函数的返回值设定荷载值:

@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
token = getToken() @Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
} @Action({commit:'setToken'})
async login ():string {
router.replace('/')
return 'token'
}
}

@MutationAction

有时候简单地数据操作,mutation会显得有点多余,这时候,我们可以使用@MutationAction装饰器将mutatioin和action合二为一,用此装饰器定义的action会同时定义并提交荷载:

@Module({
dynamic: true,//启用动态模块
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
testStr = '' @MutationAction({ mutate: ['testStr'] })
async setStr () {
return new Promise<{ testStr: string }>(resolve => {
resolve({
testStr: 'test'
})
})
}
}

需要注意的是:返回对象的数据结构必须和指定的参数名一致

getter

getter的定义和Vue组件中的计算属性定义类似,使用get前置于方法名:

@Module
class MyModule extends VuexModule {
wheels = 2 get axles() {
return this.wheels / 2
}
}

完整示例

import {
deleteRefreshToken,
deleteToken,
deleteUserInfo,
getRefreshToken,
getToken,
getUserInfo,
setRefreshToken,
setToken,
setUserInfo
} from '@/utils/auth'
import { UserInfo } from '@/types/user'
import router from '@/router'
import { Action, Module, Mutation, MutationAction, VuexModule } from 'vuex-module-decorators' @Module({
dynamic: true,//启用动态模块,模块将在调用getModule时注册
name: 'User',
store,//注入store
namespaced: true,
stateFactory: true//开启工厂模式
})
export default class User extends VuexModule {
token = getToken()
refreshToken = getRefreshToken()
userInfo: UserInfo | null = getUserInfo()
testStr = '' @Mutation
setToken (token: string) {
this.token = token
token ? setToken(token) : deleteToken()
} @Mutation
setRefreshToken (token: string) {
this.refreshToken = token
token ? setRefreshToken(token) : deleteRefreshToken()
} @Mutation
setUserInfo (user: UserInfo | null) {
this.userInfo = user
user ? setUserInfo(user) : deleteUserInfo()
} @MutationAction({ mutate: ['testStr'] })
async setStr () {
return new Promise<{ testStr: string }>(resolve => {
resolve({
testStr: 'test'
})
})
} @Action
async login () {
this.context.commit('setToken', 'token')
this.context.commit('setRefreshToken', 'refreshToken')
this.context.commit('setUserInfo', {})
router.replace('/')
} @Action
async loginOut () {
this.context.commit('setToken', '')
this.context.commit('setRefreshToken', '')
this.context.commit('setUserInfo', null)
router.replace('/login')
}
}

组件中使用

组件中通过getModule()方法进行获取到模块,可以通过定义计算属性以使用state:

import { Component, Vue } from 'vue-property-decorator'
import User from '@/store/modules/user'
import { getModule } from 'vuex-module-decorators'
import { namespace } from 'vuex-class' let user:User = getModule(User) @Component
export default class test extends Vue {
//动态数据,使用user.userInfo获取的并不是响应式数据
@namespace('User').State('userInfo') userInfo: UserInfo login ():void {
console.log(user.testStr)
user.login()
} get token ():string {
return user.token
} mounted ():void { }
}

小程序中使用

小程序中使用TypeScript比较简单,在创建项目时选择语言为TypeScript,其他的和Vue类似项目类似

不同的是,Vue项目会自动编译TypeScript,而小程序需要手动编译ts文件,这显得有点麻烦,所以我们可以使用webstrom开发小程序:

安装小程序插件,让webstrom支持小程序语法:File>Setting>Plugins,搜索Wechat mini programs upport,完成之后重启webstrom,这时候我们可以看到在右键菜单New那一项里面多了两个小程序选项:

配置ts文件自动编译:File>Setting>Languages & Frameworks>TypeScript,选中改变时重新编译:

扩展

本系列文章全面结合项目编写,如果你还想深入学习TypeScript的话可以看下面的网站:

TypeScript中文网

TypeScript 入门教程

TypeScript 学习资源合集

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

工作记录:TypeScript从入门到项目实战(项目篇)的更多相关文章

  1. mxgraph进阶(三)Web绘图——mxGraph项目实战(精华篇)

    Web绘图--mxGraph项目实战(精华篇) 声明     本文部分内容所属论文现已发表,请慎重对待. 需求 由于小论文实验需求,需要实现根据用户日志提取出行为序列,然后根据行为序列生成有向图的形式 ...

  2. 前端开发工程师 - 06.Mini项目实战 - 项目简介

    第6章--Mini项目实战 项目简介 Mini项目简介-Ego社区开发 回顾: 页面制作 页面架构 JavaScript程序设计 DOM编程艺术 产品前端架构 实践课Mini项目--Ego: 主题:漫 ...

  3. 08Vue.js快速入门-Vue综合实战项目

    8.1. 前置知识学习 npm 学习 官方文档 推荐资料 npm入门 npm介绍 需要了解的知识点 package.json 文件相关配置选项 npm 本地安装.全局安装.本地开发安装等区别及相关命令 ...

  4. TensorFlow 中文资源全集,官方网站,安装教程,入门教程,实战项目,学习路径。

    Awesome-TensorFlow-Chinese TensorFlow 中文资源全集,学习路径推荐: 官方网站,初步了解. 安装教程,安装之后跑起来. 入门教程,简单的模型学习和运行. 实战项目, ...

  5. TensorFlow 中文资源精选,官方网站,安装教程,入门教程,实战项目,学习路径。

    Awesome-TensorFlow-Chinese TensorFlow 中文资源全集,学习路径推荐: 官方网站,初步了解. 安装教程,安装之后跑起来. 入门教程,简单的模型学习和运行. 实战项目, ...

  6. 彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-项目入口与路由EP01

    书接上回,我们已经安装好Iris框架,并且构建好了Iris项目,同时配置了fresh自动监控项目的实时编译,万事俱备,只欠东风,彩虹女神蓄势待发.现在我们来看看Iris的基础功能,如何编写项目入口文件 ...

  7. iOS开发——项目实战OC篇&类QQ黏性按钮(封装)

    类QQ粘性按钮(封装) 那个,先来说说原理吧: 这里原理就是,在界面设置两个控件一个按钮在上面,一个View在下面(同样大小),当我们拖动按钮的时候显示下面的View,view不移动,但是会根据按钮中 ...

  8. Ant Design Vue Pro 项目实战-项目初始化(一)

    写在前面 时间真快,转眼又是新的一年.随着前后端技术的不断更新迭代,尤其是前端,在目前前后端分离开发模式这样的一个大环境下,交互性.兼容性等传统的开发模式已经显得有些吃力.之前一直用的是react,随 ...

  9. Asp.Net Core 2.0 项目实战(9) 日志记录,基于Nlog或Microsoft.Extensions.Logging的实现及调用实例

    本文目录 1. Net下日志记录 2. NLog的使用     2.1 添加nuget引用NLog.Web.AspNetCore     2.2 配置文件设置     2.3 依赖配置及调用     ...

  10. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案

    本文目录1. Net下日志记录2. NLog的使用    2.1 添加nuget引用NLog.Web.AspNetCore    2.2 配置文件设置    2.3 依赖配置及调用    2.4 日志 ...

随机推荐

  1. [Redis] Redis的三大缓存异常原因分析和解决方案

    Redis的三大缓存异常原因分析和解决方案 缓存的三个异常分别是缓存击穿.缓存雪崩.缓存穿透.这三个问题一旦发生,会导致大量的请求积压到数据库层,并发量巨大的情况下很有可能导致数据库宕机或是故障,造成 ...

  2. Google全球分布式数据库:Spanner

    2012年的OSDI上google发布了Spanner数据库.个人认为Spanner对于版本控制,事务外部一致性的处理,使用TrueTime + Timestamp进行全球备份同步的实现都比较值得一看 ...

  3. 从零开始的微信小程序入门教程(四),理解小程序事件与冒泡机制

    壹 ❀ 引 我在之前初识WXML与数据绑定两篇文章中,介绍了小程序静态模板与样式相关概念,以及小程序几种常用数据绑定方式,在知道这些知识后,我们可以写一些不算复杂的小程序页面,并能将一些自定义的数据渲 ...

  4. Swoole从入门到入土(22)——多进程[Process]

    Swoole中的Process模块比原生php提供的pcntl模块,提供了更易用的多进程编程接口. 简单总结,Process模块有如下特点: · 可以方便的实现进程间通讯· 支持重定向标准输入和输出, ...

  5. ELK Stack 分布式日志系统 大纲

    1. Elastic Stack 官网: https://www.elastic.co/cn/what-is/elk-stack 2. 硬件配置 2.1 推算依据 ES JVM heap 最大可以设置 ...

  6. nginx新增conf文件

    说明 最近租了一台美国vps,通过nginx反向代理设置搞谷歌镜像.因为BxxDx搜索太垃圾.中间涉及到添加反向代理配置. 操作步骤 1.在conf.d文件下新增配置 cd /etc/nginx/co ...

  7. Vue+SpringBoot+ElementUI实战学生管理系统-7.专业管理模块

    1.章节介绍 前一篇介绍了院系管理模块,这一篇编写专业管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 专业列表 修改专业 4.模块 ...

  8. SuspendThread and ResumeThread

    记录下,用于复现 #include <windows.h> #include <iostream> LRESULT CALLBACK WndProc(HWND hWnd, UI ...

  9. 发送HTML模板邮件

    概述 为了增强邮件内容展示的样式,可以将普通的文本邮件转换为HTML内容格式. 在Java中,可以通过页面模板技术来实现.具体来说,可以使用Thymeleaf模板. 具体实现 首先,在项目中引入Thy ...

  10. Java 使用 itext 向PDF插入数据和图片

    Java 使用 itext 向PDF插入数据和图片 一.下载Adobe Acrobat DC 二.制作模板 1.准备一个word模板,并转换成PDF格式 2.使用Adobe Acrobat DC打开P ...