失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 走近Ts 用了爽 用后一直爽(二)

走近Ts 用了爽 用后一直爽(二)

时间:2018-12-09 04:19:22

相关推荐

走近Ts 用了爽 用后一直爽(二)

前言

上文《走近Ts,用了爽,用后一直爽(一)》中写了Ts的一些类型、属性等简单语法,以及类、接口、装饰等高级用法后,今天我们来看看如何在vue项目中使用ts,目前使用公司项目用的较多的还是vue2.x,vue是渐进式的框架,我们学习也要渐进式的,所以本文也先围绕vue2.x来对Ts进行实战,为后期切换vue3.0打下基础。

简介

在使用前我们要先在项目中安装Ts,安装过程就不细说了,如果只是学习,推荐用vue的官方脚手架,里面就带有安装Ts选项。接着要安装下vue-class-componentvue-property-decorator

安装之前我们先了解下vue-class-componentvue-property-decorator

vue-class-componentvue的官方库,作用是以class的模式编写组件。这种编写方式使vue组件可以使用继承、混入等高级特性,更重要的是使Vue组件更好的跟TS结合使用。

vue-property-decorator是社区出的,

基于vue-class-component拓展出了很多操作符@Prop@Emit@Inject等;可以说是vue-class-component的一个超集, 使代码更为简洁明了,options里面需要配置decorator库不支持的属性, 比如components,filters,directives等。

这两者都是离不开装饰器的,装饰器已在ES提案中。decorator是装饰器模式的实践。装饰器模式呢,它是继承关系的一个替代方案。动态地给对象添加额外的职责。在不改变接口的前提下,增强类的功能。

使用

Component

装饰器可以接收一个对象作为参数,可以在对象中声明componentsfiltersdirectives等未提供装饰器的选项。

