父子组件之间每每使用props和 $emit 实现数据共享,任意组件可经过bus(一个vue实例)做为桥梁,实现数据共享。当项目中组件愈来愈多时,组件之间的数据共享变得复杂,难以维护。使用 Vuex 可集中管理组件之间的数据(状态),使组件之间的数据共享变得简单。html
父→(props)子组件;子→($meit)父组件,即子组件自定义一个事件,在父组件中监听该事件。vue
自定义输入组件:git
<template> <input @input="handleInput" :value="value" :placeholder="placeholder" /> </template> <script> export default { name: "CustomInput", //props 接收父组件传递过来的数据 props: { value: { type: [Number, String], required: true, default: "" }, placeholder: { type: String, default: "提示文本" } }, methods: { handleInput(event) { let val = event.target.value; // 子组件的事件监听函数中触发一个自定义事件 this.$emit("customInput", val); } } }; </script>
使用组件:github
<template> <div class="store"> <!-- props 传递值 --> <custom-input :value="value" @customInput="handleInput" :placeholder="placeholder" /> <p v-text="value"></p> </div> </template> <script> import CustomInput from '_c/CustomInput.vue' export default { name: 'Store', components: { CustomInput }, data() { return { value: '', placeholder: '自定义事件传递值' } }, methods: { // 自定义事假处理器 handleInput(val) { this.value = val } } } </script>
由于 v-model
指令是双向绑定的,咱们也能够用其来实现值的传递:web
<template> <div class="store"> <custom-input v-model="inputValue" :placeholder="placeholder" /> <p v-text="inputValue"></p> </div> </template> <script> import CustomInput from '_c/CustomInput.vue' export default { name: 'Store', components: { CustomInput }, data() { return { inputValue: '', placeholder: 'v-mode 传递值' } } } </script>
建立一个空的 vue 实例,而后将该实例添加到 vue 的原型上,经过该实例触发事件
和监听事件
来在不一样组件之间共享数据。vuex
//bus.js import Vue from "vue"; let Bus = new Vue(); export default Bus;
在 main.js 中添加原型属性:api
import Bus from './lib/bus' // 经过 bus 实现任意组件传递参数 Vue.prototype.$bus=bus
//ChildPage.vue <template> <div id="child-page"> <h1>{{ msg }}</h1> <h3 v-text="data"></h3> </div> </template> <script> export default { name: "ChildPage", data() { return { msg: "I am child", data: "" }; }, mounted() { // 在挂载声明周期函数中监听自定义事件 this.$bus.$on("customEvent", data => { this.data = data; }); } }; </script>
<template> <div id="app"> <button @click="sendData">给child传递数据</button> <p v-text="num"></p> </div> </template> <script> export default { name: "App", data() { return { num: 0 } }, methods: { sendData(data) { // 由 bus 触发一个事件,在接收数据的组件中监听该事件 this.$bus.$emit('customEvent', ++this.num); } } }; </script>
随着组件的增长,经过以上方式共享数据,会愈来愈复杂,vue 提供了状态管理插件 Vuex
。数组
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式;集中存储和管理应用的全部组件状态。
理解:缓存
Vuex 文档中说:app
经过定义和 隔离状态管理中的各类概念并经过强制规则维持视图和状态间的 独立性,咱们的代码将会变得更结构化且易维护。
Vuex 就是经过隔离数据、拆分改变数据的方式使得数据和视图独立,数据被组件数共享。
虚线内部的三个部分组成了一个Store,组件的数据保存在 State
中,用户和组件交互时,经过组件内的方法分发(dispatch)一个动做(action,有点像事件),动做会提交(Commit)一个更改(Mutation,也相似事件),改变 State 中的数据,而后获取数据渲染到视图上。
//main.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex);// Vuex 是 Vue 的插件 let store = new Vuex.Store({ state: { //放置state的值 count: 0, str:"abcd234" }, getters: { //放置getters方法 strLen: state => state.str.length }, // mutations只能是同步操做 mutations: { //放置mutations方法 increment(state, payload) { //在这里改变state中的数据 state.count = payload.number; } }, // actions能够是异步操做 actions: { //放置actions方法 actionName({ commit }) { //dosomething commit('mutationName') }, getSong ({commit}, id) { //请求后台数据 api.getMusicUrlResource(id).then(res => { let url = res.data.data[0].url; }) .catch((error) => { // 错误处理 console.log(error); }); } } }); new Vue({ el: '#app', store // 经过 this.store 访问 store });
咱们看看 Vuex 和 store 是什么?
Vuex:
Vuex 它其实是一个对象,里面包含了Store这一构造函数,还有几个mapActions、mapGetters、mapMutations、mapState、install 方法。
store:
store 是 Vuex 的实例(废话)。
实际项目中每每将 store 单独放置的一个文件夹在,mutations 、getters、actions 等属性各自用一个文件保存。
state 对象的属性时 Vuex 管理的状态,相似单个组建的 data。
访问 getters:
this.$store.state
;mapState
映射成计算属性,推荐
。//state.js export default { count: 100, name: 'Jack*Zhou', firstName: 'Jack', lastName: 'Zhou', age: 24, profession: 'web deveploper', company: 'Baidu' }
组件:
import {mapState} from 'vuex' export default { data(){ return { localCount:0 } }, computed: { localCount() { return this.$store.state.count + 1; }, //计算属性名和 state 属性名相同:传入数组 // ...mapState(['count','name']), // 计算属性名和 state 属性不一样,传入对象 ...mapState({ name: state => state.name, count: state => state.count, countAlias: 'count', //为了使用 this 不能使用箭头函数 countPlusLocalCount(state) { return state.count + this.localCount; } }) }, }
getters 是对 state 的加工,相似于组件中的 data 和计算属性的关系。getters 的返回值会被缓存起来,只有当它的依赖改变,才会从新计算。
访问 getters:
this.$store.getters
;mapGetters
将 getters 映射成计算属性,推荐
;// getters.js export default { fullName: state => state.firstName + ' ' + state.lastName, //在getters 中访问 getters info: (state, getters) => { return state.age + ',' + getters.fullName; }, //为了传递参数,返回一个函数, personInfo: (state, getters) => (city) => { return { name: getters.fullName, age: state.age, company: state.company, city } } }
使用 getters:
import { mapGetters } from 'vuex' export default { name: 'Store', computed: { ...mapGetters(['fullName', 'info', 'personInfo']), myInfo() { return this.personInfo('杭州') }, ...mapGetters({ fullNameAlias1: 'fullName', //不能写成函数 // fullNameAlias2(state){ // return state.name+',你好'+this.$store.getters.fullName; // } }) }, mounted() { console.log(this.personInfo('成都')) console.log(this.myInfo) } }