Bind vuex state and mutations to checkbox component properties in TypeScript-based Vue
将复选框创建为 Vue 组件,其中:
试试 1
概念
复选框组件有 checked 和 onClick 属性,它们的值是偏离的,可以是动态的。
零件
帕格语模板:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
label.SvgCheckbox–LabelAsWrapper(:class=“rootElementCssClass” @click.prevent=“onClick”)
input.SvgCheckbox–InvisibleAuthenticCheckbox( type=“checkbox” :checked=“checked” :disabled=“disabled” ) svg(viewbox=‘0 0 24 24’).SvgCheckbox–SvgCanvas path( v–if=“!checked” d=‘M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z’ ).SvgCheckbox–SvgPath.SvgCheckbox–SvgPath__Unchecked path( v–else d=‘M10,17L5,12L6.41,10.58L10,14.17L17.59,6.58L19,8M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z’ ).SvgCheckbox–SvgPath.SvgCheckbox–SvgPath__Checked span(v–if=“text”).SvgCheckbox–AppendedText {{ text }} |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 |
import { Vue, Component, Prop } from ‘vue-property-decorator’;
@Component @Prop({ type: Boolean, required: true }) private readonly checked!: boolean; @Prop({ type: Boolean, default: false }) private readonly disabled!: boolean; @Prop({ type: String }) private readonly text?: string; @Prop({ type: Function, default: () => {} }) private readonly onClick!: () => void; |
存储模块
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import { VuexModule, Module, Mutation } from“vuex-module-decorators”;
import store, { StoreModuleNames } from“@Store/Store”;
@Module({ name: StoreModuleNames.example, store, dynamic: true, namespaced: true }) private _doNotPreProcessMarkupEntryPointsFlag: boolean = true; public get doNotPreProcessMarkupEntryPointsFlag(): boolean { @Mutation |
用法
1
2 3 4 5 |
SimpleCheckbox(
:checked=“relatedStoreModule.doNotPreProcessMarkupEntryPointsFlag” :onClick=“relatedStoreModule.toggleDoNotPreProcessMarkupEntryPointsFlag” parentElementCssClass=“RegularCheckbox” ) |
1
2 3 4 5 6 7 8 9 10 |
import { Component, Vue } from“vue-property-decorator”;
import { getModule } from“vuex-module-decorators”; import ExampleStoreModule from“@Store/modules/ExampleStoreModule”; import template from“@Templates/ExampleTemplate.pug”; import SimpleCheckbox from“@Components/Checkboxes/MaterialDesign/SimpleCheckbox.vue”; @Component({ components: { SimpleCheckbox } }) |
华林斯
点击复选框时出现。复选框按我们的需要工作,但是违反了一些 Vue 概念。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
vue.common.dev.js:630 [Vue warn]: $attrs is readonly.
found in —> <SimpleCheckbox> at hikari–frontend/UiComponents/Checkboxes/MaterialDesign/SimpleCheckbox.vue vue.common.dev.js:630 [Vue warn]: $listeners is readonly. found in —> <SimpleCheckbox> at hikari–frontend/UiComponents/Checkboxes/MaterialDesign/SimpleCheckbox.vue vue.common.dev.js:630 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re–renders. Instead, use a data or computed property based on the prop‘s value. Prop being mutated:”checked” found in —> <SimpleCheckbox> at hikari-frontend/UiComponents/Checkboxes/MaterialDesign/SimpleCheckbox.vue |
沉思
此警告经常发出,原因是某些 vue 属性的新值已在组件内部分配。明确地说,我没有进行这样的操作。
问题出在 :onClick=”relatedStoreModule.toggleDoNotPreProcessMarkupEntryPointsFlag” 中。看起来它编译为类似 <component>.$props.onClick=”<vuex store manipulations …>” 的东西 – 如果是这样,它是组件内部的隐式属性突变。
试试 2
概念
基于 Vue 文档,自定义组件部分:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Vue.component(‘base-checkbox’, {
model: { prop: ‘checked’, event: ‘change’ }, props: { checked: Boolean }, template: ` <input type=“checkbox” v–bind:checked=“checked” v–on:change=“$emit(‘change’, $event.target.checked)” > ` }) |
带有 vue-property-decorator 的 TypeScript 的等价物是:
1
2 3 4 5 6 |
import { Vue, Component, Model } from ‘vue-property-decorator’
@Component |
零件
1
2 3 4 5 6 7 8 9 |
label.SvgCheckbox–LabelAsWrapper(:class=“rootElementCssClass”)
input.SvgCheckbox–InvisibleAuthenticCheckbox( type=“checkbox” :checked=“checked” :disabled=“disabled” @change=“$emit(‘change’, $event.target.checked)” ) svg(viewbox=‘0 0 24 24’).SvgCheckbox–SvgCanvas // … |
1
2 3 4 5 6 7 8 9 10 11 12 |
import { Vue, Component, Prop, Model } from“vue-property-decorator”;
@Component @Model(‘change’, { type: Boolean }) readonly checked!: boolean; @Prop({ type: Boolean, default: false }) private readonly disabled!: boolean; @Prop({ type: String }) private readonly text?: string; |
用法
1
2 3 4 |
SimpleCheckbox(
v–model=“doNotPreProcessMarkupEntryPointsFlag” rootElementCssClass=“RegularCheckbox” ) |
在 TypeScript 中,要使用 v-model,我们需要声明 getter 和同名 setter:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Component({
template, components: { SimpleCheckbox, // … } }) export default class MarkupPreProcessingSettings extends Vue { private readonly relatedStoreModule: MarkupPreProcessingSettingsStoreModule = private set doNotPreProcessMarkupEntryPointsFlag(_newValue: boolean) { |
警告
相同的错误集:
限制
首先,我们需要在 Vue 组件类中创建新的 getter 和 setter。如果可能的话,避免 id 会很酷。不幸的是,对于 vuex 类(通过 vuex-module-decorators),TypeScript setter 不可用,我们需要使用 @Mutation-decorated 方法。
此外,此解决方案不适用于 v-for 呈现的元素。它使这个解决方案毫无用处。
尝试 3
概念
事件发射器和自定义事件监听器的使用。此解决方案也可以正常工作,但 Vue 会发出警告。
零件
1
2 |
label.SvgCheckbox–LabelAsWrapper(:class=“rootElementCssClass” @click.prevent=“$emit(‘toggled’)”)
// … |
用法
1
2 3 4 5 |
SimpleCheckbox(
:checked=“relatedStoreModule.doNotPreProcessMarkupEntryPointsFlag” @toggled=“relatedStoreModule.toggleDoNotPreProcessMarkupEntryPointsFlag” rootElementCssClass=“RegularCheckbox” ) |
警告
更新
还有一些谜题,但是问题已经解决了。请参阅下面的答案。
- label.SvgCheckbox-LabelAsWrapper – 这是什么东西?如果您使用的是外部库,则可以标记它们并在问题中提及它们。
- @MatJ,它是 Pug,预处理语言。如果您不熟悉 Pug 获取预处理 HTML,请使用此工具。
此警告出现在 Electron 应用程序中。 SimpleCheckbox 来自 node_modules,但是这个库还在开发中,所以它是由 npm link 提供的。
当我试图进行复制时,我为浏览器创建了 SPA,并将 SimpleCheckbox 放置到同一个项目中(不是从 node_modules 获得的)。第一个解决方案有效! (我不在乎第二个和第三个 – 我只需要从剥离优雅的解决方案中提炼)。
我建议原因是 npm link,发布我的库并通过 npm install 安装它。警告消失了!
结论
npm link 引起这样的问题已经不是第一次了。这是另一种情况。
我还是没有深入理解这个案例——我刚刚发布了一些实验数据。”那么,如果图书馆还在开发中呢?”问题仍然没有答案。我尝试了 Lerna – 第一次警告消失了,但是当我将我的项目移动到 Lerna 时,警告再次出现 – 我还不清楚规律性。
我不确定这是基于typescript的问题。
根据您的警告信息和代码,我注意到您使用 prop 作为 input 模型。
默认情况下,prop是不允许变异的。
改变 prop 可能是个坏主意,即使它是 Object 或 Array。 (如果 prop 是 Object 或 Array,它可以在 children 中变异。但不推荐)
为避免出现此警告,您可以在子项中使用作为 prop 克隆的数据,如下所示:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
props: {
checked: { type: Boolean, default: false, }, change: { type: Function, default: () => {}, } }, data: { checkedModel: false, }, mounted() { this.checkedModel = this.checked; // init model value as prop } |
- 谢谢你的回答。不幸的是,它不适用于 <input :checked=”checkedModel” /> 和 <input v-model=”checkedModel” />。
来源:https://www.codenong.com/58110755/