vue中父组件传递参数到子组件,值,对象,数组

61 阅读2分钟

在 Vue 中,父组件向子组件传递参数(props)时,可以传递 基本类型(值)对象 或 数组,但需要注意它们的 响应性 和 可变性。以下是详细说明:


1. 传递基本类型(值)

父组件传递 字符串、数字、布尔值 等基本类型时,子组件接收的是 单向数据流(子组件不能直接修改父组件的值)。

父组件

vue

复制

下载

<template>
  <ChildComponent 
    :title="title" 
    :count="count" 
    :is-visible="isVisible" 
  />
</template>

<script>
export default {
  data() {
    return {
      title: "Hello Vue",  // 字符串
      count: 10,           // 数字
      isVisible: true      // 布尔值
    };
  }
};
</script>

子组件

vue

复制

下载

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>Count: {{ count }}</p>
    <p v-if="isVisible">This is visible</p>
  </div>
</template>

<script>
export default {
  props: {
    title: String,       // 字符串类型
    count: Number,       // 数字类型
    isVisible: Boolean   // 布尔类型
  }
};
</script>

⚠️ 注意

  • 子组件不能直接修改 props,否则会报错(Vue 遵循单向数据流)。

  • 如果需要修改,可以在子组件内部用 data 或 computed 接收:

    javascript

    复制

    下载

    data() {
      return {
        localCount: this.count  // 用 data 接收
      };
    },
    computed: {
      doubleCount() {
        return this.count * 2;  // 用 computed 计算
      }
    }
    

2. 传递对象(Object)

如果父组件传递的是 对象,子组件接收的是 引用,修改对象的属性会影响父组件(因为 Vue 默认是 浅响应式)。

父组件

vue

复制

下载

<template>
  <ChildComponent :user="user" />
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: "Alice",
        age: 25
      }
    };
  }
};
</script>

子组件

vue

复制

下载

<template>
  <div>
    <p>Name: {{ user.name }}</p>
    <p>Age: {{ user.age }}</p>
    <button @click="changeName">Change Name</button>
  </div>
</template>

<script>
export default {
  props: {
    user: Object  // 对象类型
  },
  methods: {
    changeName() {
      this.user.name = "Bob";  // 直接修改对象的属性(会影响父组件!)
    }
  }
};
</script>

⚠️ 注意

  • 直接修改 props 对象的属性会影响父组件(因为对象是引用传递)。

  • 如果不想影响父组件,可以 深拷贝

    javascript

    复制

    下载

    data() {
      return {
        localUser: JSON.parse(JSON.stringify(this.user))  // 深拷贝
      };
    }
    

3. 传递数组(Array)

数组也是 引用类型,直接修改数组的元素会影响父组件。

父组件

vue

复制

下载

<template>
  <ChildComponent :items="items" />
</template>

<script>
export default {
  data() {
    return {
      items: ["Apple", "Banana", "Orange"]
    };
  }
};
</script>

子组件

vue

复制

下载

<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item">{{ item }}</li>
    </ul>
    <button @click="addItem">Add Item</button>
  </div>
</template>

<script>
export default {
  props: {
    items: Array  // 数组类型
  },
  methods: {
    addItem() {
      this.items.push("Grape");  // 直接修改数组(会影响父组件!)
    }
  }
};
</script>

⚠️ 注意

  • 直接修改 props 数组(如 pushsplice)会影响父组件

  • 如果不想影响父组件,可以 拷贝数组

    javascript

    复制

    下载

    methods: {
      addItem() {
        const newItems = [...this.items, "Grape"];  // 创建新数组
        this.$emit("update-items", newItems);      // 通知父组件更新
      }
    }
    

4. 动态响应式更新

如果希望父组件的 props 变化时子组件能响应,可以使用:

  • watch 监听 props 变化:

    javascript

    复制

    下载

    watch: {
      items(newVal) {
        console.log("Items changed:", newVal);
      }
    }
    
  • computed 计算新值:

    javascript

    复制

    下载

    computed: {
      filteredItems() {
        return this.items.filter(item => item.startsWith("A"));
      }
    }
    

总结

类型传递方式是否影响父组件推荐做法
基本类型(String、Number、Boolean)值传递❌ 不影响用 data 或 computed 接收
对象(Object)引用传递✅ 会影响(修改属性时)深拷贝或 emit 通知父组件
数组(Array)引用传递✅ 会影响(pushsplice 时)创建新数组或 emit 通知父组件

最佳实践

  • 避免直接修改 props,用 data 或 computed 接收。
  • 对象/数组修改时,尽量用 $emit 通知父组件更新,而不是直接修改。

这样能保证数据流清晰,避免意外的副作用! 🚀