Szukaj…


Wprowadzenie

Vuex to wzorzec zarządzania stanem + biblioteka dla aplikacji Vue.js. Służy jako scentralizowany magazyn dla wszystkich składników aplikacji, z regułami zapewniającymi, że stan można zmutować tylko w przewidywalny sposób. Integruje się również z oficjalnym rozszerzeniem narzędzi programistycznych Vue, zapewniając zaawansowane funkcje, takie jak debugowanie w czasie zerowej konfiguracji i eksport / import migawek stanu.

Co to jest Vuex?

Vuex to oficjalna wtyczka do Vue.js, która oferuje scentralizowany magazyn danych do użytku w Twojej aplikacji. Ma na to duży wpływ architektura aplikacji Flux, która oferuje jednokierunkowy przepływ danych, co prowadzi do prostszego projektowania aplikacji i wnioskowania.

W aplikacji Vuex magazyn danych przechowuje cały stan wspólnej aplikacji . Ten stan jest zmieniany przez mutacje, które są wykonywane w odpowiedzi na działanie wywołujące zdarzenie mutacji za pośrednictwem dyspozytora .

Przykład przepływu danych w aplikacji Vuex przedstawiono na schemacie poniżej. Architektura aplikacji Vuex Schemat wykorzystany na licencji MIT , pochodzący z oficjalnego repozytorium Vuex GitHub .

Indywidualne Vue.js komponenty aplikacji mogą uzyskać dostęp do obiektu magazynu w celu pobrania danych przez pochłaniacze, które są czyste funkcje Zwracanie tylko do odczytu kopię żądanych danych.

Komponenty mogą mieć akcje, które są funkcjami, które dokonują zmian we własnej kopii danych komponentu, a następnie używają programu rozsyłającego do wywołania zdarzenia mutacji. To zdarzenie jest następnie obsługiwane przez magazyn danych, który w razie potrzeby aktualizuje stan.

Zmiany są następnie automatycznie odzwierciedlane w całej aplikacji, ponieważ wszystkie komponenty są reaktywnie powiązane ze sklepem za pośrednictwem modułów pobierających.


Przykład ilustrujący wykorzystanie vuex w vue projektu.

const state = {
    lastClickTime: null
}

const mutations = {
    updateLastClickTime: (state, payload) => {
      state.lastClickTime = payload
  }
}

const getters = {
  getLastClickTime: state => {
    return new Date(state.lastClickTime)
  }
}

const actions = {
    syncUpdateTime: ({ commit }, payload) => {
    commit("updateLastClickTime", payload)
  },
  asyncUpdateTime: ({ commit }, payload) => {
    setTimeout(() => {
      commit("updateLastClickTime", payload)
    }, Math.random() * 5000)
  }
}

const store = new Vuex.Store({
  state,
  getters,
  mutations,
  actions
})

const { mapActions, mapGetters } = Vuex;

// Vue 
const vm = new Vue({
    el: '#container',
  store,
  computed: {
      ...mapGetters([
        'getLastClickTime'
    ])
  },
  methods: {
      ...mapActions([
        'syncUpdateTime',
      'asyncUpdateTime'
    ]),
    updateTimeSyncTest () {
        this.syncUpdateTime(Date.now())
    },
    updateTimeAsyncTest () {
        this.asyncUpdateTime(Date.now())
    }
  }
})

I szablon HTML dla tego samego:

<div id="container">
  <p>{{ getLastClickTime || "No time selected yet" }}</p>
  <button @click="updateTimeSyncTest">Sync Action test</button>
  <button @click="updateTimeAsyncTest">Async Action test</button>
</div>
  1. Tutaj stan zawiera właściwość lastClickTime zainicjowaną jako null. To ustawienie wartości domyślnych jest ważne, aby właściwości były aktywne . Właściwości niewymienione w tym stanie będą dostępne, ale wprowadzone później zmiany nie będą dostępne przy użyciu programów pobierających.

  2. Używany getter zapewnia obliczoną właściwość, która będzie aktualizowana za każdym razem, gdy mutacja aktualizuje wartość właściwości state.

  3. Tylko mutacje mogą zmieniać stan i jego właściwości, co mówi, że robi to tylko synchronicznie .

  4. Akcji można użyć w przypadku aktualizacji asynchronicznych, w których można wykonać wywołanie API (tutaj wyśmiewane przez losowo ustawiony setTimeout), a po otrzymaniu odpowiedzi można przypisać mutację, aby zmienić stan .

