关于子组件可以通过 props 修改父组件中的复杂数据但不能修改简单数据类型

398 阅读2分钟

直接先看代码:

html 结构:

<div id="app">
    <menu-item :pstr='pstr' :parr='parr'></menu-item>
</div>

vue 实例:

Vue.component('menu-item', {
    props: ['pstr', 'parr'],
    mounted() {
    	// 修改简单数据类型报错
    	this.pstr = 'abc';
        // 修改复杂数据类型成功
        this.parr.push(lemon);
    }
});
var vm = new Vue({
    el: '#app',
    data: {
        pstr: 'hello',
        parr: ['apple', 'orange', 'banana']
    }
});

原理:

我们将整个父组件给子组件传递数据这个操作看做是一个函数的实参赋形参。

props: ['pstr', 'parr'] 这一步相当与是函数的形参。

:pstr='pstr' 这一步相当与对应形参传递实参。

当函数进行实参赋值时,相当于是一个简单的赋值操作:

  • 简单数据类型的赋值操作是深拷贝,复杂数据类型的赋值的浅拷贝
  • 复杂数据类型的数据存储在中的,所以当我们对复杂数据类型进行操作时是对中的数据进行操作,这时父组件中的复杂数据会发生改变,因为都是一个地址
  • 简单数据类型的数据就存在于中,所以操作会直接导致创建新的数据,这时父组件的简单数据不会发生改变,因为产生了新数据,并不是父组件那个简单数据

所以当我们通过子组件来修改父组件的字符串时会失败,而给数组添加内容时会添加成功。

原理代码

function fn(str,arr) {
	str = '123';
    arr.push(233);
}

let str = 'abc';
let arr = [1, 2, 3];

fn(str,arr);

// 这时 str 并没有发生改变,还是 abc
// 而 arr 已经发生改变,变成了 [1, 2, 3, 233]
console.log(str,arr)

总结

这就是因为简单数据类型是深拷贝(拷贝新数据),在经过函数实参赋值形参这种操作时,不会影响原数据。

而复杂数据类型是浅拷贝(拷贝的是地址),在进过函数实参赋值形参操作时,会改变到 堆 中的内容,就会影响所有该地址的数据