【问题标题】:Changing the element of an array created from the props inside the child component also affect the parent component's props | Vuejs 3更改从子组件内部的 props 创建的数组元素也会影响父组件的 props | Vuejs 3
【发布时间】:2021-09-20 20:57:39
【问题描述】:

我有一个父组件(App),其中有一个对象数组。我将此数组作为道具传递给子组件(UserLocations)。现在在子组件中,我使用这个数组并创建一个数据变量。

所以如果我要更改数组的一个元素,那么为什么父组件的属性也会更改。

App.Vue

<template>
  <user-locations :initalLocations="locations"/>
</template>

<script>
import UserLocations from './components/UserLocations.vue'

export default {
  name: 'App',
  components: {
    UserLocations
  },
  mounted() {
  },
  data: function() {
    return {
      locations: [
        {"id": 121, name: "test 121", "order": 1},
        {"id": 122, name: "test 122", "order": 2},
        {"id": 123, name: "test 123", "order": 3},
        {"id": 124, name: "test 124", "order": 4}
      ]
    }
  }
}
</script>

UserLocations.vue

<template>
    <ul>
        <li v-for="(location) in locations"
        :key="location.id"
        > 
        <span @click="decreaseOrder(location)">Up</span>
        {{ location.name}} {{location.order}}
        <span @click="increaseOrder(location)">down</span>
        </li>
    </ul>
</template>
<script>

export default {
    data: function() {
        return {
            locations: [...this.initalLocations]
        }
    },
    props: {
        initalLocations: { 
            type: Array,
        },
    },
    // computed: {
    //     locations() {
    //         return [
    //             ...this.initalLocations
    //         ]
    //     }
    // },
    methods:{
        increaseOrder(location) {
            if (location.order != this.locations.length) {
                this.locations = this.locations.map(l => {
                    var returnLocation = {...l};
                    if (l.id == location.id) {
                        l.order += 1
                    }
                    return returnLocation
                });
            }
        },
        decreaseOrder(location) {
            if (location.order != 1) {
                this.locations = this.locations.map(l => {
                    var returnLocation = {...l};
                    if (l.id == location.id) {
                        l.order -= 1
                    }
                    return returnLocation
                });
            }
        },
    }
}
</script>

如您所见,我使用 initalLocations 道具在 UserLocations 组件中创建 location 道具,当​​我通过单击向上/向下按钮更改数组对象之一时,它会更改传递给 UserLocations 的道具而不是更改本地数据“位置”

【问题讨论】:

  • 我也是这么想的,因为当我提出问题时,5-7 秒后有人投了反对票。连这个问题都需要2-3分钟才能理解。
  • 试试locations: this.initalLocations.slice()而不是locations: [...this.initalLocations]
  • 仍在更新 prop 而不是本地数据 'locations;
  • 我从这里读到的东西是孩子内部的突变会影响父母,但我想使用传播我们可以获得一个新的数组参考。 v3.vuejs.org/guide/component-props.html#one-way-data-flow
  • 扩展运算符不会深度克隆数组

标签: javascript arrays vue.js spread


【解决方案1】:

扩展运算符不会深度克隆数组,您需要一个克隆数组而不是引用它的函数:

<script>
function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }


    if (obj instanceof Array) {
        return obj.reduce((arr, item, i) => {
            arr[i] = deepCopy(item);
            return arr;
        }, []);
    }

    if (obj instanceof Object) {
        return Object.keys(obj).reduce((newObj, key) => {
            newObj[key] = deepCopy(obj[key]);
            return newObj;
        }, {})
    }
}

export default {
    data: function() {
        return {
            locations: deepCopy(this.initalLocations)
        }
    },
...

【讨论】:

  • 感谢您的更正。是的,我要么使用你的函数,要么使用locations: JSON.parse(JSON.stringify(this.initalLocations))(可能会将 undefined 转换为 null)或 lodash(第三方)的深度克隆函数。反正有时候我会忘记最新的 js 函数的功能。
猜你喜欢
  • 2018-07-31
  • 2020-07-26
  • 1970-01-01
  • 2016-06-03
  • 2021-01-15
  • 1970-01-01
  • 2016-04-18
  • 2020-07-30
  • 1970-01-01
相关资源
最近更新 更多