vue-property-decorator @Model does't work in Vue3

133 views Asked by At

I am currently implementing an application migration from Vue2 to Vue3.
In the Vue2 application (vue-class-component+vue-property-decorato), it is implemented with class-style.
For large scale applications, we are trying to implement it with class-style in Vue3 as a first step.
The two things we want to achieve are as follows

  • Communicate SmSwitch v-switch changes to DecoratorView
  • Dynamically change isSwitch in DecoratorView

Console log when switching v-switches enter image description here

I need help resolving this.Please advise.

/** DecoratorView.vue(ParentComponent) **/
<template>
  <div class="home">
    <h1>new view</h1>
    <decorator-organism text="component" flg :obj="obj" />
    <!-- <decorator-organism flg :obj="obj" /> -->
    <v-btn @click="changeObj" text="changeObj" />
    <p>obj.age = {{ obj.age }}</p>
    <sm-switch v-model="isSwitch" @update:modelValue="updateIsSwitch" />
    <!-- <sm-switch :onSwitch="isSwitch" @change="onChangeSwitch" /> -->
    <p>{{ mixinText }}</p>
  </div>
</template>

<script lang="ts">
import { defineAsyncComponent } from "vue";
import { Component, Watch, Mixins } from "vue-property-decorator";
import { Options, Vue } from "vue-class-component";
import SmMixin from "@/components/SmMixin";

Vue.registerHooks(["beforeRouteLeave"]);

@Options({
  components: {
    DecoratorOrganism: defineAsyncComponent(
      () => import("@/components/decoratorComponent/DecoratorOrganism.vue")
    ),
    SmSwitch: defineAsyncComponent(
      () => import("@/components/decoratorComponent/SmSwitch.vue")
    ),
  },
})
export default class DecoratorView extends Mixins(SmMixin) {
  obj = objectMock;
  isSwitch = false;
  switch2 = false;

  private updateIsSwitch(newValue: boolean): void {
    this.isSwitch = newValue;
  }

  private changeObj(): void {
    this.obj.age = this.obj.age + 1;
  }

  private onChangeSwitch(newValue: boolean): void {
    console.log("onChangeSwitch excuted");
    console.log(newValue);
    this.isSwitch = newValue;
    console.log(this.isSwitch);
  }

  get mixinText(): string {
    return this.$isFlg ? "true" : "false";
  }

  beforeRouteLeave(): void {
    console.log("leave");
  }

  @Watch("obj.age")
  printOut() {
    console.log("watch func start");
  }

  @Watch("isSwitch")
  printSwitch() {
    console.log("printSwitch");
    console.log(this.isSwitch);
  }
}

const objectMock = {
  name: "hoge",
  age: 28,
  sex: "male",
};
</script>

/** SmSwitch.vue(ChildComponent) **/
<template>
  <div>
    <v-switch
      :value="state"
      color="secondary"
      @update:modelValue="onChangeSwitch"
    />
    <!-- <v-switch :value="onSwitch" color="secondary" @change="onChangeSwitch" /> -->
  </div>
</template>

<script lang="ts">
import { Vue, Options } from "vue-class-component";
import { Prop, Model } from "vue-property-decorator";

@Options({})
export default class SmSwitch extends Vue {
  @Prop({ type: Boolean, default: false })
  @Model("update:modelValue", { type: Boolean })
  private readonly onSwitch!: boolean;

  private get state(): boolean {
    return this.onSwitch;
  }

  private set state(newValue: boolean) {
    console.log("child-component setter execute");
    console.log(newValue);
    console.log(this.onSwitch);
    this.$emit("update:modelValue", this.state);
  }

  private onChangeSwitch(newValue: boolean) {
    console.log("onChangeSwitch start");
    console.log(newValue);
    this.state = newValue;
    this.$emit("update:modelValue", this.state);
  }
}
</script>

pacakge.json is here.

{
  "name": "vee-validate-tutorial",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@vee-validate/i18n": "^4.11.8",
    "@vee-validate/rules": "^4.11.8",
    "core-js": "^3.8.3",
    "vue": "^3.3.7",
    "vue-class-component": "^8.0.0-rc.1",
    "vue-facing-decorator": "^3.0.4",
    "vue-property-decorator": "^9.1.2",
    "vue-router": "^4.0.3",
    "vuex": "^4.0.0",
    "yup": "^1.3.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.4.0",
    "@typescript-eslint/parser": "^5.4.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-typescript": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "@vue/compat": "^3.3.4",
    "@vue/eslint-config-typescript": "^9.1.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-vue": "^8.0.3",
    "prettier": "^2.4.1",
    "typescript": "~4.5.5",
    "vee-validate": "^4.11.8",
    "vuetify": "^3.3.20"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/vue3-essential",
      "eslint:recommended",
      "@vue/typescript/recommended",
      "plugin:prettier/recommended"
    ],
    "parserOptions": {
      "ecmaVersion": 2020
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead",
    "not ie 11"
  ]
}

I've tried vue-facing-decorator, but gave up.
Because mixins did not work well.

I've tried vue-facing-decorator, but gave up. Because mixins did not work well.

0

There are 0 answers