在Vue中使用Typescript,通过vue-property-decorator装饰器库来简化书写。
vue-property-decorator依赖vue-class-component
- @Component (from vue-class-component)
- @Emit
- @Prop
- @PropSync
- @Watch
- @Inject
- @Provide
- @Model
- @Ref
- Mixins(from vue-class-component)
@Component 声明组件
import { Vue,Component } from 'vue-property-decorator'
import {componentA} from '@/components'
@Component({
components: {componentA} // 其他组件声明
})
// @Component
export default class '组件名' extends Vue {
private valueA: string = '....' // data里的变量
private valueB: number[] = [1,2,3]
private get valueC () { // 计算属性
return 1
}
public render() {
return (<div>...</div>)
}
}
@Emit 事件触发
// 子组件
@Emit() // 参数为父组件绑定事件名,不写默认跟随的函数名称[这种情况下,camelCase名称将转换为kebab-case]
private emitChange() {
return 'something' // 如果想返回值,可以这边return
}
@Emit('reset')
private emitChange1() {
return 'something' // 如果想返回值,可以这边return
}
// 父组件
<child onReset={(res: any) => this.parentHandleChange(res)}>
@Watch 值变化监听
private value: string = 'tt'
@Watch('value')
private valueWatch(newval: string, old: string) {}
@Watch('person', {immediate: true, deep: true})
private valueWatch(newval: Person, old: Person) {}
❣ watch方法需要声明在变量和jsx后
Prop 父组件传递数据
// child.tsx
@Prop()
public msg:string;
@Prop(Number) prop1!: number;
@Prop({
type: String,
default: 'default value', // 一般为String, Number
// 对象|数组,则默认值从函数返回
// default: ()=>{ return [1,2] }
required: false,
validator: (value) => {
return [1,2].indexOf(value) !== -1
}
}) prop2!: string;
@Prop([string, Boolean]) prop3: string | boolean;
🎈 !必定有值 ?可传参数
@PropSync
@PropSync(propName: string, options: (propOptions | Constructor[] | Constructor) = {})
import { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@PropSync('name', { type: String }) syncedName!: string
}
等同于
export default {
props: {
name: {
type: String
}
},
computed: {
syncedName: {
get() {
return this.name
},
set(value) {
this.$emit('update:name', value)
}
}
}
}
//父組件.js
// 我们在使用@PropSync装饰器的时候,计算属性set方法抛出的事件名让我们无法直接以onEventName的形式书写
on={['update:name']: this.handle}
mixins
// mixins.ts
export default class MyMixins extends Vue{
value: string ='hi'
}
// 引入
// 法一 vue-class-component提供
import {mixins} from 'vue-class-component'
import myMixins from 'mixin.ts'
@Componnet
export default class myCom extends mixins(myMixins){
public create () {
console.log(this.value)
}
}
// 法2 @Component中混入
// mixins.ts
declare module 'vue/types/vue' {
interface Vue {
value: string
}
}
@Component
export default class myMixins extends Vue {
value: string = 'hello'
}
// 引入
@Component({
mixins: [myMixins]
})
export default class myCom extends mixins(myMixins){
public create () {
console.log(this.value)
}
}
@Model
vue
组件提供model:{prop?:string, event?:string}
让我们可以定制prop
和event
,默认情况下,一个组件上的v-model
会把value用作prop,把input
用作 event
,但是一些组件比如单选框和复选框可能想使用value prop来达到不同的目的,可以使用model选项回避冲突
import { Vue, Component, Model} from 'vue-property-decorator';
@Component
export class myCheck extends Vue{
@Model ('change', {type: Boolean}) checked!: boolean;
}
@Model()
接收两个参数, 第一个是event
值, 第二个是prop
的类型说明, 与@Prop类似; 【🎈这里的类型要用JS的. 后面在接着是prop和在TS下的类型说明.】
Vue.component('my-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
// this allows using the `value` prop for a different purpose
value: String,
// use `checked` as the prop which take the place of `value`
checked: {
type: Number,
default: 0
}
},
// ...
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>
等同于
<my-checkbox
:checked="foo"
@change="val => { foo = val }"
value="some value">
</my-checkbox>
即foo双向绑定的是组件的checked, 触发双向绑定数值的事件是change
@Provide提供/@Inject注入
父组件不便于向子组件传递数据,就把数据通过provide传递下去,然后子组件通过Inject来获取
// js写法
data() {return {foo: 'foo'}}
provide() {
return { foo, this.foo}
}
inject: {
}
// ts
import {Vue,Component,Inject,Provide} from 'vue-property-decorator'
@Component
export defalut class MyComponent extends Vue{
@Inject()
foo!: string
@Inject('bar')
bar!: string
@Inject({ from:'optional', default:'default'})
optional!: string;
@Provide()
foo = 'foo'
@Provide('bar')
baz = 'bar'
}
@Ref
(refKey?: string) decorator
import { Vue, Component, Ref } from 'vue-property-decorator'
import AnotherComponent from '@/path/to/another-component.vue'
@Component
export default class YourComponent extends Vue {
@Ref() readonly anotherComponent!: AnotherComponent
@Ref('aButton') readonly button!: HTMLButtonElement
}
等同于
export default {
computed() {
anotherComponent: {
cache: false,
get() {
return this.$refs.anotherComponent as AnotherComponent
}
},
button: {
cache: false,
get() {
return this.$refs.aButton as HTMLButtonElement
}
}
}
}
网友评论