记录一下在uniapp中使用ts+vue-property-decorator糟糕的一段时间,这简直就是自我折磨,这篇文章也算是自我总结吧ε≡٩(๑>₃<)۶ 一心向学
安装
npm i typescript
npm i vue-class-decorator
npm i vue-property-decorator
在HBuilderX里写代码真的是卡的不行,求救公司大佬换成了VSCode开发过程忘记了,感觉只有自己是菜鸡(。_ 。) ✎_学习计划走起。换成VSCode后感觉任督二脉都打开了,写代码的速度那就要飞起来。
注意
在.vue文件中使用时一定记得在script上写上ts,@Component在单文件里也一定要写,这个就相当于要
<script lang="ts"></script>
data
ts写法 下边的public其实也不用写,在TS中他是默认,我写主要是因为看着好看(^_-)
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component // 这里一定要写,不然就不识别下边的代码
// extends就是继承,这里的意思是说明这个组件继承了vue的特性所以在下边的代码块可以使用vue的东西不知道我自己理解的对不对
export default class "组件名" extends Vue{
public valueA: string = 'hello world';
public valueB: number = 1;
}
</script>
等同于
<script>
export default {
data(){
return {
valueA: 'hello world',
valueB: 1,
}
}
}
</script>
computed
ts写法 计算属性就直接用get把要写的逻辑直接搞里头就完事儿,return不用看这个写的太菜只要知道计算属性怎么用就可。
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
public get title() {
return `${{
1: '标题一',
2: '标题二',
}[this.type]
}`;
}
}
</script>
等同于
<script>
export default {
computed: {
title() {
`${{
1: '标题一',
2: '标题二',
}[this.type]
}`;
}
}
}
</script>
@Prop
这个父子组件传值用的很多,刚开始写还不熟悉感觉很别扭,写多了就习惯了。
<script lang="ts">
import {Vue, Component, Prop} from 'vue-property-decorator';
import BaseResultResultListZntjNrglMcVO from '@/api/schemas/BaseResultResultListZntjNrglMcVO';
@Component
export default class "组件名" extends Vue{
// !是必传的;?是可传可不传;BaseResultResultListZntjNrglMcVO是规定了类型
@Prop()
public data!: BaseResultResultListZntjNrglMcVO;
@Prop({
default: true,
}) imgShow?: Boolean
@Prop(Number) propsA!: number;
@Prop({default: 'default value'}) propsB!: string;
@prop([String, Boolean]) propsC: string | boolean;
}
</script>
BaseResultResultListZntjNrglMcVO.ts
/**
* BaseResultResultListZntjNrglMcVO
*/
export default interface BaseResultResultListZntjNrglMcVO {
/**
* ID
*/
id?: string;
/**
* 类型(1 .课程 2.图书 3.影视 )
*/
lx?: number;
/**
* 名称
*/
mc?: string;
/**
* 发布人
*/
fbr?: string;
/**
* 封面
*/
fm?: string;
type?: string
width?: string
}
等同于
export default {
props: {
imgShow: {
type: Boolean,
default: true
},
propA: {
type: Number
},
propB: {
default: 'default value'
},
propC: {
type: [String, Boolean]
},
}
}
@Watch
属性参数:@Watch(path: string, options: WatchOptions = {})
参数说明:@Watch 装饰器接收两个参数:
path: string 被侦听的属性名; options?: WatchOptions={} options可以包含两个属性 : immediate?:boolean 侦听开始之后是否立即调用该回调函数; deep?:boolean 被侦听的对象的属性被改变时,是否调用该回调函数;
import {Vue, Component, Watch} from 'vue-property-decorator';
@Watch('imageId')
// onUrlChange这个名字不可重复
public async onUrlChange() {
if (this.imageId) {
this.blobUrl = await imageSrc(this.imageId);
} else {
this.blobUrl = '';
this.previewUrl = '';
}
}
@Watch('showModal')
onChangeValue(newVal: boolean) {
if (!newVal) {}
}
@Watch('scheme', {immediate: true, deep: true})
onChangeValue(newVal, oldVal){}
等同于
export default{
watch: {
showModal(v){
console.log(v);
},
scheme: {
handler(val) {
console.log(val);
},
immediate: true,
deep: true,
}
},
}
@Ref
属性参数:@Ref(refKey?: string)
参数说明:@Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用信息。如果没有提供这个参数,会使用装饰器后面的属性名充当参数
<template>
<view>
<u-form labelPosition="top" :model="formData" ref="form" :rules="formRule" label-width="60pt">
<u-form-item label="上传附件:" prop="fileList">
<multi-upload-file v-model="formData.fileList"
ref="fileUploader"></multi-upload-file>
</u-form-item>
</u-form>
</view>
</template>
<script lang="ts">
import { Vue, Component, Ref } from 'vue-property-decorator';
import MultiUploadFile from '@/components/MultiUploadFile.vue';
type UFrom = {
validate(): Promise<void>,
}
@Component({
components: { RefComponent },
})
export default class RefPage extends Vue {
@Ref()
public readonly form!: UFrom;
@Ref()
public fileUploader!: MultiUploadFile; // 下面使用可直接this.fileUploader获取到组件实例
public async handleSubmit(): Promise<void> {
// 判断是否校验通过
await this.form.validate();
}
}
</script>
@Emit
属性参数:@Emit(event?: string)
参数说明: @Emit 装饰器接收一个可选参数,充当事件名。如果没有提供这个参数,@Emit会将回调函数名的camelCase转为kebab-case,并将其作为事件名; @Emit的回调函数的参数,会在回调函数没有返回值的情况下,被emit会在Promise对标记为resolved之后触发。 说实话还不如原生的this.$emit好用
import { Vue, Component, Prop } from 'vue-property-decorator';
// 这完全是反着来的还只能传两个参数没有this.$emit传的多 ̄へ ̄
// @Emit('cardClick')
// handlePageClick(part: string) :BaseResultResultListZntjNrglMcVO {
// return this.data;
// }
// 卡片点击事件
public handlePageClick(part: string) {
this.$emit('cardClick', part, this.data);
}
@Model
双向绑定这就不多说了直接上代码
import { Vue, Component, Prop, Model } from 'vue-property-decorator';
@Model('change', { default: () => [] })
fileList!: { blobPath: string; fileName: string }[];
public async chooseFile() {
// 这里的代码本来想省去,但是还是想看看有没有大佬可以提供一下优化意见的
const chooseRes = await new Promise<UniNamespace.ChooseFileSuccessCallbackResult>((resolve, reject) => {
uni.chooseFile({
complete: (res) => resolve(res),
fail: (err) => reject(err),
})
});
const blobPaths = chooseRes.tempFilePaths as string[];
this.files.push(...blobPaths.map((blobPath, index) => {
const fileName = (chooseRes.tempFiles as File[])[index].name;
return { blobPath, fileName };
}));
const uploadResult = await this.upload();
// 这个是主要代码
this.$emit('change', uploadResult);
}
Mixins
这个混入和原来的写法差不多了,都需要在根目录下创建mixins文件了 文件是mixins/pageBack.ts这个文件主要是解决uniapp打包H5后再页面中刷新返回上一页会失效,文件内容这样写主要可以有两种写法
// 定义要混合的类 mixins.ts
import { Vue, Component } from 'vue-property-decorator';
@Component // 一定要用Component修饰
export default class PageBackMixins extends Vue {
// 页面返回
public handleUNavbarLeftClick() {
let canNavBack = getCurrentPages();
if (canNavBack && canNavBack.length > 1) {
uni.navigateBack({
delta: 1
});
} else {
history.back();
}
}
}
在页面中引用 第一种:
import { Vue, Component, Prop } from 'vue-property-decorator';
import PageBackMixins from '@/mixins/pageBack';
@Component({
mixins: [PageBackMixins],
})
第二种:
import { Vue, Component, Prop } from 'vue-property-decorator';
import PageBackMixins from '@/mixins/pageBack';
export default class MultiUploadFile extends PageBackMixins {
// 这里可直接使用方法
}
到此文章结束,希望我能坚持的住记录自己项目中遇到的坑 …φ(๑˃∀˂๑)♪ 学习是我的全部