Vue2.0 饿了么报错:Avoid mutating a prop directly since the value will be overwritten whenever

本文探讨了Vue.js中单向数据流的概念,解释了为什么子组件不能直接修改父组件通过Prop传递的值,并提供了解决方案。通过定义本地data属性并使用Prop作为初始值,可以实现组件状态的更新,同时确保数据流的正确性。

 报错原因:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。(父组件更新,子组件中的prop值也会更新,但子组件不能修改由父组件传递过来的值)

 解决办法:

    定义一个本地的 data 属性并将这个 prop 用作其初始值,同步对组件的修改,再通知父组件更新

相关代码:

<div class="rating-type">
  <span @click="select(2,$event)" class="block positive" :class="{'active': selectedtype === 2}">{{desc.all}}
    <span class="count">47</span>
  </span>
  <span @click="select(0,$event)" class="block positive" :class="{'active': selectedtype === 0}">{{desc.positive}}
    <span class="count">50</span>
  </span>
  <span @click="select(1,$event)" class="block negative" :class="{'active': selectedtype === 1}">{{desc.negative}}
    <span class="count">47</span>
  </span>
</div>

 子组件:

data() {
  return {
    typeSelected: this.selectType,
    contOnly: this.onlyContent
  };
},
methods: {
  select(type, event) {
    if (!event._constructed) {
      return;
    }
    this.typeSelected = type;
    this.$emit('change', type);
  },
  toggleContent(event) {
    if (!event._constructed) {
      return;
    }
    this.contOnly = !this.contOnly;
    this.$emit('toggle', this.contOnly);
  }
}

父组件:

<ratingselect :select-type="selectType" :only-content="onlyContent"
:desc="desc" :ratings="food.ratings"
 @change="change" @toggle="toggle"></ratingselect>
methods: {
  //  子组件更新的值
  change(type) {
    this.selectType = type;
  },
  toggle(val) {
    this.onlyContent = val;
  },
  //  子组件更新的值==结束

效果图:

官方文档链接:https://cn.vuejs.org/v2/guide/components-props.html

### Vueprop 'maxDate'类型检查失败以及避免直接修改prop的问题解决方案 在Vue组件开发中,`prop`的类型校验是一个常见且重要的环节。当遇到`type check failed for prop "maxDate". Expected Date, got Object`这样的错误时,通常意味着传递给`maxDate`的值不符合其预期的数据类型(即`Date`类型),而是传递了一个`Object`类型的值[^1]。 以下是对该问题的详细分析与解决方法: --- #### 问题原因分析 1. **数据来源问题**: 如果从后端获取数据,可能返回的是时间字符串或时间戳,而不是JavaScript中的`Date`对象。例如,后端可能返回类似`"2023-10-01T00:00:00Z"`这样的ISO格式字符串,而前端直接将其作为`maxDate`的值传递给组件,导致类型校验失败[^1]。 2. **数据转换问题**: 在定义`prop`时明确指定了`maxDate`的类型为`Date`,但如果传递的值未被正确转换为`Date`对象,则会触发类型校验错误。例如: ```javascript props: { maxDate: { type: Date, required: true } } ``` 3. **默认值问题**: 如果在定义`prop`时设置了默认值,但默认值不是`Date`类型,也会导致校验失败。例如: ```javascript props: { maxDate: { type: Date, default: () => ({}) // 默认值为一个空对象,而非Date实例 } } ``` 4. **直接修改`prop`问题**: 在Vue中,直接修改父组件传递的`prop`是不推荐的,因为这会导致数据流的混乱,并且可能会引发不可预期的行为。如果需要修改`prop`的值,应该通过`watch`监听器或其他方式创建本地副本进行操作[^2]。 --- #### 解决方案 1. **确保传递正确的`Date`对象**: 在将数据传递给子组件之前,确保将其转换为`Date`对象。例如: ```javascript const maxDate = new Date("2023-10-01T00:00:00Z"); this.$emit('update:maxDate', maxDate); ``` 2. **在父组件中进行数据转换**: 如果从后端接收到的时间是字符串格式,可以在父组件中将其转换为`Date`对象后再传递给子组件: ```javascript axios.get('/api/date') .then(response => { const maxDate = new Date(response.data.maxDate); // 转换为Date对象 this.maxDate = maxDate; }); ``` 3. **设置合理的默认值**: 在定义`prop`时,确保默认值是一个`Date`对象。例如: ```javascript props: { maxDate: { type: Date, default: () => new Date() // 默认值为当前日期 } } ``` 4. **使用`watch`监听并转换数据**: 如果需要动态处理传递的数据,可以在子组件中使用`watch`监听`prop`的变化,并在必要时进行转换: ```javascript watch: { maxDate(newVal) { if (typeof newVal === 'string') { this.localMaxDate = new Date(newVal); // 转换为Date对象 } else { this.localMaxDate = newVal; } } }, data() { return { localMaxDate: null }; } ``` 5. **调整后端接口返回值**: 如果条件允许,可以要求后端直接返回`Date`对象或更易于前端处理的时间格式(如时间戳)。例如,返回时间戳`1696108800000`,然后在前端通过以下方式转换为`Date`对象: ```javascript const maxDate = new Date(1696108800000); ``` 6. **避免直接修改`prop`**: 如果需要对`maxDate`进行修改,建议在子组件中创建一个本地副本,而不是直接修改`prop`。例如: ```javascript props: { maxDate: { type: Date, required: true } }, data() { return { localMaxDate: null }; }, watch: { maxDate(newVal) { this.localMaxDate = newVal; // 创建本地副本 } } ``` --- ### 示例代码 以下是一个完整的示例,展示如何正确传递和处理`maxDate`: ```vue <template> <div> <child-component :max-date="maxDate"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { maxDate: null }; }, created() { this.fetchMaxDate(); }, methods: { fetchMaxDate() { axios.get('/api/max-date') .then(response => { this.maxDate = new Date(response.data.maxDate); // 确保传递的是Date对象 }); } } }; </script> ``` ```javascript // ChildComponent.vue export default { props: { maxDate: { type: Date, required: true, default: () => new Date() // 默认值为当前日期 } }, data() { return { localMaxDate: null }; }, watch: { maxDate(newVal) { this.localMaxDate = newVal; // 创建本地副本 } } }; ``` --- ### 注意事项 - 确保在数据传递过程中始终遵循Vue组件的`prop`类型定义。 - 如果需要动态处理数据,建议在父组件中完成转换逻辑,避免子组件承担过多职责。 - 使用`Date`对象时需注意时区差异,确保前后端时间一致[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值