Dlaczego warto korzystać z Vuex?

Podczas budowania dużych aplikacji, takich jak aplikacje pojedynczej strony (SPA), które zazwyczaj składają się z wielu komponentów wielokrotnego użytku, mogą one szybko stać się trudne do zbudowania i utrzymania. Współdzielenie danych i stanu między tymi komponentami może również szybko ulec awarii i stać się trudne do debugowania i utrzymania.

Dzięki zastosowaniu scentralizowanego magazynu danych aplikacji cały stan aplikacji może być reprezentowany w jednym miejscu, dzięki czemu aplikacja jest bardziej zorganizowana. Dzięki zastosowaniu jednokierunkowego przepływu danych, mutacji i ograniczeniu dostępu do danych tylko do wymaganych danych, znacznie łatwiej jest zrozumieć rolę składnika i jego wpływ na stan aplikacji.

Komponenty VueJS są oddzielnymi bytami i nie mogą łatwo udostępniać sobie danych. Aby udostępnić dane bez vuex, musimy emit zdarzenie z danymi, a następnie nasłuchiwać i łapać to zdarzenie z on .

składnik 1

this.$emit('eventWithDataObject', dataObject)

składnik 2

this.$on('eventWithDataObject', function (dataObject) {
    console.log(dataObject)
})

Po zainstalowaniu vuex możemy po prostu uzyskać dostęp do jego danych z dowolnego komponentu, bez potrzeby słuchania zdarzeń.

this.$store.state.myData

Możemy również zmieniać dane synchronicznie z mutatorami , wykonywać działania asynchroniczne i uzyskiwać dane za pomocą funkcji pobierających .

Funkcje Gettera mogą działać jako globalne funkcje obliczeniowe. Możemy uzyskać do nich dostęp z komponentów:

this.$store.getters.myGetter

Działania są metodami globalnymi. Możemy wysłać je z komponentów:

this.$store.dispatch('myAction', myDataObject)

Mutacje to jedyny sposób na zmianę danych w vuex. Możemy zatwierdzać zmiany:

this.$store.commit('myMutation', myDataObject)

Kod Vuex wyglądałby tak

state: {
  myData: {
    key: 'val'
  }
},
getters: {
  myGetter: state => {
     return state.myData.key.length
  }
},
actions: {
  myAction ({ commit }, myDataObject) {
    setTimeout(() => {
      commit('myMutation', myDataObject)
    }, 2000)
  }
},
mutations: {
  myMutation (state, myDataObject) {
    state.myData = myDataObject
  }
}

Jak zainstalować Vuex?

Przez większość czasu będziesz używać Vuex w aplikacjach opartych na większych komponentach, w których prawdopodobnie korzystasz z pakietu modułów, takiego jak Webpack lub Browserify w połączeniu z Vueify, jeśli używasz pojedynczych plików.

W takim przypadku najłatwiejszym sposobem uzyskania Vuex jest NPM. Uruchom poniższe polecenie, aby zainstalować Vuex i zapisać go w zależnościach aplikacji.

 npm install --save vuex

Upewnij się, że ładujesz link Vuex do konfiguracji Vue, umieszczając następujący wiersz po instrukcji request require('vue') .

Vue.use(require('vuex'))

Vuex jest również dostępny na CDN; można pobrać najnowszą wersję ze cdnjs tutaj .

Automatyczne odrzucanie powiadomień

Ten przykład dynamicznie zarejestruje moduł vuex do przechowywania niestandardowych powiadomień, które można automatycznie zamknąć

notifications.js

rozwiąż sklep vuex i zdefiniuj niektóre stałe

//Vuex store previously configured on other side
import _store from 'path/to/store';

//Notification default duration in milliseconds
const defaultDuration = 8000;

