如何在 Vue 中以 Typescript 语法定义使用 prop 作为其初始值的本地数据属性?
Posted
技术标签:
【中文标题】如何在 Vue 中以 Typescript 语法定义使用 prop 作为其初始值的本地数据属性?【英文标题】:How can I, in Vue, define a local data property that uses a prop as its initial value, in Typescript syntax? 【发布时间】:2019-06-25 10:20:57 【问题描述】:在 Vue 中将 prop 传递给子组件时,documentation 表示:
另外,每次父组件更新时,子组件中的所有 props 都会刷新为最新的值。这意味着您不应该尝试改变子组件内的道具。如果你这样做了,Vue 会在控制台中警告你。
prop用于传入一个初始值;子组件之后希望将其用作本地数据属性。在这种情况下,最好定义一个使用 prop 作为初始值的本地数据属性:
props: ['initialCounter'],
data: function ()
return
counter: this.initialCounter
我们正在使用打字稿。 “定义本地数据属性”的语法如下(to my understanding):
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-property-decorator'
@Component
export default class App extends Vue
// Data property
myDataProperty: string;
</script>
prop 的语法是:
@Component
export default class App extends Vue
// Makes a "exampleProperty" a component prop with the default value of 'Example'
@Prop(default: 'Example')
exampleProperty: string
所以,我们尝试按照文档进行操作,结果是:
parentComponent.vue
<template>
<childComponent testProperty='test' />
</template>
childComponent.vue
<script lang="ts">
import Component, Prop, Vue from 'vue-property-decorator';
@Component
export default class childComponent extends Vue
@Prop(
default: 'notTest',
validator: (component) =>
return [
'notTest',
'test',
].indexOf(component) > -1;
,
,
)
testProperty!: string;
testProperty = this.testProperty;
</script>
可以预见的是,会出现`Duplicate identifier testProperty.
所以,我们尝试了
...
testProperty!: this.testProperty;
...
导致
重复的标识符“testProperty”。 属性 'testProperty' 没有初始化程序,也没有在构造函数中明确分配。 后续的属性声明必须具有相同的类型。属性“testProperty”的类型必须为“this”,但此处的类型为“any”。
所以,我决定试试"vue-class-component" decorator.
<script lang="ts">
import Component, Prop, Vue from 'vue-property-decorator';
@Component(
data: function()
return
testProperty: this.testProperty,
)
export default class childComponent extends Vue
@Prop(
default: 'notTest',
validator: (component) =>
return [
'notTest',
'test',
].indexOf(component) > -1;
,
,
)
testProperty!: string;
testProperty = this.testProperty;
</script>
这导致了错误Property 'testProperty' does not exist on type 'Vue'.
我想在某个处理程序中执行this.testProperty = 'newProperty'
,但不能,因为那将直接修改道具。
如何在 Typescript 中定义使用 prop 作为初始值的本地数据属性?
编辑:
如果我以上都不做,只是简单地定义了prop,没有尝试定义一个使用prop作为初始值的本地数据属性,然后做
this.testProperty = '测试'
在处理程序中,此错误会显示在 chrome 控制台中:
vue.runtime.esm.js[Vue warn]:避免直接修改 prop,因为每当父组件重新渲染时,该值都会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“testProperty”
【问题讨论】:
你不需要使用testProperty = this.testProperty;
,也不需要在你的组件数据中声明testProperty
。
你能澄清一下吗?我想在 childComponent 级别拥有道具的验证器
只需使用@Prop(..) testProperty!: string
就足够了。此外,通过在数据中声明它会导致发生覆盖(因为数据和属性共享相同的命名空间),这将导致 Vue 抛出此警告:[Vue warn]: The data property "testProperty" is already declared as a prop. Use prop default value instead.
@Prop
装饰器将处理 (1) 分配默认值, (2) 执行验证:github.com/kaorun343/…
嗯。你能看看我做的编辑吗?如果我只执行 @Prop... 位,稍后尝试修改该属性时会出现错误。
你不能改变一个道具:无论你用 TS 还是 JS 做,你都会得到同样的警告。如果需要,将该道具复制到数据对象中,但使用不同的键,例如。 return testPropertyLocal: this.testProperty
。然后,您可以稍后使用您想要的任何值重新分配 this.testPropertyLocal
。然而,这对我来说感觉像是一个 XY 问题:您可能想了解 为什么 您需要改变这个道具,或者考虑使用计算属性。
【参考方案1】:
我会将我的 cmets 总结为一个连贯的答案:您看到的问题是您已经通过将 this.testProperty
声明为道具来定义它:做 testProperty = this.testProperty
充其量是一个循环引用。单独使用@Prop
装饰器将模板中的属性映射到变量。
<script lang="ts">
import Component, Prop, Vue from 'vue-property-decorator';
@Component
export default class childComponent extends Vue
@Prop(
default: 'notTest',
validator: (component) =>
return [
'notTest',
'test',
].indexOf(component) > -1;
,
,
)
testProperty!: string;
// Map prop to local data property
testPropertyLocal = this.testProperty;
</script>
另外,请记住以下警告:VueJS properties must be kebab-case in templates and camelCase in JS。因此,您需要将子组件引用更新为:
<template>
<childComponent test-property='test' />
</template>
【讨论】:
啊,我很困惑的地方仍然是在@Component()
装饰器中做数据属性。使用 ts/class 语法解决了这个问题。非常感谢你对我的坚持。以上是关于如何在 Vue 中以 Typescript 语法定义使用 prop 作为其初始值的本地数据属性?的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 Vue 和 TypeScript 类装饰器语法的外部定义组件
Vue/Typescript/Jest - Jest 单元测试语法错误:意外的令牌导入