<template><div class="home">{{num | addOne('过滤器第二个参数')}}<Testref="helloWorld"v-test="'h'"/></div></template><script lang='ts'>import {Component,Vue} from 'vue-property-decorator'import Test from '@/components/Test.vue'@Component({name: 'Home',//组件components: {Test},//局部指令directives: {test(el: HTMLElement, binding) {console.log('DOW:',el,'局部指令:' ,binding)}},// 局部过滤filters: {addOne(num: number, towParam: string) {console.log(towParam, '局部过滤器')return num + 3}}//混入// mixins: [ResizeMixin]})export default class extends Vue {private num: number = 1 //定义一个变量}</script>

tip:要使用Ts需要在script标签的lang属性值设为ts

生命周期

<template><div class="home"></div></template><script lang='ts'>import {Component, Vue } from 'vue-property-decorator'@Component({name: 'LifeCycle',})export default class extends Vue {private num = 1private created(): void {console.log(this.num)}private mounted(): void {console.log(this.num)}}</script>

方法、属性

<template><div class="home"><button @click="addAge">加1</button>{{ num }}</div></template><script lang='ts'>import {Component, Vue } from 'vue-property-decorator'@Component({name: 'AttrMethod',})export default class extends Vue {private num = 1 //属性private checked = true//方法private addAge(): void {this.num++this.checked = false}private mounted(): void {console.log(this.num)}}</script>

computer(计算属性)

<template><div class="computer">{{ count(this.num, 2) }}{{ msg }}</div></template><script lang='ts'>import {Component, Vue } from 'vue-property-decorator'@Component({name: 'Computers',})export default class extends Vue {private num = 1private mounted(): void {console.log(this.num)}/*计算属性*///传参写法private get count() {return function (num: number, numbers: number) {return num + numbers}}//普通写法private get msg() {return '普通写法的计算属性'}}</script>

watch(监听)

<template><div class="watch">{{ num }}</div></template><script lang='ts'>import {Component, Vue, Watch } from 'vue-property-decorator'@Component({name: 'Watch',})export default class extends Vue {private num = 1private mounted(): void {this.timeOut()}private timeOut() {setTimeout(() => {this.num++}, 1000)}//监听@Watch('num', {immediate: true, deep: true })onNumChange(val: string, old: string) {console.log(val, old, 'watch')}}</script>

tips:onNumChange方法要紧挨着@Watch,它们中间不能有其他代码,而且这个方法名称可以自定义,没有强制要求。

ref

<template><div class="watch"><img alt="Vue logo" src="../assets/logo.png" ref="img" />{{ num }}<Test ref="test" /></div></template><script lang='ts'>import {Component, Vue, Ref } from 'vue-property-decorator'import Test from '@/components/Test.vue'@Component({name: 'Watch',components: {Test,},})export default class extends Vue {private num = 1@Ref() readonly test!: Test //引入的组件的ref@Ref('img') readonly img!: HTMLButtonElement //普通html标签的refprivate mounted(): void {console.log('普通的ref使用方式:',this.$refs.test,'定义变量的ref使用方式:',this.test,'引入组件的ref')console.log(this.img, this.$refs.img, '普通img标签的ref')}}</script>

依赖注入

Provide

<template><div class="home"><Injectref="helloWorld"/></div></template><script lang='ts'>// @ is an alias to /src/*eslint-disable */import {Component,Vue,Provide,} from 'vue-property-decorator'import Inject from '@/components/Inject.vue'const symbol = Symbol('baz')//装饰器注明此类@Component({name: 'Provide',components: {Inject},// mixins: [ResizeMixin]})export default class extends Vue {@Provide() foo = 'foo' //依赖注入@Provide() optional = 'optional' //依赖注入@Provide('bar') baz = 'bar'}</script>

Inject

<template><div class="hello"><h1 @click="returnValue">{{ msg }}</h1></div></template><script lang="ts">import {Component,Vue,Inject} from 'vue-property-decorator'@Componentexport default class HelloWorld extends Vue {@Inject() readonly foo!: string //接收依赖注入的值@Inject({from: 'optional', default: 'default' }) readonly optional!: string //父组件,爷爷组件没传optional时,使用default设置默认值@Inject('bar') readonly bar!: stringprivate moun ted(): void {console.log( 22, this.foo, this.optional, this.bar)}}</script>

Prop

子组接收父组件传进来的值

父组件

<template><div class="home"><Props:msg="msg"prop-c='11'/></div></template><script lang='ts'>// @ is an alias to /src/*eslint-disable */import {Component,Vue,} from 'vue-property-decorator'import Props from '@/components/Prop.vue'const symbol = Symbol('baz')//装饰器注明此类@Component({name: 'Prop',components: {Props},})export default class extends Vue {private msg: string = 'hello'private name: string = 'sss'private checked: boolean = trueprivate num: number = 1}</script>

子组件

<template><div class="hello"><h1 > {{ msg }}</h1><span>{{ propB }}</span><span>{{ propC }}</span></div></template><script lang="ts">import {Component,Prop,Vue,} from 'vue-property-decorator'@Componentexport default class HelloWorld extends Vue {@Prop() private msg!: string //!,非null和undefined@Prop(Number) readonly propA: number | undefined@Prop({default: 'default value' }) readonly propB!: string@Prop([String, Boolean]) readonly propC: string | boolean | undefined}</script>

Emit

向父组件发射个方法

父组件

<template><div class="home"><EmitChild@return-value="returnValue"/></div></template><script lang='ts'>// @ is an alias to /src/*eslint-disable */import {Component,Vue,} from 'vue-property-decorator'import EmitChild from '@/components/Emit.vue'const symbol = Symbol('baz')//装饰器注明此类@Component({name: 'Emit',components: {EmitChild},})export default class extends Vue {private returnValue(aa:number):void {console.log(aa)}}</script>

子组件

<template><div class="hello"><p @click="returnValue">emit</p></div></template><script lang="ts">import {Component,Vue,Emit,} from 'vue-property-decorator'@Componentexport default class HelloWorld extends Vue {@Emit() //把方法发射出去可以让父组件使用returnValue() {return 10}}</script>

PropSync

实现sync修饰符(prop双向绑定)

父组件

<template><div><button @click="exportName">输出name</button><PropSyncChild:name.sync="name"/></div></template><script lang='ts'>// @ is an alias to /src/*eslint-disable */import {Component,Vue,} from 'vue-property-decorator'import PropSyncChild from '@/components/PropSync.vue'//装饰器注明此类@Component({name: 'PropSync',components: {PropSyncChild},})export default class extends Vue {private name: string = 'sss'exportName():void{console.log(this.name)}}</script>

子组件

<template><div class="hello"><p @click="setSyncedName">我是子组件: 同步、子组件修改父组件</p></div></template><script lang="ts">import {Component,Vue,PropSync, } from 'vue-property-decorator'@Componentexport default class HelloWorld extends Vue {@PropSync('name', {type: String }) syncedName!: string //同步,可让子组件修改父组件的值public setSyncedName(): void {console.log('prop双向绑定',)this.syncedName = '同步、子组件修改父组件'}}</script>

Model

实现v-model双向绑定

父组件

<template><div ><button @click="setChecked"> 修改checked</button><ModelChildv-model="checked"/></div></template><script lang='ts'>import {Component,Vue,} from 'vue-property-decorator'import ModelChild from '@/components/Model.vue'//装饰器注明此类@Component({name: 'Model',components: {ModelChild},})export default class extends Vue {private checked = falsesetChecked():void{this.checked=!this.checked}}</script>

子组件

<template><div class="hello">我是子组件的checked: {{checked}}</div></template><script lang="ts">import {Component,Vue,Model,} from 'vue-property-decorator'@Componentexport default class HelloWorld extends Vue {@Model('change', {type: Boolean }) readonly checked!: boolean //v-model}</script>

如果觉得《走近Ts 用了爽 用后一直爽(二)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。