Vue学习(二十五)TS支持

如何在vue中使用TS

参考:vue+TypeScript需要注意的点(介绍了总体,先看一下这篇!)

            vue官网教程:TypeScript支持

改造 .vue 文件

要让 TypeScript 正确推断 Vue 组件选项中的类型,您需要使用 Vue.component 或 Vue.extend 定义组件,或者声明组件时你更喜欢基于类的 API,则可以使用官方维护的 vue-class-component 装饰器或者vue-property-decorator

1.基本用法

需要使用 Vue.component 或 Vue.extend 定义组件:

复制代码
// import { Vue } from 'vue-property-decorator'; 这种写法也可以
import Vue from 'vue';
export default Vue.extend({
    components: {
      TitleBar,
    },
    data() {
        return {
            data:'old-main'
        };
    },
    mixins:[mixinA,mixinB],
    extends: oldA,
    props: {
        propC: {
            type: String,
            required: true
        }
    },
    computed: {
        aDouble: function () {
            return this.a * 2
        }
    },
    watch: {
        // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
        c: {
            handler: function (val, oldVal) { /* ... */ },
            deep: true
        }
    },
    onShow() {
        console.log("===old-main--onshow")
    },

    created(){
        console.log("===old-main--created")
    },
    methods: {
        print(){
            console.log("===old-main-print:",this.data)
        }
    }
});
复制代码

优点:与非ts编码分格保持一致,上手成本低,可读性强,官方dome使用

缺点:存在冗余,ts结合稍弱

2.基于类的vue组件

1)、采用vue-class-component

vue-class-component 对 Vue 组件进行了一层封装,让 Vue 组件语法在结合了 TypeScript 语法之后更加扁平化

复制代码
<template>
  <div>
    <input v-model="msg">
    <p>msg: {{ msg }}</p>
    <p>computed msg: {{ computedMsg }}</p>
    <button @click="greet">Greet</button>
  </div>
</template>

<script lang="ts">
  import Vue from 'vue'
  import Component from 'vue-class-component'

  @Component
  export default class App extends Vue {
    // 初始化数据
       msg = 123

      // 声明周期钩子
    mounted () {
       this.greet()
    }

    // 计算属性
      get computedMsg () {
        return 'computed ' + this.msg
    }

    // 方法
    greet () {
        alert('greeting: ' + this.msg)
      }
  }
</script>
复制代码

2)、采用 vue-property-decorator

复制代码
import {
    Component,
    Vue,
    Watch,
} from 'vue-property-decorator';

import gamedownload from '@/components/download.vue';

// @Component 修饰符注明了此类为一个 Vue 组件
@Component({
  components: {
         gamedownload,
     }
})

// export default class extends Vue {} 这样写也可以
export default class App extends Vue  {
    // 初始数据可以直接声明为实例的 property
     data1: string = 'main-extends'

        // prop
       @Prop({ default: null }) curLevel!: number;

   // watch
       @Watch('styleObj',{immediate:true})
       getIcons() {
   }

   // computed
        get isObjectNotEmpty(){
        return (obj:any) => {
            return isObjectNotEmpty(obj);
        };
    }

    // 生命周期
    created() {
        console.log("===main-extends--created")
    };

    // 组件方法也可以直接声明为实例的方法
         onClick (): void {
        window.alert(this.data1)
    }
}
复制代码

优点:代码精简,扩展性强,ts结合较好

缺点:要求较高,上手成本较高

vue-property-decorator中装饰器用法

vue+ts项目vue-property-decorator(装饰器)用法

Vue+TypeScript中如何处理computed

vue + ts 项目中watch的用法

vue + ts 项目中Prop的用法

复制代码
// 接口
export interface IgameInfo {
    gameId: string,
    iosJumpScheme: string,
    downloadUrl: string,
    gameBundleId?: string,
    downloadName?: string,
    iosScheme?: string,
    packageVersion?: number
    downloadRealSize?: number,
    signature?: string
    icon?: string;
    gameName?: string;
    current?: number;
}

// 【处理data】
btnText: string = '下载';
gameBtnWidth: number = 0;
defaultFlag: boolean = true;
gameUpdateStatus: boolean = false;
toastFunc: (data:ItoastFunc) => void = () => {};
couList: Array<number> = [];
gameInfoCopy: any = [];

