草庐IT

关于javascript:在基于TypeScript的Vue中将vuex状态和突变绑定到复选框组件属性

codeneng 2023-03-28 原文

Bind vuex state and mutations to checkbox component properties in TypeScript-based Vue

问题

将复选框创建为 Vue 组件,其中:

  • 复选框组件内不允许有逻辑:所有事件处理程序以及 checked 属性都完全依赖于外部逻辑,可能是 vuex 存储。
  • 我们不应该看复选框"已选中"的状态:选中与否,这又取决于外部逻辑,例如。 G。 vuex 状态或吸气剂。
  • 试试 1

    概念

    复选框组件有 checkedonClick 属性,它们的值是偏离的,可以是动态的。

    零件

    帕格语模板:

    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
    export default class SimpleCheckbox extends Vue {

      @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: String }) private readonly parentElementCssClass?: 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 })
    export default class ExampleStoreModule extends VuexModule {

      private _doNotPreProcessMarkupEntryPointsFlag: boolean = true;

      public get doNotPreProcessMarkupEntryPointsFlag(): boolean {
        return this._doNotPreProcessMarkupEntryPointsFlag;
      }

      @Mutation
      public toggleDoNotPreProcessMarkupEntryPointsFlag(): void {
        this._doNotPreProcessMarkupEntryPointsFlag = !this._doNotPreProcessMarkupEntryPointsFlag;
      }
    }

    用法

    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 } })
    export default class MarkupPreProcessingSettings extends Vue {
      private readonly relatedStoreModule: ExampleStoreModule = getModule(ExampleStoreModule);
    }

    华林斯

    点击复选框时出现。复选框按我们的需要工作,但是违反了一些 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
           <MarkupPreProcessingSettings>
             <Application> at ProjectInitializer/ElectronRendererProcess/RootComponent.vue
               <Root>

    vue.common.dev.js:630 [Vue warn]: $listeners is readonly.

    found in

    ---> <SimpleCheckbox> at hikari-frontend/UiComponents/Checkboxes/MaterialDesign/SimpleCheckbox.vue
           <MarkupPreProcessingSettings>
             <Application> at ProjectInitializer/ElectronRendererProcess/RootComponent.vue
               <Root>

    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
           <MarkupPreProcessingSettings>
             <Application> at ProjectInitializer/ElectronRendererProcess/RootComponent.vue
               <Root>

    沉思

    此警告经常发出,原因是某些 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
    export default class YourComponent extends Vue {
      @Model('change', { type: Boolean }) readonly checked!: boolean
    }

    零件

    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
    export default class SimpleCheckbox extends Vue {

      @Model('change', { type: Boolean }) readonly checked!: boolean;

      @Prop({ type: Boolean, default: false }) private readonly disabled!: boolean;

      @Prop({ type: String }) private readonly text?: string;
      @Prop({ type: String }) private readonly rootElementCssClass?: 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 =
          getModule(MarkupPreProcessingSettingsStoreModule);
      //...
      private get doNotPreProcessMarkupEntryPointsFlag(): boolean {
        return this.relatedStoreModule.doNotPreProcessMarkupEntryPointsFlag;
      }

      private set doNotPreProcessMarkupEntryPointsFlag(_newValue: boolean) {
        this.relatedStoreModule.toggleDoNotPreProcessMarkupEntryPointsFlag();
      }
    }

    警告

    相同的错误集:

    限制

    首先,我们需要在 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 可能是个坏主意,即使它是 ObjectArray。 (如果 prop 是 ObjectArray,它可以在 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" />

    有关关于javascript:在基于TypeScript的Vue中将vuex状态和突变绑定到复选框组件属性的更多相关文章

    1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

      我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

    2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

      我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

    3. ruby-on-rails - 跳过状态机方法的所有验证 - 2

      当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

    4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

      对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

    5. ruby - Net::HTTP 获取源代码和状态 - 2

      我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

    6. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

      导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

    7. 基于C#实现简易绘图工具【100010177】 - 2

      C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

    8. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

      项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

    9. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

      需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

    10. ruby-on-rails - 为模型创建状态属性 - 2

      我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,

    随机推荐