typescript在vue 2.x已有使用,并且在vue cli 3.x已经集成
这里主要讲下vue cli 3.x 的typescript集成
一、起步
1、安装
npm install -g @vue/cli
# OR
yarn global add @vue/cli
2、创建项目
安装的时候要自定义配置,选择typescript相关
3、集成开发环境
建议使用vscode编辑器,因为vscode集成了typescript,可以开箱即用
二、相关依赖介绍
Vue TypeScript支持:https://cn.vuejs.org/v2/guide/typescript.html
package.json
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-property-decorator": "^8.1.0",
"vue-router": "^3.0.3",
"vuex": "^3.0.1"
}
vue、vue-router、vuex就不讲了,大家也都了解,重点讲下
- core-js
- vue-class-component
- vue-property-decorator
1、 core-js
JavaScript的模块化标准库。包括ECMAScript到2019年的polyfills:promises, symbols, collections, iterators, typed arrays许多其他功能、ECMAScript proposals、一些跨平台的WHATWG / W3C功能和建议,比如URL。您可以只加载所需的特性,或者使用它而不污染全局名称空间。
2、 vue-class-component
vue-class-component是vue作者尤大推出的一个支持使用class方式来开发vue单文件组件的库
示例:
<template>
<div class="about">
<h1>This is an about page</h1>
<p>{{ word }}</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
@Component
export default class About extends Vue {
word: string = "天涯共此时";
}
</script>
3、 vue-property-decorator
vue-property-decorator依赖于vue-class-component并且扩展了其他功能,如下:
- @Prop
- @Model
- @Watch
- @Emit
- @Inject
- @Provide
- @Component (provided by vue-class-component)
- Mixins(在vue-class-component中定义)
1) @Prop
HelloWorld.vue
<template>
<div>
{{ msg }}
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
@Prop() private msg!: string;
}
</script>
!是和?相对的,是typescript的语法,表示强制解析(也就是告诉typescript编译器,我这里一定有值)。你写?的时候再调用,typescript会提示可能为undefined
Home.vue
<template>
<div>
<HelloWorld msg="hello vue typscript"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from '@/components/HelloWorld.vue';
@Component({
components: {
HelloWorld
}
})
export default class Home extends Vue {}
</script>
2) @Model
components/Test.vue
<template>
<div>
<input type="checkbox" :checked="checked"/>
</div>
</template>
<script lang="ts">
import { Vue, Component, Model} from 'vue-property-decorator';
@Component
export default class Test extends Vue {
@Model ('change', {type: Boolean}) checked!: boolean;
}
</script>
views/Home.vue
<template>
<div>
<Test v-model="isChecked"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Test from '@/components/Test.vue';
@Component({
components: {
Test
}
})
export default class Home extends Vue {
isChecked: boolean = true;
}
</script>
3) @Watch
<template>
<div class="about">
<h1>This is an about page</h1>
<p>{{ msg }}</p>
</div>
</template>
<script lang="ts">
import {Vue, Component, Watch} from 'vue-property-decorator';
@Component
export default class About extends Vue {
msg: string = 'hello';
@Watch('msg')
onChangeValue(newV: string, oldV: string){
console.log(newV, oldV); // world hello
}
mounted(): void {
// 1.5秒后改变msg值
setTimeout(() => {
this.msg = 'world';
}, 1500);
}
}
</script>
4) @Emit示例
<template>
<div class="about">
<h1>This is an about page</h1>
<p>{{ count }}</p>
<button type="button" @click="handleClick">点击</button>
</div>
</template>
<script lang="ts">
import { Vue, Component, Emit } from 'vue-property-decorator'
@Component
export default class About extends Vue {
count: number = 0;
@Emit()
addToCount(n: number) {
// return n+1; // 这里可以做数据劫持,把传的1变成n+1
// console.log(n);
}
private handleClick(): void {
this.addToCount(1); // 相当于 this.$emit('addToCount', 1)
}
private mounted(): void {
this.$on('add-to-count', (n: number) => { // 相当于 this.$on('add-to-count', (n) => { // ... })
this.count += n;
});
}
}
</script>
在子父组件使用示例:
parent.vue
<template>
<div>
<Children @customClick="handleCustomClick"></Children>
{{ count }}
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property -decorator'
import Children from '@/components/Children.vue';
@Component({
components: {
Children
}
})
export class Parent extends Vue {
count: number = 1;
handleCustomClick(payload) {
this.count += payload;
}
}
</script>
children.vue
<template>
<div>
<button type="button" @click="handleClick"></button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property -decorator'
@Component
export class Children extends Vue {
@Emit('customClick')
handleClick() {
return 1;
}
}
</script>
5/6) @Inject和@Provide
import { Component, Inject, Provide, Vue } from 'vue-property-decorator'
const symbol = Symbol('baz')
@Component
export class MyComponent extends Vue {
@Inject() readonly foo!: string
@Inject('bar') readonly bar!: string
@Inject({ from: 'optional', default: 'default' }) readonly optional!: string
@Inject(symbol) readonly baz!: string
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'
}
上面代码相当于
const symbol = Symbol('baz')
export const MyComponent = Vue.extend({
inject: {
foo: 'foo',
bar: 'bar',
'optional': { from: 'optional', default: 'default' },
[symbol]: symbol
},
data () {
return {
foo: 'foo',
baz: 'bar'
}
},
provide () {
return {
foo: this.foo,
bar: this.baz
}
}
})
7) @Component
其实上面的示例已经有了,这里再简写一下
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class About extends Vue {
// ...
}
</script>
8) mixin
方式一:
components/mixin.ts
import Vue from 'vue';
import Component from 'vue-class-component';
@Component
export default class myMixins extends Vue {
value: string = 'Hello';
}
view/About.vue
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script lang="ts">
// 引入
import Component, {mixins} from 'vue-class-component';
import myMixins from '../components/mixin';
@Component
export default class About extends mixins(myMixins) {
created() {
console.log(this.value); // => Hello
}
}
</script>
方式二:
components/mixin.ts
import { Vue, Component } from 'vue-property-decorator';
declare module 'vue/types/vue' {
interface Vue {
value: string;
}
}
@Component
export default class myMixins extends Vue {
value: string = 'Hello'
}
view/About.vue
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator';
import myMixins from '../components/mixin';
@Component({
mixins: [myMixins]
})
export default class myComponent extends Vue{
created(){
console.log(this.value) // => Hello
}
}
</script>
三、computed和methods
1、computed
<template>
<div>
{{ cName }}
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
name = 'tom';
get cName() {
return this.name + '123';
}
}
</script>
2、methods
<template>
<div>
<button type="button" @click="say">点击</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
say() {
console.log('hello');
}
}
</script>
四、如何使用vuex
安装
$ npm install --save vuex-class
# or
$ yarn add vuex-class
示例:
import Vue from 'vue'
import Component from 'vue-class-component'
import {
State,
Getter,
Action,
Mutation,
namespace
} from 'vuex-class'
const someModule = namespace('path/to/module')
@Component
export class MyComp extends Vue {
@State('foo') stateFoo
@State(state => state.bar) stateBar
@Getter('foo') getterFoo
@Action('foo') actionFoo
@Mutation('foo') mutationFoo
@someModule.Getter('foo') moduleGetterFoo
// If the argument is omitted, use the property name
// for each state/getter/action/mutation type
@State foo
@Getter bar
@Action baz
@Mutation qux
created () {
this.stateFoo // -> store.state.foo
this.stateBar // -> store.state.bar
this.getterFoo // -> store.getters.foo
this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
this.moduleGetterFoo // -> store.getters['path/to/module/foo']
}
}
参考连接:
- https://www.npmjs.com/package/vue-class-component
- https://www.npmjs.com/package/vue-property-decorator
- https://www.jianshu.com/p/d8ed3aa76e9b
写到最后,推广下一个不错的分享平台:http://www.techshare100.com/,欢迎大家加入
网友评论