//Valid mutation names
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED';
const NOTIFICATION_DISMISSED = 'NOTIFICATION_DISMISSED';

ustaw stan początkowy naszego modułu

const state = {
  Notifications: []
}

ustaw nasze moduły pobierające

const getters = {
  //All notifications, we are returning only the raw notification objects
  Notifications: state => state.Notifications.map(n => n.Raw)
}

ustaw nasze akcje modułu

const actions = {
  //On actions we receive a context object which exposes the 
  //same set of methods/properties on the store instance
  //{commit} is a shorthand for context.commit, this is an 
  //ES2015 feature called argument destructuring
  Add({ commit }, notification) {
    //Get notification duration or use default duration
    let duration = notification.duration || defaultDuration

    //Create a timeout to dismiss notification
    var timeOut = setTimeout(function () {
      //On timeout mutate state to dismiss notification
      commit(NOTIFICATION_DISMISSED, notification);
    }, duration);

    //Mutate state to add new notification, we create a new object 
    //for save original raw notification object and timeout reference
    commit(NOTIFICATION_ADDED, {
      Raw: notification,
      TimeOut: timeOut
    })
  },
  //Here we are using context object directly
  Dismiss(context, notification) {
    //Just pass payload
    context.commit(NOTIFICATION_DISMISSED, notification);
  }
}

ustaw nasze mutacje modułowe

const mutations = {
  //On mutations we receive current state and a payload
  [NOTIFICATION_ADDED](state, notification) {
    state.Notifications.push(notification);
  },
  //remember, current state and payload
  [NOTIFICATION_DISMISSED](state, rawNotification) {
    var i = state.Notifications.map(n => n.Raw).indexOf(rawNotification);
    if (i == -1) {
      return;
    }

    clearTimeout(state.Notifications[i].TimeOut);
    state.Notifications.splice(i, 1);
  }
}

Zarejestruj nasz moduł ze zdefiniowanym stanem, getterami, akcjami i mutacją

_store.registerModule('notifications', {
  state,
  getters,
  actions,
  mutations
});

Stosowanie

componentA.vue

Ten komponent wyświetla wszystkie powiadomienia jako alerty bootstrap w prawym górnym rogu ekranu, pozwala również ręcznie odrzucić każde powiadomienie.

<template>
<transition-group name="notification-list" tag="div" class="top-right">
  <div v-for="alert in alerts" v-bind:key="alert" class="notification alert alert-dismissible" v-bind:class="'alert-'+alert.type">
    <button v-on:click="dismiss(alert)" type="button" class="close" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <div>
      <div>
        <strong>{{alert.title}}</strong>
      </div>
      <div>
        {{alert.text}}
      </div>
    </div>
  </div>
</transition-group>
</template>

<script>
export default {
  name: 'arc-notifications',
  computed: {
    alerts() {
      //Get all notifications from store
      return this.$store.getters.Notifications;
    }
  },
  methods: {
    //Manually dismiss a notification
    dismiss(alert) {
      this.$store.dispatch('Dismiss', alert);
    }
  }
}
</script>
<style lang="scss" scoped>
$margin: 15px;

.top-right {
    top: $margin;
    right: $margin;
    left: auto;
    width: 300px;
    //height: 600px;
    position: absolute;
    opacity: 0.95;
    z-index: 100;
    display: flex;
    flex-wrap: wrap;
    //background-color: red;
}
.notification {
    transition: all 0.8s;
    display: flex;
    width: 100%;
    position: relative;
    margin-bottom: 10px;
    .close {
        position: absolute;
        right: 10px;
        top: 5px;
    }

    > div {
        position: relative;
        display: inline;
    }
}
.notification:last-child {
    margin-bottom: 0;
}
.notification-list-enter,
.notification-list-leave-active {
    opacity: 0;
    transform: translateX(-90px);
}
.notification-list-leave-active {
    position: absolute;
}
</style>

Urywek służący do dodawania powiadomień w dowolnym innym składniku

//payload could be anything, this example content matches with componentA.vue 
this.$store.dispatch('Add', {
  title = 'Hello',
  text = 'World',
  type = 'info',
  duration = 15000
});


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow