<!--
* @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>