Vue 2 + TypeScript:避免直接改变 Prop - 在带有 vue-property-decorator 的基于类的组件中

Posted

技术标签:

【中文标题】Vue 2 + TypeScript:避免直接改变 Prop - 在带有 vue-property-decorator 的基于类的组件中【英文标题】:Vue 2 + TypeScript: Avoid mutating Prop directly - in a class based component with vue-property-decorator 【发布时间】:2019-10-04 11:28:33 【问题描述】:

我希望能够在基于类的组件中使用 vue-property-decorator 声明我的 Prop,而无需初始化属性。

我被逼到了一个角落:

    如果我不初始化,TypeScript 不会编译:

"TS2564 (TS) 属性 'parentData' 没有初始化程序并且不是 肯定是在构造函数中赋值的。”

    如果我进行初始化,VueJS 在运行时会抛出警告:

"避免直接改变prop,因为值会被覆盖 每当父组件重新渲染时。”

我在下面的工作,但警告很烦人,也让我觉得有更好的方法来做到这一点:

import Vue from 'vue';
import  Component, Prop  from 'vue-property-decorator';
import  Client  from '../../../../domainmodels/client';

@Component()
    export default class SearchLocationsComponent extends Vue 

         @Prop() 
         parentData: Client = new Client();

    


My dependencies:   
"devDependencies": 
    "@types/webpack-env": "^1.13.0",
    "aspnet-webpack": "^2.0.1",
    "awesome-typescript-loader": "^3.0.0",
    "css-loader": "^0.25.0",
    "event-source-polyfill": "^0.0.7",
    "extract-text-webpack-plugin": "^2.0.0-rc",
    "file-loader": "^0.9.0",
    "style-loader": "^0.13.1",
    "typescript": "^2.2.1",
    "url-loader": "^0.5.7",
    "vue": "^2.2.2",
    "vue-loader": "^11.1.4",
    "vue-property-decorator": "^5.0.1",
    "vue-router": "^2.3.0",
    "vue-template-compiler": "^2.2.2",
    "webpack": "^2.2.0",
    "webpack-cli": "^3.3.2",
    "webpack-hot-middleware": "^2.12.2"   

【问题讨论】:

【参考方案1】:

如果您没有在构造阶段初始化属性,您应该明确指出它可能是未定义的:

parentData: Client | undefined;

要为@Prop 装饰成员分配默认值,您应该使用装饰器的default 参数:

@Prop( default: () => new Client) 
parentData: Client | undefined;

或者,作为不推荐选项,您可以将"strictPropertyInitialization": false 添加到您的打字稿编译器选项中。

更新 1:

这种情况最合适的解决方法是使用在 typescript 2.7 中引入的definite assignment assertion modifiers。将它与默认的 Prop 装饰器初始化结合起来应该可以解决问题:

@Prop( default: () => new Client ) 
parentData!: Client;

【讨论】:

事情是,parentData 永远不能未定义,因为属性是从 Parent 传入的。明确说明它可能是未定义的,这迫使我在我使用它的任何地方都检查它是否未定义——这不必要地使代码混乱。假设我确实输入了默认值以及未定义的潜力,这对我来说没有意义 - 它至少总是一个新的 Client() 并且因此永远不会未定义 - 对吧? 是的,你是对的。我为您的案例更新了解决方法的答案。【参考方案2】:

也许我来晚了一点,但如果你在 Typescript 中编写 Vue,你可能想要使用 PropSync 而不是 vue-property-decorator 提供的 Prop

例如,您有以下内容:

@Prop() propArrayName!: type[];

您可以使用:

@PropSync('propArrayName',  type: Array ) _localArrayVariable!: type[];

这样你就可以避免改变 Prop() 而是计算 prop()...你可以在这里阅读更多内容:

https://github.com/kaorun343/vue-property-decorator#-propsyncpropname-string-options-propoptions--constructor--constructor---decorator

【讨论】:

以上是关于Vue 2 + TypeScript:避免直接改变 Prop - 在带有 vue-property-decorator 的基于类的组件中的主要内容,如果未能解决你的问题,请参考以下文章

Vue关闭组件返回避免直接改变道具

Vue:props 不会自动分配;手动分配时 - 避免直接改变道具 - 错误

[Vue 警告]:避免直接改变 prop

Vue 2.5中将迎来有关TypeScript的改变!

Vue警告避免改变道具“taskToEdit”

避免在可重用组件中直接改变 prop