Οι frontend εφαρμογές, ιδίως οι πιο σύνθετες, πρέπει να επεξεργάζονται πολλά δεδομένα. Οι προγραμματιστές εισάγουν διάφορα πρότυπα σχεδίασης για να κάνουν τα έργα τους ευανάγνωστα και συντηρήσιμα. Στα περισσότερα κοινά σενάρια αντιμετώπισης ενός MVC, θέλουμε να διαχωρίσουμε τα δεδομένα από τα οπτικά μέρη της εφαρμογής.
Αυτός είναι ο λόγος για τον οποίο κατάστημα έχει γίνει τόσο χρήσιμη. Εξαρτάται από εσάς αν θα χρησιμοποιήσετε το React + Redux ή το Vue + Vuex - ο κύριος στόχος είναι ο ίδιος, δηλαδή διατηρώντας τα δεδομένα σας δομημένα, προσβάσιμα και ασφαλή ταυτόχρονα.
Σε αυτό το άρθρο, θα σας δείξω μερικά παραδείγματα για το πώς να διατηρείτε το κατάστημα Vuex καθαρό και αποδοτικό.
Πριν ξεκινήσουμε, ας υποθέσουμε ότι:
- έχετε κάποια εμπειρία με σύγχρονα JavaScript,
- βασικά γνωρίζετε τι είναι το Vue και πώς να το χρησιμοποιήσετε στηρίγματα, υπολογίζεται, κ.λπ,
- είστε εξοικειωμένοι με το Vuex (δράσεις, μεταλλάξεις, κ.λπ.) και θέλετε να βελτιώσετε τις εφαρμογές σας.
Vuex, όπως και η πλειοψηφία των βασικών Έργα Vue, είναι αρκετά καλά τεκμηριωμένη και μπορείτε να βρείτε πολλές χρήσιμες λύσεις στα επίσημα έγγραφα. Εξαγάγαμε μερικές βασικές πληροφορίες από αυτό για εσάς.
Μια βασική υλοποίηση του αποθηκευτικού χώρου Vuex μοιάζει ως εξής:
// main.js
import Vue from 'vue'
import Vuex from 'vuex'
import App from "./App",
Vue.use(Vuex)
const store = new Vuex.Store((
state: (
data: null,
),
actions: (
someAction: (( commit ), data) (
commit("SOME_MUTATION", data),
)
),
mutations: (
SOME_MUTATION (state, data) (
state.data = data,
)
))
));
new Vue((
el: "#app",
render: h => h(App),
store
));
Συνήθως, όταν η εφαρμογή σας μεγαλώνει, πρέπει να εφαρμόσετε δρομολόγηση, κάποιες παγκόσμιες οδηγίες, πρόσθετα κ.λπ. Αυτό κάνει την main.js
αρχείο πολύ μεγαλύτερο και πιο δύσκολο να διαβαστεί. Είναι καλή πρακτική να διατηρείτε το κατάστημα σε ένα εξωτερικό αρχείο, όπως εδώ:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex),
const state = (
data: null,
);
const actions = (
someAction: (( commit ), data) (
commit("SOME_MUTATION", data),
)
);
const mutations = (
SOME_MUTATION (state, data) (
state.data = data,
)
);
export default new Vuex.Store((
state,
actions,
mutations
));
1. Ενότητες
Τι πρέπει να κάνετε όταν η store.js
αρχείο γίνεται τεράστιο και δύσκολο να το επεξεργαστείτε; Στην πραγματικότητα, υπάρχει ένα πολύ καλό χαρακτηριστικό του Vuex - ενότητες. Είναι αφιερωμένα στη διάσπαση των δεδομένων σας σε ξεχωριστά αρχεία.
Φανταστείτε ότι εργάζεστε σε κάποια εταιρική εφαρμογή, στην οποία έχετε, για παράδειγμα, λίγους τομείς δεδομένων:
- χρήστη (διαχείριση όλων των εξουσιοδοτήσεων και δικαιωμάτων),
- παράμετροι διαδρομής (διαχείριση παγκόσμιων παραμέτρων πριν από τις αιτήσεις στο API),
- πωλήσεις (για το στοιχείο SalesMegaChart που είναι ορατό σε μηνιαίο/τριμηνιαίο/ετήσιο πλαίσιο),
- παραγγελίες (ορατές αφού κάνετε κλικ στη γραμμή SalesMegaChart).
...και ίσως μερικά ακόμη. Τώρα έχετε σοβαρούς λόγους να εισαγάγετε κάποια αρθρωτή δομή στο κατάστημά σας.
Πρώτα απ' όλα, μετακινήστε το store.js
αρχείο σε ένα νεοδημιουργημένο store/
και μετονομάστε το σε index.js
. Προαιρετικά, αν θέλετε να διατηρήσετε τα πάντα συσκευασμένα σε ενότητες, αφαιρέστε το κράτος, δράσεις και μεταλλάξεις από το κύριο αρχείο.
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex),
export default new Vuex.Store((
modules: (
// modules will go here
)
));
Στη συνέχεια, δίπλα στο αρχείο `store/index.js`, δημιουργήστε το πρώτο module - `store/user.js`.
import ApiService από το αρχείο '../services/api.service',
const state = (
loggedIn: false,
loginError: null,
user: null
);
const actions = (
login: async (( commit ), data) (
try (
const response = await ApiService.post('/login', data),
const ( user ) = response.data,
COMMIT("SAVE_USER", user),
COMMIT("LOGIN_SUCCESS"),
) catch (error) (
commit("LOGIN_ERROR", error),
)
)
);
const mutations = (
SAVE_USER (state, user) (
state.user = user,
),
LOGIN_SUCCESS (state) (
state.loggedIn = true,
),
LOGIN_ERROR (state, error) (
state.loginError = error,
state.loggedIn = false,
)
);
export const user (
state,
actions,
mutations
)
Και τώρα, φορτώστε την έτοιμη ενότητα στο κύριο αρχείο `store/index.js`:
import Vue from 'vue'
import Vuex from 'vuex'
import ( user ) from './user',
Vue.use(Vuex),
export default new Vuex.Store((
modules: (
χρήστης
)
));
Συγχαρητήρια! Τώρα έχετε μια πραγματικά όμορφη υλοποίηση καταστήματος. Μπορείτε επίσης να έχετε πρόσβαση στα δεδομένα από το στοιχείο (π.χ, UserProfile.vue
) έτσι:
<template>
<div class="user-profile">
<h2>(( user.name )))!</h2>
<!-- component template goes here -->
</div>
</template>
<script> import ( mapActions ) from 'Vuex';
export default (
name: 'UserProfile',
computed: mapState((
user: state => state.user
// user: 'user' <-- alternative syntax
))
)
</script>
2. Χώροι ονομάτων
Τώρα που γνωρίζετε πώς να χρησιμοποιείτε τις ενότητες, θα πρέπει επίσης να εξοικειωθείτε με τις λειτουργίες του Vuex namespacing. Στο προηγούμενο βήμα, δημιουργήσαμε το store/user.js
αρχείο με το χρήστης ενότητα.
Η δομή δεδομένων που ορίζεται στο user.js
αρχείο είναι προσβάσιμο από τα συστατικά, αλλά μπορείτε να εντοπίσετε ότι όλα τα χρήστης τα δεδομένα πηγαίνουν απευθείας στο παγκόσμιο κράτος
πλαίσιο, όπως εδώ:
υπολογίζεται: mapState((
user: state => state.user
// user: 'user' <-- εναλλακτικός τρόπος
))
Όταν ορίζετε περισσότερες ενότητες, πιθανόν να μπερδευτείτε σχετικά με το ποιο αντικείμενο προέρχεται από ποια ενότητα. Τότε θα πρέπει να χρησιμοποιείτε namespaced modules και να τα ορίζετε με αυτόν τον τρόπο:
export const user (
namespaced: true, // <-- namespacing!
state,
actions,
mutations
)
Από τώρα και στο εξής, όλα τα χρήστης δεδομένα (κράτος
μεταβλητή από store/user.js
αρχείο) θα αντιμετωπιστεί στο πλαίσιο του state.user
αναφορά:
υπολογίζεται: mapState((
user: state => state.user.user
// user: 'user/user' <-- εναλλακτικός τρόπος
))
Λίγα βήματα αργότερα, μπορείτε να επιτύχετε για το συστατικό κάτι σαν αυτό:
import ( mapActions ) from 'Vuex',
export default (
name: 'Dashboard',
computed: mapState((
sales: 'sales/data',
orders: 'orders/data',
sortBy: 'orders/sortBy',
loggedIn: 'user/loggedIn'
)),
methods: mapActions((
logout: 'user/logout',
loadSales: 'sales/load',
loadOrders: 'orders/load'
)),
created() (
if (this.loggedIn) (
loadSales(),
loadOrders(),
)
)
)
Μπράβο! Τόσο φρέσκο, τόσο καθαρό... Αλλά μην ανησυχείτε, το refactoring δεν τελειώνει ποτέ. Έτοιμοι για τα επόμενα βήματα;
3. Επικοινωνία μεταξύ μονάδων
Στο πρώτο βήμα, σας έδειξα κάποια δράση στο χρήστης ενότητα:
const actions = (
login: async (( commit ), data) (
try (
const response = await ApiService.post('/login', data),
const ( user ) = response.data,
COMMIT("SAVE_USER", user),
COMMIT("LOGIN_SUCCESS"),
) catch (error) (
commit("LOGIN_ERROR", error),
)
)
);
Σε περίπτωση αποτυχίας, προσθέτουμε το σφάλμα σύνδεσης στο κατάστημά μας - τι ακολουθεί;
Εδώ έχουμε μερικές επιλογές και η επιλογή εξαρτάται από το ποια επιλογή ταιριάζει καλύτερα στις ανάγκες σας. Ο απλούστερος τρόπος χρησιμοποιεί το v-if
οδηγία, χάρη στην οποία μπορεί να εμφανιστεί ένα μήνυμα σφάλματος αν υπάρχει κάποιο σφάλμα στο κατάστημά σας.
<template>
<div class="dashboard">
<!-- dashboard component template -->
<div
v-if="error"
class="error-message"
> (( error.message )) </div>
</div>
</template>
<script> import ( mapActions ) from 'Vuex';
export default (
name: 'Dashboard',
computed: mapState((
error: "user/loginError"
))
)
</script>
Και πάλι, φανταστείτε ότι έχετε πολλές ενότητες και κάθε μία από αυτές try/catch
παράγει ένα νέο σφάλμα στο κατάστημά σας. Προφανώς, θα κάνετε κατάχρηση του κανόνα DRY με αυτόν τον τρόπο.
Πώς μπορείτε να κάνετε τις διαδικασίες χειρισμού σφαλμάτων σας πιο γενικές;
Ας ορίσουμε το κοινή ενότητα και να βάλουμε κάποια λογική εκεί που θα χρησιμοποιείται σε παγκόσμιο επίπεδο.
// store/common.js
const state = (
errors: []
);
const actions = (
error: (
root: true,
handler(( commit ), error) (
commit("ERROR", error),
)
)
),
const mutations = (
ERROR (state, error) (
/* με αυτόν τον τρόπο θα έχουμε το νεότερο σφάλμα στην κορυφή της λίστας */
state.errors = [error, ...state.errors],
))
);
export const common (
namespaced: true,
state,
mutations
)
Τώρα, μπορούμε να προσαρμόσουμε το χρήστης ενότητα (και άλλες ενότητες επίσης):
try (
// κάποια ενέργεια
)catch (error) (
commit("common/ERROR", error, ( root: true )),
)
ή με πιο κομψό τρόπο, χρησιμοποιώντας την παγκόσμια δράση μας:
try (
// κάποια ενέργεια
) catch (error) (
dispatch("error", error),
)
Αυτή η σύνταξη του commit
και αποστολή
Οι κλήσεις φαίνονται αυτονόητες, αλλά μπορείτε να διαβάσετε περισσότερα για αυτά τα κόλπα εδώ.
Όταν έχετε όλα τα σφάλματα σε ένα μέρος, μπορείτε εύκολα να τα φορτώσετε στο Ταμπλό
συστατικό:
υπολογίζεται: mapState((
errors: 'common/errors'
)),
watch: (
/* αυτό θα καλείται μετά από κάθε μετάλλαξη "common/ERROR", όπου προσθέτουμε μόνο νέα σφάλματα στο κατάστημα, ένα προς ένα */
errors() (
this.showErrorMessage(this.errors[0]),
)
)
Το προηγούμενο παράδειγμα με το κοινή ενότητα χειρισμού σφαλμάτων είναι ήδη μια αποτελεσματική λύση, αλλά μπορείτε να προχωρήσετε ακόμη περισσότερο.
Όπως μπορείτε να δείτε, παρακολουθούμε τις αλλαγές στο κοινά/λάθη
array στο κατάστημα. Σε τέτοιες περιπτώσεις, όταν πρέπει να καθορίσετε κάποια ενέργεια σε μια συγκεκριμένη μετάλλαξη, μπορείτε να χρησιμοποιήσετε το Πρόσθετα Vuex ή ακόμη και στοιχεία ανώτερης τάξης (HOC).
Θα συζητήσω τα πρόσθετα και τα HOC στο επόμενο άρθρο. Εν τω μεταξύ, σας ευχαριστώ που διαβάσατε αυτό το λήμμα, ελπίζω να σας άρεσαν τα παραδείγματα που ετοιμάσαμε.
Μείνετε συντονισμένοι και συνεχίστε να κωδικοποιείτε!
Διαβάστε περισσότερα:
– Πώς να βελτιώσετε τις εφαρμογές Vue.js; Μερικές πρακτικές συμβουλές
– GraphQL: μαθήματα στην παραγωγή
– Shopify, Spree ή Solidus; Ελέγξτε γιατί η Ruby on Rails μπορεί να σας βοηθήσει να αναπτύξετε το ηλεκτρονικό σας εμπόριο.