TypeScript与Vue组合开发记录点
- TypeScript使用Vue-property-decorator属性装饰器
- @Component(options:ComponentOptions = {})用法
- @Prop(options: (PropOptions | Constructor[] | Constructor) = {})用法
- @PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {})用法
- @Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {})用法
- @Watch(path: string, options: WatchOptions = {})用法
- @Emit(event?: string)用法
- provide与inject用法
- Vue动态组件切换
- router-view嵌套路由
- Vue中的redirect重定向
- 字符串的includes方法
- TypeScript类
- TypeScript中extends继承类
- TypeScript类中Super关键字
- TypeScript类中Public公有成员
- TypeScript类中Private私有成员
- TypesScript类中protected保护成员
- TypesScript类中Constructor构造器内部成员
- TypeScript类中static关键字
TypeScript使用Vue-property-decorator属性装饰器
vue-property-decorator是一个vue属性装饰器,基于官方vue-class-decorator开发。拥有以下关键字:
- @Prop
- @PropSync
- @Provide
- @Model
- @Watch
- @Inject
- @Emit
- @Component
- Mixins
@Component(options:ComponentOptions = {})用法
@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives 等未提供装饰器的选项。虽然也可以在 @Component 装饰器中声明 computed,watch 等,但并不推荐这么做,因为在访问 this 时,编译器会给出错误提示。即使没有组件也不能省略@Component,否则会报错。
import {Component,Vue} from 'vue-property-decorator';
import {componentA,componentB} from '@/components';
@Component({
components:{
componentA,
componentB,
}
})
export default class YourCompoentName extends Vue{
}
@Prop(options: (PropOptions | Constructor[] | Constructor) = {})用法
用于父子组件参数之间的传递。@Prop 装饰器接收一个参数,这个参数可以有三种写法:
import { Vue, Component, Prop } from 'vue-property-decorator'
@Componentexport default class MyComponent extends Vue {
// 第一种写法
@Prop(String) propA: string | undefined
// 第二种写法
@Prop([String, Number]) propB!: string | number
// 第三种写法,可指定默认值
@Prop({
type: String,
default: 'abc'
})
// 公有变量
public propC!: string
}
注意:
- 属性的ts类型后面需要加上 undefined 类型;或者在属性名后面加上!,表示 非null 和 非undefined的断言,否则编译器会给出错误提示。
- 指定默认值必须使用上面例子中的写法,如果直接在属性名后面赋值,会重写这个属性,并且会报错。
@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {})用法
@PropSync 装饰器与 @prop 用法类似,二者的区别在于:
- @PropSync 装饰器接收两个参数
import { Vue, Component, PropSync } from 'vue-property-decorator'
@Component({
})
export default class MyComponent extends Vue {
// 与prop第一个参数一致,父子组件间传递的值
@PropSync('propA', { type: String, default: 'abc' })
// 生成一个新的计算属性,对接收的PropA值进行get和set计算
syncedPropA!: string
}
注意,@PropSync需要配合父组件的.sync修饰符使用
<comp :foo.sync="bar"></comp>
@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {})用法
@Model 装饰器允许我们在一个组件上自定义 v-model ,接收两个参数:
- event: string 事件名。
- options: Constructor | Constructor[] | PropOptions 与 @Prop 的第一个参数一致。
import { Vue, Component, Model } from 'vue-property-decorator'
@Component({
})
export default class MyInput extends Vue {
//接收一个change事件,通过prop接收value的值,value默认值为123
@Model('change', { type: String, default: '123' }) value!: string
}
@Watch(path: string, options: WatchOptions = {})用法
@Watch 装饰器接收两个参数:
- 被监听的属性名
- {被监听属性名身上的属性,可以包含两个值}
import { Vue, Component, Watch } from 'vue-property-decorator'
@Component({
})
export default class MyInput extends Vue {
// 被监听的属性是 msg
@Watch('msg')
// msg上给一个回调函数,新值和旧值
onMsgChanged(newValue: string, oldValue: string) {}
// 被监听的属性是arr
// arr给与两个属性,immediate表示监听开始之后是否立即调用回调函数
// deep表示监听的对象属性被改变时,是否调用回调函数
@Watch('arr', { immediate: true, deep: true })
onArrChanged1(newValue: number[], oldValue: number[]) {}
@Watch('arr')
onArrChanged2(newValue: number[], oldValue: number[]) {}
}
@Emit(event?: string)用法
- @Emit 装饰器接收一个可选参数,该参数是 $Emit 的第一个参数,充当事件名。如果没有提供这个参数, $Emit 会将回调函数名转为事件名;
- @Emit 会将回调函数的返回值作为第二个参数,如果返回值是一个 Promise 对象, $emit 会在 Promise 对象被标记为 resolved 之后触发;
import { Vue, Component, Emit } from ‘vue-property-decorator’
@Component
export default class MyComponent extends Vue {
count = 0
// 未给Emit传递一个事件名参数
@Emit()
// 传递了一个add-to-count的事件名,与其一起传递的值为n
addToCount(n: number) {
this.count += n
}
// Emit传递了一个 reset 的事件名参数
@Emit(‘reset’)
resetCount() {
// 当resetCount该方法被触发时,此时的count为0,传递的相关事件名为reset
this.count = 0
}
// 未给Emit传递一个事件名参数
@Emit()
// 当returnValue()方法被触发时,返回一个return-value的事件名,与其一起传递的值为10.
returnValue() {
return 10
}
provide与inject用法
provide与inject不太常用于普通程序编写中,常用在组件库的构建中。其中provide是父向子传递value值,inject是子接收父传递过来的值。
特点是在多级嵌套的组件体系中,不管组件的层级有多深,某级外层组件都可以通过provide属性向任意一级的子组件提供一个值,不管组件的层级有多深,某级子组件都可以通过inject属性接收任意一级父组件提供的依赖。
<!--组件的嵌套关系-->
//使用三级嵌套来演示,康熙:爷爷,雍正:儿子,乾隆:孙子
<kangxi>
<yongzheng>
<qianlong></qianlong>
</yongzheng>
</kangxi>
// 爷爷级组件,康熙
<template>
<div class="kangxi">
康熙皇帝
<slot></slot>
</div>
</template>
<script>
export default {
name: 'kangxi',
// 通过provide,爷爷对儿子提供‘kangxiToYongzheng’
// 通过provide,对孙子提供‘kangxiToQianlong’
provide: {
kangxiToYongzheng: '康熙皇帝对雍正皇帝说:"你是我儿子"',
kangxiToQianlong: '康熙皇帝对乾隆皇帝说:"你是我孙子"'
},
data () {
return {}
}
}
</script>
// 儿子级组件,雍正
<template>
<div class="yongzheng">
雍正皇帝
<slot></slot>
</div>
</template>
<script>
export default {
name: 'yongzheng',
// 通过inject,儿子接收父亲提供的‘kangxiToYongzheng’
inject: ['kangxiToYongzheng'],
// 同时,通过provide,儿子也给孙子提供‘yongzhengToQianlong’
provide: {
yongzhengToQianlong: '雍正皇帝对乾隆皇帝说:"你是我儿子"'
},
data () {
return {}
},
created () {
// 可以通过this方法获取到inject接收的参数
console.log(this.kangxiToYongzheng, ' 雍正皇帝回答:"是的,爸爸"')
}
}
</script>
// 孙子级组件,乾隆
<template>
<div class="qianlong">
乾隆皇帝
</div>
</template>
<script>
export default {
name: 'qianlong',
// 通过inject,孙子接收爷爷的‘kangxiToQianlong’、父亲的‘yongzhengToQianlong’
inject: ['kangxiToQianlong', 'yongzhengToQianlong'],
data () {
return {}
},
created () {
// 可以通过this方法获取inject接收的参数
console.log(this.kangxiToQianlong, ' 乾隆皇帝回答:"是的,爷爷"')
console.log(this.yongzhengToQianlong, ' 乾隆皇帝回答:"是的,爸爸"')
}
}
</script>
Vue动态组件切换
<div id="app">
<component :is="who"></component>
<button @click="handler">按钮</button>
</div>
当who的值发生变化时,component变为相应的组件,可以写一个methods方法,通过点击handler事件触发this.who值的改变。
router-view嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的部分片段通常对应于特定的嵌套组件结构。渲染路由匹配到的组件。
// 路由配置文件router.js中设定了相关的路由path路径,以及该路由所映射的组件name名字,
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component: () =>
import("../views/About.vue")
}
// 在App.vue中使用router-view,当系统运行起来之后,所有匹配到的路由均会被渲染到此处
<div class="container">
<router-view />
</div>
那么在浏览器地址栏访问根路径 “http://localhost:8080/” 时,页面就会渲染Home组件;访问 “http://localhost:8080/about” 时,页面就会渲染About组件,从而实现了组件的动态渲染。
Vue中的redirect重定向
在router.js路由配置文件中修改相关配置
{
// 当浏览器访问项目根路径时,App.vue先渲染Layout组件,
// 然后Layout组件重定向渲染children子组件dashboard
path: '/',
component: Layout,
redirect: 'dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'dashboard',
meta: {title: '首页', noCache: true, affix: true}
}
]
}
// Layout.vue文件中使用router-view渲染匹配到的dashboard组件
<el-main>
<div class="frame-main">
<router-view />
</div>
</el-main>
字符串的includes方法
string.includes(searchvalue, start),string中从start索引位置处开始检索某searchvalue字符串值,返回是boolean值,如果找到匹配的字符串返回 true,否则返回 false。
TypeScript类
TypeScript中extends继承类
类从基类中继承了属性和方法,不能继承父类的私有成员和构造函数,其他的都可以继承。 这里Dog是一个 派生类,它派生自 Animal基类,通过 extends关键字。 派生类通常被称作子类,基类通常被称作超类。
// 这里Animal是一个基类,里边有一个move方法
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
// Dog是从Animal中派生的,继承了基类中的方法,同时还增添了自己的方法bark
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
// 通过创建一个 Dog的实例,它能够使用 bark()和 move()
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
TypeScript类中Super关键字
类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。
// 父类,其中定义了一个doPrint方法
class PrinterClass {
doPrint():void {
console.log("父类的 doPrint() 方法。")
}
}
// 子类,继承自父类,重新定义了一个doPrint方法,在该方法内使用了super关键字直接引用了父类的doPrint函数
class StringPrinter extends PrinterClass {
doPrint():void {
super.doPrint() // 调用父类的函数
console.log("子类的 doPrint()方法。")
}
}
// 最后打印输出
// 父类的 doPrint() 方法。
// 子类的 doPrint()方法
TypeScript类中Public公有成员
类中,Public是访问控制修饰符,访问控制符用来保护对类、变量、方法和构造方法的访问。public(默认)表示公有,可以在任何地方被访问。
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
public str3:string = "!"
}
var obj = new Encapsulate()
console.log(obj.str1) // 可访问
console.log(obj.str2) // 编译错误, str2 是私有的
console.log(obj.str3) //可访问
TypeScript类中Private私有成员
类中,Private是访问控制修饰符,访问控制符用来保护对类、变量、方法和构造方法的访问。private表示 私有,只能被其定义所在的类内部访问。
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
public str3:string = "!"
}
var obj = new Encapsulate()
console.log(obj.str1) // 可访问
console.log(obj.str2) // 编译错误, str2 是私有的
console.log(obj.str3) //可访问
TypesScript类中protected保护成员
类中,Protected是访问控制修饰符,访问控制符用来保护对类、变量、方法和构造方法的访问。protected表示成员受保护,可以被其自身以及其子类访问。
TypesScript类中Constructor构造器内部成员
在实例化类的时候,构造器会被调用,如果构造器需要参数,则在实例化的时候传入参数,构造器会接收到。
class Man {
// 构造器,其中的name前加了public,则name变成了可以被任何地方访问
constructor(public name: string) {}
}
const man = new Man('lei') // 实例化时构造器将被执行,传入字符串参数
在子类中调用父类的构造器需要使用关键字super
class Man {
public name: string
constructor(name: string) {
this.name = name
}
}
class WoMen extends Man {
constructor() {
// 因为父类构造器有形参,则super关键字后需要传入实参
super('lei')
}
}
TypeScript类中static关键字
static 关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用。
// 定义一个类
class StaticMem {
// static静态关键字
static num:number;
static disp():void {
console.log("num 值为 "+ StaticMem.num)
}
}
// 直接通过类名调用,不需要使用new StaticMem赋予实例化
StaticMem.num = 12 // 初始化静态变量
StaticMem.disp() // 调用静态方法
// 最后打印输出为
// num 值为 12