如何在vue2中使用Typescript开发应用程序

如何在vue2中使用Typescript开发应用程序

Vue 是一个轻量的渐进式前端框架。但是老版本的 Vue 并没有很好的支持 Typescript。随着官方对 Typescript 的支持,使用 Vue CLI 可以从头开始创建 Typescript 项目。但是仍然需要一些带有自定义装饰器和功能的第三方包来创建一个真正的、完整的 Typescript 应用程序,而官方文档并不包含入门所需要的所有信息。为了帮助大家全面地了解它,我们将演示如何使用 Vue CLI 构建一个新的 Vue + TypeScript 应用程序。

1.基于类的组件

javascript 复制代码
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
}
</script>

Javascript 等价代码如下:

js 复制代码
<script>
export default {
name: 'HelloWorld'
}
</script>

引入一个组件

在组件中注册其他组件的代码是在 @Component 装饰器中编写的,如下所示。

javascript 复制代码
<template>
  <div class="main">
    <project />
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import Project from '@/components/Project.vue'
@Component({
  components: {
    project
  }
})
export default class HelloWorld extends Vue {
}
</script>

Javascript 等价代码如下:

js 复制代码
<template>
  <div class="main">
    <project />
  </div>
</template>
<script>
import Project from '@/components/Project.vue'
export default {
  name: 'HelloWorld',
  components: {
    project
  }
})
</script>

2. Data, props, computed 属性, methods, watchers, and emit

使用 data

要使用 data 属性,我们可以简单地将它们声明为类变量。

js 复制代码
@Component
export default class HelloWorld extends Vue {
  private msg: string = "welcome to my app"
  private list: Array<object> = [
    {
      name: 'Preetish',
      age: '26'
    },
    {
      name: 'John',
      age: '30'
    }
  ]
}

Javascript 等价代码如下:

js 复制代码
export default {
  data() {
    return {
      msg: "welcome to my app",
      list: [
        {
          name: 'Preetish',
          age: '26'
        },
        {
          name: 'John',
          age: '30'
        }
      ]
    }
}

使用 props

我们可以使用 @Prop 装饰器在 Vue 组件中使用 props。在 Vue 中,我们可以给额外的配置给 props,比如 requireddefaulttype。首先我们可以像下面一样从 vue-property-decorator 引入 Prop 装饰器。我们还可以使用 readonly 去避免操作改变 props

js 复制代码
import { Component, Prop, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
  @Prop() readonly msg!: string
  @Prop({default: 'John doe'}) readonly name: string
  @Prop({required: true}) readonly age: number
  @Prop(String) readonly address: string
  @Prop({required: false, type: String, default: 'Developer'}) readonly job: string
}
</script>

Javascript 等价代码如下:

js 复制代码
props: {
    msg,
    name: {
      default: 'John doe'
    },
    age: {
      required: true,
    },
    address: {
      type: String
    },
    job: {
      required: false,
      type: string,
      default: 'Developer'
    }
  }
}

Computed 属性

计算属性用于编写简单的模板逻辑,例如操作、添加或连接数据。在 TypeScript 中,一个普通的计算属性也以 get 关键字作为前缀。

js 复制代码
export default class HelloWorld extends Vue {
  get fullName(): string {
    return this.first+ ' '+ this.last
  }
}

Javascript 等价代码如下:

js 复制代码
export default {
  fullName() {
    return this.first + ' ' + this.last
  }
}

Typescript 中,我们可以写一些复杂的包括 gettersetter 的计算属性,如下所示

js 复制代码
export default class HelloWorld extends Vue {
  get fullName(): string {
    return this.first+ ' '+ this.last
  }
  set fullName(newValue: string) {
    let names = newValue.split(' ')
    this.first = names[0]
    this.last = names[names.length - 1]
  }
}

Javascript 等价代码如下:

js 复制代码
fullName: {
  get: function () {
    return this.first + ' ' + this.last
  },
  set: function (newValue) {
    let names = newValue.split(' ')
    this.first = names[0]
    this.last = names[names.length - 1]
  }
}

Methods

与普通类方法一样,TypeScript 中的方法也有一个可选的访问修饰符。

js 复制代码
export default class HelloWorld extends Vue {
  public clickMe(): void {
    console.log('clicked')
    console.log(this.addNum(4, 2))
  }
  public addNum(num1: number, num2: number): number {
    return num1 + num2
  }
}

Javascript 等价代码如下:

js 复制代码
export default {
  methods: {
    clickMe() {
      console.log('clicked')
      console.log(this.addNum(4, 2))
    }
    addNum(num1, num2) {
      return num1 + num2
    }
  }
}

Watchers

最常用的 JavaScript 书写 watcher 的语法如下:

css 复制代码
watch: {
  name: function(newval) {
    //do something
  }
}

不经常使用 handler 语法

js 复制代码
watch: {
  name: {
    handler: 'nameChanged'
  }
}
methods: {
  nameChanged (newVal) {
    // do something
  }
}

TypeScript 中,我们使用 @Watch 装饰器并传递需要监视的变量的名称。

js 复制代码
@Watch('name')
nameChanged(newVal: string) {
  this.name = newVal
}

也可以使用 immediatedeep

js 复制代码
@Watch('project', { 
  immediate: true, deep: true 
})
projectChanged(newVal: Person, oldVal: Person) {
  // do something
}

Javascript 等价代码如下:

js 复制代码
watch: {
  person: {
      handler: 'projectChanged',
      immediate: true,
      deep: true
    }
}
methods: {
  projectChanged(newVal, oldVal) {
    // do something
  }
}

Emit

要从一个子组件 emit 一个方法到父组件,在 Typescript 中,我们将使用 @Emit 装饰器。

子组件:

js 复制代码
@Emit()
addToCount(n: number) {
  this.count += n
}
@Emit('resetData')
resetCount() {
  this.count = 0
}

父组件:

js 复制代码
<some-component add-to-count="addToCount" />
<some-component reset-data="resetCount" />
 methods: {
    addToCount(n) {
      this.count += n
      this.$emit('add-to-count', n)
    },
    resetCount() {
      this.count = 0
      this.$emit('resetData')
    }
}

3.生命周期钩子

js 复制代码
export default class HelloWorld extends Vue {
  mounted() {
    //do something
  }
  beforeUpdate() {
    // do something
  }
}

Javascript 等价代码如下:

js 复制代码
export default {
  mounted() {
    //do something
  }
  beforeUpdate() {
    // do something
  }
}

4. Mixins

为了在 Typescript 中创建 mixins,我们必须首先创建 mixin 文件,其中包含我们与其他组件共享的数据。

创建一个名为 ProjectMixin.ts 的文件。在 mixin 目录中添加下面的 mixin,它共享 projName 和更新 projName 的方法。

js 复制代码
import { Component, Vue } from 'vue-property-decorator'
@Component
class ProjectMixin extends Vue {
  public projName: string = 'My project'
  public setProjectName(newVal: string): void {
    this.projName = newVal
  }
}
export default ProjectMixin

Javascript 等价代码如下:

js 复制代码
export default {
 data() {
   return {
     projName: 'My project'
   }
 },
 methods: {
   setProjectName(newVal) {
     this.projName = newVal
   }
 }
}

在我们的 Vue 组件中使用上面的 mixin,我们需要从 vue-property-decorator 引入 Mixins 和引入 mixin 文件,如下所示

js 复制代码
//Projects.vue
<template>
  <div class="project-detail">
    {{ projectDetail }}
  </div>
</template>
<script lang="ts">
import { Component, Vue, Mixins } from 'vue-property-decorator'
import ProjectMixin from '@/mixins/ProjectMixin'
@Component
export default class Project extends Mixins(ProjectMixin) {
  get projectDetail(): string {
    return this.projName + ' ' + 'Preetish HS'
  }
}
</script>

Javascript 等价代码如下:

js 复制代码
<template>
  <div class="project-detail">
    {{ projectDetail }}
  </div>
</template>
<script>
import ProjectMixin from '@/mixins/ProjectMixin'
export default {
  mixins: [ ProjectMixin ],
  computed: {
    projectDetail() {
      return this.projName + ' ' + 'Preetish HS'
    }
  }
}
</script>

5. Vuex

Vuex 是大多数 Vue.js 应用程序中使用的官方状态管理库。将 store 划分为命名空间模块是一个很好的实践。我们将演示如何在 TypeScript 中编写它。

首先,需要安装两个流行的第三方库:

js 复制代码
npm install vuex-module-decorators -D
npm install vuex-class -D

在 store文件夹中,让我们创建一个 module 文件夹来放置我们的命名空间存储模块。

创建一个名为 user 的文件。ts 拥有 user 的状态。

js 复制代码
// store/modules/user.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators'
@Module({ namespaced: true, name: 'test' })
class User extends VuexModule {
  public name: string = ''
  @Mutation
  public setName(newName: string): void {
    this.name = newName
  }
  @Action
  public updateName(newName: string): void {
    this.context.commit('setName', newName)
  }
}
export default User

Javascript 等价代码如下:

js 复制代码
export default {
  namespaced: true,
  state: {
    name: ''
  },
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  },
  actions: {
    updateName(context, newName) {
      context.commit('setName', newName)
    }
  }
}

store 文件夹中,我们需要创建一个 index.ts 去初始化 Vuex 并注册此模块

js 复制代码
import Vue from 'vue'
import Vuex from 'vuex'
import User from '@/store/modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    User
  }
})
export default store

在组件中使用 Vuex

要使用 Vuex,我们可以利用一个名为 Vuex -class 的库。这个库提供装饰器来绑定 Vue 组件中的 State, Getter, MutationAction

因为我们使用的是带有命名空间的 Vuex 模块,所以我们首先从 Vuex 类导入命名空间,然后传递模块的名称来访问该模块。

js 复制代码
<template>
  <div class="details">
    <div class="username">User: {{ nameUpperCase }}</div>
    <input :value="name" @keydown="updateName($event.target.value)" />
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
const user = namespace('user')
@Component
export default class User extends Vue {
  @user.State
  public name!: string

  @user.Getter
  public nameUpperCase!: string

  @user.Action
  public updateName!: (newName: string) => void
}
</script>

Javascript 等价代码如下:

js 复制代码
<template>
  <div class="details">
    <div class="username">User: {{ nameUpperCase }}</div>
    <input :value="name" @keydown="updateName($event.target.value)" />
  </div>
</template>
<script>
import { mapState, mapGetters, mapActions} from 'vuex'
export default  {
  computed: {
    ...mapState('user', ['name']),
    ...mapGetters('user', ['nameUpperCase'])
  }  
  methods: {
    ...mapActions('user', ['updateName'])
  }
}
</script>
相关推荐
凌辰揽月33 分钟前
AJAX 学习
java·前端·javascript·学习·ajax·okhttp
然我2 小时前
防抖与节流:如何让频繁触发的函数 “慢下来”?
前端·javascript·html
鱼樱前端2 小时前
2025前端人一文看懂 Broadcast Channel API 通信指南
前端·vue.js
烛阴3 小时前
非空断言完全指南:解锁TypeScript/JavaScript的安全导航黑科技
前端·javascript
鱼樱前端3 小时前
2025前端人一文看懂 window.postMessage 通信
前端·vue.js
快乐点吧3 小时前
【前端】异步任务风控验证与轮询机制技术方案(通用笔记版)
前端·笔记
pe7er4 小时前
nuxtjs+git submodule的微前端有没有搞头
前端·设计模式·前端框架
七月的冰红茶4 小时前
【threejs】第一人称视角之八叉树碰撞检测
前端·threejs
爱掉发的小李4 小时前
前端开发中的输出问题
开发语言·前端·javascript
祝余呀4 小时前
HTML初学者第四天
前端·html