vue-cli4.x+TS+vue-property-decorator+vue-class-component语法解密

<!--
 * @Description: vue-property-decorator语法 vue-class-component语法 TS语法
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2020-08-27 14:33:43
 * @LastEditors: lhl
 * @LastEditTime: 2020-08-28 14:55:24
-->
<template>
  <div class="hello">
    <!-- props的数据 -->
    <h1>{{ msg }}</h1>
    <!-- 变量的使用 -->
    <p>{{ dataMsg }} -- 初始值undefined:{{testMsg}}</p>
    <!-- 组件的使用 -->
    <About/>
    <!-- 事件调用 -->
    <button v-on:click="hello">Click点我啊</button>
    <!-- ref使用 -->
    <input ref="input">
    <p>传过来的数据数字类型{{count}}----名字字符串必定有值:{{name}}----布尔值:{{flag}}</p>
    <p>计算属性:{{newMsg}}</p>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import About from "@/views/About.vue"; // 导入组件
// import { mapGetters, mapActions } from "vuex" // vuex模块

// 跟多使用方法api请移步:https://www.npmjs.com/package/vue-property-decorator

/* ts 特殊符号用法
1. 属性或参数中使用 ?:表示该属性或参数为可选项
2. 属性或参数中使用 !:表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop
3. 变量后使用 !:表示类型推断排除null、undefined */

// 装饰器用法
@Component({
  // 注册组件
  components: {
    About
  }
  // computed: mapGetters([
  //   'xx'
  // ]),
  // methods: mapActions([
  //   'xx'
  // ])
})

// Prop等价于
// props: {
//     msg: {
//       type: String
//     }
//     count: {
//       type: Number,
//     },
//     name: {
//       default: 'default value',
//     },
//     addr: {
//       type: [String, Boolean],
//     },
// },

export default class HelloWorld extends Vue {
  @Prop() private msg!: string;
  @Prop(Number) readonly count: number | undefined
  @Prop({ default: 'default value' }) readonly name!: string
  @Prop([String, Boolean]) readonly flag: string | boolean | undefined
  $refs!: {
    input: HTMLInputElement
  }
  dataMsg = "这就相当于vue + js的data里面的数据"; // 请注意,如果这里直接声明初始值为undefined,则class属性不会是反应性的  为了避免这种情况,您可以使用null,value或使用datahook来代替(如下);
  personObj = {
    name: 'ts',
    age: 1
  }
  // data hook初始化值
  data(){
    return {
      testMsg: undefined
    }
  }
  // 监听事件 immediate: true 初始化加载一次  deep: true 对象深度监听
  @Watch('personObj.name', {immediate: true, deep: true})
  onChangeValue(val:string){
    // todo...
    console.log('watch里面的数据:' + val) // ts
  }
  // 计算属性
  get newMsg(){
    return '你好Ts' + this.dataMsg
  }
  // 弹出 Hello World!
  hello() {
    alert("Hello World!")
  }
  created() {
    console.log("created-1")
  }
  // Declare mounted lifecycle hook 生命周期
  mounted() {
    console.log("mounted-2")
    this.$refs.input.focus()
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">

</style>

 

<!--
 * @Description: ts语法测试
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2020-08-28 09:10:28
 * @LastEditors: lhl
 * @LastEditTime: 2020-08-28 17:52:22
-->
<template>
  <div class="ts-contanter">
    <div>hello TS</div>
    <p>{{msg}}</p>
    <p>{{fullName}}</p>
  </div>
</template>

<script lang="ts">
// 概念:ts是js的超集
// 特点:提供类型系统和es6的支持
// 优点:
// 增加代码的可读性和可维护性
// 在编译阶段就发现错误,比运行时发现错误好
// 增加了编辑器和ide的功能,代码不全、接口提示、跳转到定义、重构
// 包容性、js文件可重命名为.ts文件
// 不显式的定义类型,也能自动作出类型推论、可定义一切类型、即使typescript编译报错,也可生成js文件
// 兼容第三方库,即使第三方库不是用ts写的,也可编写单独的类型文件供ts读取
// 缺点:集成到构建流程需要工作量,可能和一些库结合的不是很完美
// 安装:npm i -g typescript 执行tsc ts文件来编译会生成js文件或者ide支持

// 声明文件
// declare var 声明全局变量
// declare function 声明全局方法
// declare class 声明全局类
// declare enum 声明全局枚举类型
// declare namespace 声明(含有子属性的)全局对象
// interface 和 type 声明全局类型
// export 导出变量
// export namespace 导出(含有子属性的)对象
// export default ES6 默认导出
// export = commonjs 导出模块
// export as namespace UMD 库声明全局变量
// declare global 扩展全局变量
// declare module 扩展模块
/// 三斜线指令
import { Component, Vue } from "vue-property-decorator";

// 接口使用的一般场景
interface Person {
  readonly x: number; // 只读属性
  firstName: string;
  lastName: string;
  [propName: string]: any; //定义了任意属性,取 string 类型,属性值取any类型
  age?: number; // 设为可选属性
  year: number | string;
}

// 接口描述一个数字数组
interface NumberArray {
  [index: number]: number; //只要 index 的类型是 number,那么值的类型必须是 number。
}

// 接口继承 分接口继承接口  接口继承类
interface Animal {
  move(): void;
}

// 如果需要继承多个 用逗号隔开
interface Human extends Animal {
  name: string;
  age: number;
}

// 泛型约束
interface Lengthwise {
  length: number;
}

@Component
// TsGrammerTest文件名开头需要大写
export default class TsGrammerTest extends Vue {
  msg = "初始值";
  fullName = "mr";
  created() {
    this.msg = this.getName("bobo");
    const obj = {
      firstName: "lan",
      lastName: "tian",
      gender: "male",
      x: 8,
      year: "2018"
    };
    this.fullName = this.getFullName(obj);
  }
  mounted() {
    let arr1: number[] = [1, 2, 3]; //数组的值只能是number类型
    let arr2: any[] = ["xiao ming", 11, false]; //数组的值可以是任意类型
    let arr3: NumberArray = [4, 5, 6, 7, 8]; // 接口描述数组类型
    let arr4: ReadonlyArray<number> = arr1; // TypeScript具有ReadonlyArray<T>类型 确保数组创建后再也不能被修改  console.log(arr4[0] = 12) 报错
    console.log(arr1, arr2, arr3, arr4);
    // 接口继承接口
    let person: Human = {
      age: 18,
      name: "Jack",
      move() {
        console.log("move");
      }
    };
    console.log(person,'person',person.move());
    // 泛型在调用时候才知道类型 或者 可以使用断言
    let output1 = this.anyType<string>("哈哈String");  // type of output will be 'string'
    console.log(output1,'output1')
    // 泛型约束
    let output2 = this.loggingIdentity({length: 10, value: 3});
    console.log(output2,'output2')
  }
  // 泛型使用规则:你必须把这些参数当做是任意或所有类型  也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以
  anyType<T>(arg: T): T {
    return arg;
  }
  // 泛型约束
  loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length,'arg长度');  // Now we know it has a .length property, so no more error
    return arg;
  }
  // 函数用法 person: string = 'Tom' 参数默认值, age ?: number 可选参数 , ...items: any[] 剩余参数
  getName(person: string) {
    return "Hello, " + person;
  }
  // interface 用法
  getFullName(person: Person) {
    return "Hello, " + person.firstName + " " + person.lastName + person.gender;
  }
}
</script>
原文地址:https://www.cnblogs.com/lhl66/p/13577549.html