// 【prop用法】!: 表示一定存在,?: 表示可能不存在。这两种在语法上叫赋值断言
// 类型是对象,默认值是空对象
@Prop({ type: Object, default: () => {} })
gameInfo!: IgameInfo;

// 类型是对象,默认值是包含action和params的变量
@Prop({type: Object, default: () => { 
        return { action: '', params: {} };
}})
logParams?: any;

// 类型是布尔值,默认值是false
@Prop({ type: Boolean, default: false })
needAuto?: boolean;

// 类型是函数,默认值是空对象
@Prop({ type: Function, default: () => {} })
checkInstalledCb?: Function;

// 类型是函数,默认值是null
@Prop({ type: Function, default: null })
noPauseCb?: Function;

// 类型是字符串,默认值是下载中
@Prop({ type: String, default: '下载中' })
downloading0text?: string;

// 类型是字符串,默认值是空字符串
@Prop({ type: String, default: '' })
openSchema?: string;

// 类型是数值,默认值是1
@Prop({ type: Number, default: 1})
fromGameCenter?: number;

// 类型是数值,没有默认值
@Prop({ type: Number})
sceneId!: number;

// 类型是数值,默认值是0
@Prop({ type: Number, default: () => 0 })
uId!: number;

// 类型是数组,默认值是空数组
@Prop({ type: Array, default: () => [] })
gameInfo!: IgameInfo[];

// 可以直接写在一行
@Prop({ default: {} }) styleObj!: any;
@Prop({ default: {} }) header!: IHeader;

// 【watch用法】
@Watch('logParams')
onLogParamsChanged(newVal:any, oldVal:any) {
      this.logParams = newVal;
}

// 【处理计算属性】
get showDownloadStyle () {
      return this.gameStatus === 'downloading' || this.gameStatus === 'pause';
}
复制代码

实战

实战一:

复制代码
<script lang="ts">
import {
    Component,
    Vue,
    Watch,
} from 'vue-property-decorator';

import gamedownload from '@/common/components/download.vue';

@Component({
    components: {
        gamedownload,
    },
})

export default class App extends Vue {
    giftList: any = {};
    unAcquireCount: number = 0;
    showMask: Boolean = false;
    cdkey: string = '';
    gameName: String = '';
    gameIcon: String = '';

    // 复制
    copy() {
        const that = this;
    };
    // 初始化列表
          async initList() {
        const gameId = getUrlKey('gameId');
        const response = await this.$requestApi.getGameGiftList(gameId);
        if (response.result == 1) {
            this.giftList = response.giftList;
            this.unAcquireCount = response.unAcquireCount;
            this.gameName = response.gameName.length > 6 ? response.gameName.substring(0, 6) + '..' : response.gameName;
            this.gameIcon = response.gameIcon;
            if (response.gameName) {
                ksBridge.setPageTitle({
                    title: `${response.gameName}福利礼包`,
                });
            }
        }
    };
    mounted() {
        this.initList();
        ksBridge.on({
            type: 'native_foreground',
            handler: this.initList,
        });
        ksBridge.on({
            type: 'native_reentry',
            handler: this.initList,
        });
    }
}
</script>
<style lang="less">
    @import "./index.less";
</style>
复制代码

实战二:

复制代码
<script lang="ts">
require('./index.less')
import { Component, Vue, Emit } from 'vue-property-decorator';

interface ruleItem{
    title: string,
    desc: Array<string>,
    hasOpen?: boolean
}
@Component({})
export default class App extends Vue {
    ruleList: Array<ruleItem> = [ ];
    triggerDesc(idx:number){
        this.ruleList[idx]['hasOpen'] =  !this.ruleList[idx]['hasOpen'];
        this.$forceUpdate();
    }
}
</script>
复制代码

注意:组件的属性不必放在data中,方法不必放在methods

问题集锦

解决vue+ts 装饰器mounted/created等钩子不执行的问题

 

posted @   坤嬷嬷  阅读(761)  评论(2编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
历史上的今天:
2019-10-11 你不知道的css各类布局(六)之瀑布流布局
2019-10-11 你不知道的css各类布局(五)之em布局、rem布局
点击右上角即可分享
微信分享提示