【Vue】组件传参、vuex状态管理

本文详细介绍了Vue中的组件间通信方法(props,$emit)、状态管理工具vuex、eventBus在多层组件间的通讯以及ref用于父子组件交互。同时提到了provide/inject的依赖注入方式。
摘要由CSDN通过智能技术生成

一、props:父组件向子组件传递数据(常用)

缺点:若组件嵌套层次多,传递数据比较麻烦

  • 父组件
  <template>
    <child :message="message"></child>
  </template>
  <script>
  import Child from './Child.vue'
  export default {
    components: {
      Child
    },
    data() {
      return {
        message: '父组件'
      }
    }
  }
  </script>
  • 子组件Child
  <template>
    <div>
      <span>{{message}}</span>
    </div>
  </template>
  <script>
  export default {
    props: {
      message: {
        type: String,
        default: '子组件'
      }
    }
  }
  </script>

二、$emit:子组件向父组件传递数据(常用)

  • 父组件
<template>
  <child :num="num" @addCount="addCount"></child>
</template>
<script>
import Child from "./Child.vue";
export default {
  components: {
    Child
  },
  data() {
    return {
      num: 100
    };
  },
  methods: {
    addCount(res) {
      //将子组件传来的参数复制给num
      this.num = res;
    }
  }
};
</script>

  • 子组件Child
<template>
  <div>
    <el-button type="primary" @click="addCount">{{ count++ }}</el-button>
  </div>
</template>
<script>
export default {
  props: {
    num: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      num: 100
    };
  },
  methods: {
    addCount() {
     //将num传给父组件
      this.$emit("addCount", this.num + 1);
    }
  }
};
</script>

三、vuex:状态管理,实现多个组件进行数据共享(常用,重点)

  • store.js
import Vuex from "vuex";
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex);
const store = new Vuex.Store({
  state: {
    //基本数据,用来存储变量。
    count: 0,
    list: [
      { id: 1, is: false },
      { id: 2, is: true }
    ]
  },
  getter: {
    //Getter类似于Vue的computed对象。是根据业务逻辑来处理State,使得生成业务所需的属性。
    listFilter: (state, getters) => {
      return state.list.filter(res => res.is);
    }
  },
  mutations: {
    //更改vuex的store中的状态的唯一方法,只能是同步操作。
    increment(state, payload) {
      state.count += payload;
    }
  },
  actions: {
    //Action 提交的是 mutation,而不是直接变更状态;
    //Action 可以包含任意异步操作。
    addCount({ commit }) {
      // context ({ dispatch, commit })是一个与 store 实例具有相同方法和属性的 context 对象
      setTimeout(() => {
        commit("increment");
      }, 1000);
    }
    //Action处理异步的正确使用方式
    // async actionA({ commit }) {
    //  commit('gotData', await a())
    // },
    // async actionB({ dispatch, commit }) {
    //   await dispatch('actionA') // 等待 actionA 完成
    //   commit('gotOtherData', await b())
    // }
  },
  module: {
    //模块化,module可以将store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter
  },
  //持久化
  plugins: [createPersistedState()],
});

  • 将store注入到根实例
// 注入到根实例-入口文件
new Vue({
  el: '#app',
  store,
  template: '<App/>',
  components: { App }
})
  • 组件A
<template>
  <div>
    <el-button type="primary" @click="addCount"></el-button>
  </div>
</template>
<script>
import { mapMutations, mapActions } from "vuex";
export default {
  // 原始写法
  // methods: {
  //     //改变状态count
  //     addCount() {
  //       this.$store.commit("increment", 5);
  //       this.$store.dispatch({
  //         type: "incrementAsync"
  //       });

  //     }
  //   }
  // };

  //mapMutations 辅助函数 获取
//mapActions 辅助函数 获取
  methods: {
    //方式1
    // ...mapMutations(["increment"]),
    //方式2
    ...mapMutations({
      // userInfo 是一个重新定义的别名,本组件可以直接调用这个方法名字使用
      increment1: "increment",
    }),

    //mapActions写法同mapMutation
    ...mapActions(["incrementAsync"]),

    //改变状态count
    addCount() {
      this.increment1(5);
      // 以对象形式分发Action
      this.incrementAsync(5);
    },
  },
};
</script>
  • 组件B
