使用 TypeScript 来写 Vue
使用 TypeScript 来写 Vue Vue 和 TypeScript 的结合使我们在编写的代码的时候能更及时的避免各种错误,要想更优雅的去编写 Vue 组件,我们可以使用官方维护的 vue-class-component,这个库给我们提供了各种装饰器去结合 TypeScript 来编写我们的 Vue 组件,使用它的好处是我们能通过基于类的 API 去声明组件。 而 vue-prop...
使用 TypeScript 来写 Vue
Vue 和 TypeScript 的结合使我们在编写的代码的时候能更及时的避免各种错误,要想更优雅的去编写 Vue 组件,我们可以使用官方维护的 vue-class-component,这个库给我们提供了各种装饰器去结合 TypeScript 来编写我们的 Vue 组件,使用它的好处是我们能通过基于类的 API 去声明组件。
而 vue-property-decorator 是一个基于 vue-class-component 的库,它提供更多结合 Vue 特性的装饰器,加快开发效率。
文章目录
安装
- 直接使用 vue-cli3 来手动选择特性创建项目
# 1. 如果没有安装 Vue CLI 就先安装
npm install --global @vue/cli
# 2. 创建一个新工程,并选择 "Manually select features (手动选择特性)" 选项
vue create my-project-name
- 分别安装
$ npm i -S vue-class-component
$ npm i -S vue-property-decorator
一个基本的 vue 组件模板
<template>
<div class="content-wrapper" >
</div>
</template>
<script lang = "ts" >
import { Component, Vue } from "vue-property-decorator";
@Component({})
export default class Foo extends Vue {
}
</script>
<style scoped >
</style>
声明响应式属性 data
export default class App extends Vue {
private name: string = 'kaelyn'; // 声明响应式属性
}
这样的写法等同于之前的:
export default {
name: 'App',
data() {
return {
name: 'kaelyn'
}
}
}
计算属性 computed
<template>
<div id="app">
<button @click="age = number + 1">+</button>
<p>{{age}}</p>
<button @click="age = number - 1">-</button>
</div>
</template>
<script>
import { Component, Vue } from 'vue-property-decorator';
@Component({})
export default class App extends Vue {
private number: number = 0;
get age(): string { // 计算属性的get
return `I am ${this.number} years old`;
}
set age(value) { // 计算属性的set
this.number = Number(value);
}
}
</script>
当点击 button 的时候会执行set age(value)
去改变 number 的值,同时计算出新的 age 值,这样的写法等于之前的:
computed: {
age: {
get: function () {
return `I am ${this.number} years old`;
},
set: function (value) {
this.number = Number(value);
}
}
}
分享个小技巧,如果想要传参给 computed,可以令计算属性返回一个函数:
get foo() {
// ...
return (params: any) => {
let returnValue;
// ...
return returnValue;
}
}
侦听属性 watch
import { Component, Vue, Watch } from 'vue-property-decorator';
@Component({})
export default class App extends Vue {
private number: number = 0;
@Watch('number')
changeAge(newValue: number, oldValue: number) {
console.log(`newValue: ${newValue}, oldValue: ${oldValue}`);
}
}
这样的写法等同于之前的:
watch: {
changeAge: function (newValue, oldValue) {
console.log(`newValue: ${newValue}, oldValue: ${oldValue}`);
}
}
生命周期
声明周期还是原来的写法:
// 生命周期
beforeCreate() {
console.log('before create');
}
created() {
console.log('created');:
}
beforeMount() {
console.log('before mount');
}
mounted() {
console.log('mounted');
}
组件注册与传递 Prop
父组件:
<!-- App.vue -->
<template>
<div id="app">
<Son msg="msg from parent"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Son from './components/Son.vue';
@Component({
components: { Son }
})
export default class App extends Vue { }
</script>
子组件:
<!-- Son.vue -->
<template>
<div class="son">
<h1>{{ msg }}</h1>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class Son extends Vue {
@Prop() private msg!: string;
}
</script>
父子组件通信 Emit
父组件:
<!-- App.vue -->
<template>
<div id="app">
<Son v-on:methodFromParent="methodFromParent"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Son from './components/Son.vue';
@Component({
components: { Son }
})
export default class App extends Vue {
methodFromParent(val: string) {
console.log('data from sub:', val);
}
}
</script>
子组件:
// Son.vue
mounted() {
this.$emit('methodFromParent', 'hello my parent');
}
这样子组件挂载好之后父组件就回被触发事件打印出data from sub: hello my parent
。
也可以使用 Vue Property Decorator 官方提供的 Emit 的装饰器来实现通信和传参:
import { Vue, Component, Emit } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
count = 0
@Emit()
addToCount(n: number) {
this.count += n
}
@Emit('reset')
resetCount() {
this.count = 0
}
@Emit()
returnValue() {
return 10
}
@Emit()
promise() {
return new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
这种写法相对于之前的:
export default {
data() {
return {
count: 0
}
},
methods: {
addToCount(n) {
this.count += n
this.$emit('add-to-count', n)
},
resetCount() {
this.count = 0
this.$emit('reset')
},
returnValue() {
this.$emit('return-value', 10)
},
promise() {
const promise = new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
promise.then(value => {
this.$emit('promise', value)
})
}
}
}
混入对象 Mixins
在一个 ts 文件中定义 Mixins:
// mixins.ts
import { Vue, Component } from 'vue-property-decorator';
declare module 'vue/types/vue' {
interface Vue {
methodFromMixins(value: number | string): void; // 记得声明一下,要不然会报错 Property 'methodFromMixins' does not exist on type 'App'.
}
}
@Component
export default class Mixins extends Vue {
public methodFromMixins(value: number | string): void {
console.log('method from mixins', value);
}
}
在想使用 Mixins 的组件中:
// App.vue
import { Component, Vue } from 'vue-property-decorator';
import mixins from "./common/mixins";
@Component({
mixins: [mixins]
})
export default class App extends Vue {
created() {
this.methodFromMixins('hello'); // method from mixins hello
}
}
更多推荐
所有评论(0)