首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将vue2.x的代码迁移到vue3.x时,遇到了v-model模块中"task“prop的意外突变

将vue2.x的代码迁移到vue3.x时,遇到了v-model模块中"task“prop的意外突变
EN

Stack Overflow用户
提问于 2021-11-04 04:07:59
回答 1查看 49关注 0票数 1

我在将项目从vue2.x迁移到vue3.0时使用了组合API,但是页面不能正常工作,在vue3.0中环境提示我有一个“任务的意外突变”错误,我想知道如何编写正确的compos API这是Vue2.x代码

代码语言:javascript
复制
<template>
  <transition name="fade">
    <div class="task" v-if="!task.deleted">
      <input :id="id" type="checkbox" v-model="task.done" />
      <label :for="id">{{ task.title }}</label>
      <transition name="fade">
        <span
          class="task_delete"
          v-show="task.done"
          @click="deleteTask({ task })"
        >
          <i class="fa fa-trash"></i>
        </span>
      </transition>
    </div>
  </transition>
</template>

<script>
import { mapMutations } from "vuex";
let GID = 1;
export default {
  props: {
    task: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      id: `task-${GID++}`,
    };
  },
  methods: {
    ...mapMutations(["deleteTask"]),
  },
};
</script>

<style lang="scss">
.task {
  display: flex;
  padding: 12px 0;
  border-bottom: 1px solid #eee;
  font-size: 14px;
}
.task input {
  display: none;
}
.task label {
  flex: 1;
  line-height: 20px;
}
.task label:before,
.task label:after {
  content: "";
  display: inline-block;
  margin-right: 20px;
  margin-top: 1px;
  width: 14px;
  height: 14px;
  vertical-align: top;
}
.task label:before {
  border: 1px solid #ccc;
  border-radius: 2px;
  background-color: white;
}
.task label:after {
  content: "\f00c";
  position: relative;
  display: none;
  z-index: 10;
  margin-right: -16px;
  width: 10px;
  height: 10px;
  padding: 3px;
  border-radius: 2px;
  font: normal normal normal 10px/1 FontAwesome;
  color: white;
  background-color: #ccc;
  float: left;
}
.task input:checked + label:after {
  display: inline-block;
}
.task_delete {
  padding: 0 10px;
  color: #ccc;
  font-size: 16px;
}
.fade-leave-to,
.fade-enter {
  opacity: 0;
}
.fade-enter-to,
.fade-leave {
  opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
  transition: all 0.3s ease;
}
</style>

这是Vue3.0代码使用组合API,但不工作

代码语言:javascript
复制
<template>
  <transition name="fade">
    <div class="task" v-if="!data.task.deleted">
      <input :id="id" type="checkbox" v-model="data.task.done" />
      <label :for="id">{{ data.task.title }}</label>
      <transition name="fade">
        <span
          class="task_delete"
          v-show="data.task.done"
          @click="deleteTask({ task })"
        >
          <i class="fa fa-trash"></i>
        </span>
      </transition>
    </div>
  </transition>
</template>

<script>
import { reactive } from "vue";
import { mapMutations } from "vuex";

let GID = 1;
export default {
  name: "Task",
  props: {
    task: {
      type: Object,
      required: true,
    },
  },
  setup(props) {
    const data = reactive({
      task: props.task,
      id: `task-${GID++}`,
    });
    return { data };
  },
  methods: {
    ...mapMutations(["deleteTask"]),
  },
};
</script>

<style lang="scss">
.task {
  display: flex;
  padding: 12px 0;
  border-bottom: 1px solid #eee;
  font-size: 14px;
}
.task input {
  display: none;
}
.task label {
  flex: 1;
  line-height: 20px;
}
.task label:before,
.task label:after {
  content: "";
  display: inline-block;
  margin-right: 20px;
  margin-top: 1px;
  width: 14px;
  height: 14px;
  vertical-align: top;
}
.task label:before {
  border: 1px solid #ccc;
  border-radius: 2px;
  background-color: white;
}
.task label:after {
  content: "\f00c";
  position: relative;
  display: none;
  z-index: 10;
  margin-right: -16px;
  width: 10px;
  height: 10px;
  padding: 3px;
  border-radius: 2px;
  font: normal normal normal 10px/1 FontAwesome;
  color: white;
  background-color: #ccc;
  float: left;
}
.task input:checked + label:after {
  display: inline-block;
}
.task_delete {
  padding: 0 10px;
  color: #ccc;
  font-size: 16px;
}
.fade-leave-to,
.fade-enter {
  opacity: 0;
}
.fade-enter-to,
.fade-leave {
  opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
  transition: all 0.3s ease;
}
</style>
EN

回答 1

Stack Overflow用户

发布于 2021-11-07 08:12:45

我认为问题是你在复选框中为道具使用了v-model,它会直接改变道具的值,而vue不允许这样做。尝试通过emit事件手动更新属性值。而且你不需要在子组件中使用带有reactive的道具,但需要在父组件中使用reactive的道具

代码语言:javascript
复制
<input :id="id" type="checkbox" v-value="task.done" @change="updateCheckbox($event)")/>  

在脚本中:

代码语言:javascript
复制
export default {
  name: "Task",
  props: {
    task: {
      type: Object,
      required: true,
    },
  },
  emits: ['updateCheckbox'],
  setup(props) {
    const data = reactive({
      id: `task-${GID++}`,
    });
    return { data };
  },
  methods: {
    updateCheckbox(e) {
       this.$emit('updateCheckbox', e.target.value)
    }
  },
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69834433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档