<template>
  <div>{{ count }}{{ listFilter }}</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
  // 原始写法
  // computed: {
  //   count() {
  //     // 获取vuex里的count
  //     return this.$store.state.count;
  //   },
  //   listFilter() {
  //     // 获取vuex里的listFilter
  //     return this.$store.getters.listFilter;
  //   },
  // }

  //mapState 辅助函数 获取
  //mapGetters 辅助函数 获取
  computed: {
    // 注意:这种写法用mapstate等这种辅助函数的时候,前面的方法名和获取的属性名是一致的
    ...mapState(["count"]),
    ...mapGetters(["listFilter"]),
  },
};
</script>

  • 模块化:将 store 分割为模块(module),每个模块拥有自己的 state 、 getters 、mutations 、actions 。(开发常用)

四、eventBus:常用于多层嵌套组件场景下兄弟组件或任意两个组件之间通讯(事件总线)

缺点:不支持响应式, $on事件不会自动清楚销毁的,需要手动来销毁,可在beforeDestroy中解绑监听,避免重复触发。

  • 入口文件添加事件总线
import Vue from 'vue';
// 添加事件总线
Vue.prototype.$eventBus = new Vue();
  • 组件A
<template>
  <div>
    {{ a }}
  </div>
</template>
  <script>
export default {
  data() {
    return {
      a: "",
    };
  },
  create() {
    this.$eventBus.$on("message", (res) => {
      //组件b传过来的参数
      this.a = res;
      console.log("收到消息!");
    });
  },
  // 组件销毁时需要解绑监听
  beforeDestroy() {
    eventBus.$off("message");
  },
};
</script>
  • 组件B
<template>
    <div>
   <span>{{a}}<span>
    </div>
  </template>
  <script>
  export default {
    data() {
      return {
        a: '兄弟组件'
      };
    },
    create() {
      this.eventBus.$emit('message',a)
    }
  };
  </script>

五、ref:通过$refs可以拿到子组件的实例,从而调用实例里的方法来实现父子组件通信

  • 父组件
<template>
  <el-button type="primary" @click="get">通过ref获取子组件实例</el-button>
 哦那个子组件获取的: {{ num }}
  <child ref="child"></child>
</template>
<script>
import Child from "./Child.vue";
export default {
  components: {
    Child
  },
  data() {
    return {
      num: 100
    };
  },
  methods: {
    get() {
      this.num = this.$refs.child.num;
    }
  }
};
</script>

  • 子组件Child
<template>
  <div>
    <el-button type="primary" @click="addCount">{{ num }}</el-button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      num: 100
    };
  },
  methods: {
    addCount() {
     this.num++;
    }
  }
};
</script>

待补充

六、provide / inject:通过依赖注入(inject / provide)的方式,向其所有子孙后代传递数据

缺点:无法监听数据修改的来源,不支持响应式。

  • 父组件
<template>
  <el-button type="primary" @click="get">通过ref获取子组件实例</el-button>
 哦那个子组件获取的: {{ num }}
  <child ref="child"></child>
</template>
<script>
import Child from "./Child.vue";
export default {
  components: {
    Child
  },
   // 提示:provide 和 inject 绑定不支持响应式。
  provide() {
    return {
   // 传过去的必须是可监听的对象,注意,是对象,其他类型都不行
      user: this.userInfo
    };
  },
  data() {
    return {
      userInfo: {
        id: "1"
      }
    };
  },
  methods: {
    get() {
      this.userInfo.name= "小明";
    }
  }
};
</script>

  • 子组件Child
<template>
  <div>
     {{ user.name}}
  </div>
</template>
<script>
export default {
  inject: ["foo"]
};
</script>

七、attrs/listeners

自行查阅资料

八、$children / $parent

自行查阅资料

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值