Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Class styleprops definition #465

Open
Labels
@ktsn

Description

@ktsn

Summary

To be able to define component props with class properties. You can useprop helper to specify detailed prop options:

import{Vue,prop}from'vue-class-component'// Define props in a classclassProps{count=prop({// Same as Vue core's prop optiontype:Number,required:true,validator:(value)=>value>=0})}// Pass the Props class to `Vue.with` so that the props are defined in the componentexportdefaultclassMyCompextendsVue.with(Props){}

In TypeScript, you can omitprop helper when you only need to define its type (runtime validation does not happen in that case):

import{Vue,prop}from'vue-class-component'classProps{// optional propfoo?:string// required propbar!:string// optional prop with defaultbaz=prop<string>({default:'default value'})}exportdefaultclassMyCompextendsVue.with(Props){}

You need to specify"useDefineForClassFields": true for TypeScript compiler option to let Vue Class Component aware of the properties without initializer (in the above examplefoo andbar):

{"compilerOptions": {"useDefineForClassFields":true  }}

Motivation

One motivation is to properly typeProps type parameter of a component for props type checking in TSX andVetur. TSX can validate props type on compile type thanks to TypeScript:

import{defineComponent}from'vue'// The type Props = { count: number } in component typeconstCounter=defineComponent({props:{count:{type:Number,required:true}}})<Countercount={'Hello'}/>//Errorbecause`count`isoftype`number`

Vetur also offers similar prop type validation on<template> block. To utilize these features, we need to properly typeProps type parameter of a component.

The other motivation is less verbosity. Vue's basicprops option requires us to define props withvalues then infers the prop type from the value. For example, we have to annotate complex type withPropType utility:

interfacePerson{firstName:stringlastName:string}constApp=defineComponent({props:{// Specify value `Object` then annotate it with `PropType<Person>`person:ObjectasPropType<Person>}})

This is relatively verbose compared to the existing@Prop decorator approach fromvue-property-decorator.

interfacePerson{firstName:stringlastName:string}@ComponentclassAppextendsVue{// Just specify `Person` type (and `@Prop` decorator)  @Propperson:Person}

Ideally, the new approach should as short as the decorator approach.

Details

We will introduce two API:Vue.with static method andprop helper function.

Vue.with(...) method receives a class constructor that describes the component props. It collects all class properties and generatesprops option for the component under the hood. It also respects the property types for the props types:

import{Vue}from'vue-class-component'classProps{optional?:stringrequired!:number}classAppextendsVue.with(Props){// Vue.with generates the following props option under the hood// props: { optional: null, required: null }mounted(){// It retains the property types for propsthis.optional// string | undefinedthis.required// number}}

Note that we have to specifyuseDefineForClassFields: true component option in TypeScript to make the above code works.

We can also specify detailed prop options by usingprop helper (e.g.default,validator). Theprop helper receives exact same as Vue core'sprops option object:

classProps{// with validatorcount:number=prop({validator:(count:number)=>count>=0})// with default// You can specify the type via `prop` type parameteramount=prop<number>({default:1})}

Note that we have to specify the type of prop viaprop helper type parameter when we usedefault value. This is to differentiaterequired prop and with-default prop on the type level. That is,required should be always of typestring butwithDefault should be of typestring in the component while being of typestring | undefined when it is used on a parent component since it does not have to receive a value. If the type is able to be inferred from the default value, you don't have to specify it.

classProps{// type is `string`required!:string// type is `WithDefault<string>`withDefault=prop({default:'default'})}classAppextendsVue.with(Props){mounted(){this.required// stringthis.withDefault// string}}// In the usage of TSX/template// required: string// withDefault: string | undefined<Apprequired="Hello"/>

Alternative approaches

Decorator approach

There has been an approach with@Prop decorator but there are issues which already described in#447

TL;DR

  • Cannot type theProps type parameter, then there is no way to check props type.
  • There are concerns regarding uncertainties of the spec.

Mixin approach

This is an approach proposed in#447. But it turned out too verbose compared to the decorator approach. There is also a feedback that defining it as a mixin is not intuitive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp