父子組件之間每每使用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) } }