Vue中父子组件传值的方式和场景分析
更新时间:2023-07-08
## 父组件向子组件传值
在 Vue 中,我们可以通过 props 属性将父组件的属性传递给子组件,这是一个非常常见的用法。
### 如何传值?
我们可以通过在子组件中定义 props 来接受父组件传递的值,例如:
```html
```
## 子组件向父组件传值
除了父组件向子组件传值以外,Vue 还支持子组件向父组件传值。
### 如何传值?
我们可以使用 Vue 的 $emit 方法来触发一个事件,并将需要传递的值包含在事件中。然后在父组件中监听这个事件,从而获取子组件传递过来的值。
例如,在一个表格组件中,我们需要在用户点击某一行时触发一个事件,并将该行对应的数据传递给父组件:
```html
```
这样当用户在表格中点击某一行时,子组件就会触发 row-click 事件,并将该行对应的数据传递给父组件中的 handleRowClick 方法,从而实现子组件向父组件传值的功能。
### 传值场景
子组件向父组件传值的适用场景有很多,比如:
1. 子组件需要向父组件传递用户的输入值,从而实现一些特定的功能;
2. 子组件需要向父组件传递某个状态的变化,从而让父组件知道这个状态的变化并做出相应的响应;
3. 子组件中有一些复杂的计算逻辑,需要将计算结果传递给父组件。
例如,在一个评论组件中,我们需要在用户输入评论内容后,通过点击提交按钮触发一个事件,并将输入的内容传递给父组件进行发布:
```html
```
## 非父子组件之间的传值
除了父子组件之间和子组件向父组件传值之外,有时候我们还需要在非父子组件之间进行传值,这时候我们可以使用事件系统或者 Vuex 状态管理器来实现。
### 如何传值?
#### 事件系统
在 Vue 中,我们可以借助事件系统来实现非父子组件之间的传值。我们可以使用 Vue 的实例作为 event bus 来实现。
首先,我们需要创建一个空的 Vue 实例作为 event bus:
```javascript
// eventBus.js
import Vue from 'vue';
export const eventBus = new Vue();
```
然后,在需要传值的组件中,我们可以使用 event bus 发送一个事件,并将需要传递的数据包含在事件中。而在需要接受数据的组件中,则可以通过监听该事件来获取数据。
例如,在一个购物车应用中,我们需要在用户点击结算按钮时将商品数据传递给一个弹窗组件:
```html
```
在上面的代码中,我们首先定义了一个 eventBus,并将其导出供其他组件使用。然后在商品列表组件中,当用户点击结算按钮时,我们使用 event bus 发送了一个名为 checkout 的事件,并将该组件中的产品数据作为参数传递了进去。而在弹窗组件中,我们在 created 钩子函数中监听了该事件,并在事件处理函数中将传递过来的商品数据保存在本组件中,并进行一些其他的操作。
#### Vuex
如果我们在应用中需要做一些比较复杂的状态管理,那么使用 Vuex 状态管理器会比使用事件系统更为方便。
在 Vuex 中,我们可以使用 store 来存储和管理组件中的状态,并使用 getter、mutation 和 action 来改变 store 中的状态。
如果我们需要在多个组件之间共享状态,那么我们可以使用 Vuex 来管理这些状态。在这种情况下,每个组件都会通过读取这些状态来自动更新它们自己。下面是一个使用 Vuex 实现非父子组件之间传值的例子:
```html
```
```javascript
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
number1: 0,
number2: 0,
},
getters: {
result(state) {
return state.number1 + state.number2;
}
},
mutations: {
setNumber1(state, payload) {
state.number1 = payload;
},
setNumber2(state, payload) {
state.number2 = payload;
},
},
actions: {
calculate(context) {
context.commit('setNumber1', 1);
context.commit('setNumber2', 2);
}
}
});
```
在上面的代码中,我们首先创建一个 store 并导出。在 store 中,我们定义了两个状态 number1 和 number2,以及一个计算结果的 getter。然后定义了两个 mutation,用于修改 state 中的 number1 和 number2,以及一个 action,用于触发两个 mutation 从而改变状态。
在子组件中,我们使用了 mapGetters 函数来将 store 中的 result 状态映射到组件的 computed 中。而在孙子组件中,我们使用了 mapActions 函数将 store 的 calculate action 映射到组件的 methods 中,并在点击按钮时触发这个 action。
这样当用户在孙子组件中点击计算按钮时,组件就会触发对应的 action,从而修改 store 中的状态并自动更新子组件中的数据。
{{title}}
```
### 传值场景
父子组件传值的适用场景有很多,比如:
1. 将父组件中的状态传递给子组件,然后在子组件中展示或修改这些状态;
2. 将父组件中的方法传递给子组件,然后在子组件中调用这些方法;
3. 将一个复杂的对象或数组传递给子组件,以供子组件进行操作。
例如,在一个购物车应用中,我们需要在父组件中获取商品列表数据,并将这些数据传递给子组件用于展示和操作:
```html
- {{product.name}} - {{product.price}}
Name | Age | Gender |
---|---|---|
{{row.name}} | {{row.age}} | {{row.gender}} |
- {{product.name}} - {{product.price}}
确认购买以下商品:
- {{product.name}} - {{product.price}}
我是子组件
计算结果:{{result}}