So führen Sie Benutzersuchen auf GitHub mit Vue durch

Ich denke, jeder weiß bereits, wie man eine Suche nach GitHub-Benutzern auf React , Svelte , Angular oder überhaupt ohne sie schreibt. Wie kann man ohne Vue auskommen? Es ist Zeit, diese Lücke zu schließen.


Bild


Daher werden wir heute dieselbe Anwendung mit Vue erstellen, Tests auf Cypress schreiben und Vue CLI 3 geringfügig beeinflussen.


Es gibt Gifs in der Post


Vorbereitung


Installieren Sie zunächst die Vue-CLI der neuesten Version:


npm i -g @vue/cli 

Führen Sie die Erstellung des Projekts aus:


 vue create vue-github-search 

Befolgen Sie die Schritte des Generators. Für unser Projekt habe ich den manuellen Modus und die folgende Konfiguration gewählt:


Bild


Zusätzliche Module


Wir werden Stylus als Stile verwenden, daher benötigen wir Stylus und Stylus-Loader. Wir benötigen Axios auch für Netzwerkanfragen und Lodash , von denen wir die Entprellungsfunktion übernehmen werden.


Gehen Sie zum Projektordner und installieren Sie die erforderlichen Pakete:


 cd vue-github-search npm i stylus stylus-loader axios lodash 

Überprüfen Sie


Wir starten das Projekt und stellen sicher, dass alles funktioniert:


  npm run serve 

Alle Änderungen am Code werden sofort im Browser übernommen, ohne die Seite neu zu laden.


Speichern


Beginnen wir mit dem Schreiben des vuex-Speichers, in dem sich alle Anwendungsdaten befinden. Wir müssen nur nichts speichern: eine Suchabfrage, Benutzerdaten und ein Flag des Ladevorgangs.
Öffnen Sie store.js und beschreiben Sie den Anfangszustand der Anwendung und die erforderlichen Mutationen:


 ... const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY'; const SET_LOADING = 'SET_LOADING'; const SET_USER = 'SET_USER'; const RESET_USER = 'RESET_USER'; export default new Vuex.Store({ state: { searchQuery: '', loading: false, user: null }, mutations: { [SET_SEARCH_QUERY]: (state, searchQuery) => state.searchQuery = searchQuery, [SET_LOADING]: (state, loading) => state.loading = loading, [SET_USER]: (state, user) => state.user = user, [RESET_USER]: state => state.user = null } }); 

Fügen Sie Aktionen hinzu, um Daten von der GitHub-API zu laden und die Suchabfrage zu ändern (wir benötigen sie für die Suchzeichenfolge). Infolgedessen wird unser Geschäft die folgende Form annehmen:


store.js


 import Vue from 'vue'; import Vuex from 'vuex'; import axios from 'axios'; Vue.use(Vuex); const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY'; const SET_LOADING = 'SET_LOADING'; const SET_USER = 'SET_USER'; const RESET_USER = 'RESET_USER'; export default new Vuex.Store({ state: { searchQuery: '', loading: false, user: null }, mutations: { [SET_SEARCH_QUERY]: (state, searchQuery) => state.searchQuery = searchQuery, [SET_LOADING]: (state, loading) => state.loading = loading, [SET_USER]: (state, user) => state.user = user, [RESET_USER]: state => state.user = null }, actions: { setSearchQuery({commit}, searchQuery) { commit(SET_SEARCH_QUERY, searchQuery); }, async search({commit, state}) { commit(SET_LOADING, true); try { const {data} = await axios.get(`https://api.github.com/users/${state.searchQuery}`); commit(SET_USER, data); } catch (e) { commit(RESET_USER); } commit(SET_LOADING, false); } } }); 

Suchzeichenfolge


Erstellen Sie eine neue Search.vue Komponente im components . Fügen Sie eine berechnete Eigenschaft hinzu, um die Komponente dem Speicher zuzuordnen. Wenn sich die Suchabfrage ändert, rufen wir die Suche mit Entprellen auf.


Search.vue


 <template> <input v-model="query" @input="debouncedSearch" placeholder="Enter username" /> </template> <script> import {mapActions, mapState} from 'vuex'; import debounce from 'lodash/debounce'; export default { name: 'search', computed: { ...mapState(['searchQuery']), query: { get() { return this.searchQuery; }, set(val) { return this.setSearchQuery(val); } } }, methods: { ...mapActions(['setSearchQuery', 'search']), debouncedSearch: debounce(function () { this.search(); }, 500) } }; </script> <style lang="stylus" scoped> input width 100% font-size 16px text-align center </style> 

Jetzt verbinden wir unsere App.vue mit der Hauptkomponente von App.vue und löschen gleichzeitig die vom Generator erstellten zusätzlichen Zeilen.


App.vue


 <template> <div id="app"> <Search /> </div> </template> <script> import Search from './components/Search'; export default { name: 'app', components: { Search } }; </script> <style lang="stylus"> #app font-family 'Avenir', Helvetica, Arial, sans-serif font-smoothing antialiased margin 10px </style> 

Lassen Sie uns das Ergebnis im Browser sehen und sicherstellen, dass alles mit vue-devtools funktioniert:


Bild


Wie Sie sehen können, haben wir die gesamte Anwendungslogik bereit! Wir geben den Benutzernamen ein, die Anfrage wird ausgeführt und die Profildaten werden im Store gespeichert.


Benutzerprofil


Erstellen Sie die User.vue Komponente und fügen Sie eine Logik hinzu, um die Last anzuzeigen, das Profil anzuzeigen und einen Fehler anzuzeigen, wenn der Benutzer nicht gefunden wird. Fügen Sie auch Übergangsanimationen hinzu.


User.vue
 <template> <div class="github-card"> <transition name="fade" mode="out-in"> <div v-if="loading" key="loading"> Loading </div> <div v-else-if="user" key="user"> <div class="background" :style="{backgroundImage: `url(${user.avatar_url})`}" /> <div class="content"> <a class="avatar" :href="`https://github.com/${user.login}`" target="_blank"> <img :src="user.avatar_url" :alt="user.login" /> </a> <h1>{{user.name || user.login}}</h1> <ul class="status"> <li> <a :href="`https://github.com/${user.login}?tab=repositories`" target="_blank"> <strong>{{user.public_repos}}</strong> <span>Repos</span> </a> </li> <li> <a :href="`https://gist.github.com/${user.login}`" target="_blank"> <strong>{{user.public_gists}}</strong> <span>Gists</span> </a> </li> <li> <a :href="`https://github.com/${user.login}/followers`" target="_blank"> <strong>{{user.followers}}</strong> <span>Followers</span> </a> </li> </ul> </div> </div> <div v-else key="not-found"> User not found </div> </transition> </div> </template> <script> import {mapState} from 'vuex'; export default { name: 'User', computed: mapState(['loading', 'user']) }; </script> <style lang="stylus" scoped> .github-card margin-top 50px padding 20px text-align center background #fff color #000 position relative h1 margin 16px 0 20px line-height 1 font-size 24px font-weight 500 .background filter blur(10px) opacity(50%) z-index 1 position absolute top 0 left 0 right 0 bottom 0 background-size cover background-position center background-color #fff .content position relative z-index 2 .avatar display inline-block overflow hidden background #fff border-radius 100% text-decoration none img display block width 80px height 80px .status background white ul text-transform uppercase font-size 12px color gray list-style-type none margin 0 padding 0 border-top 1px solid lightgray border-bottom 1px solid lightgray zoom 1 &:after display block content '' clear both li width 33% float left padding 8px 0 box-shadow 1px 0 0 #eee &:last-of-type box-shadow none strong display block color #292f33 font-size 16px line-height 1.6 a color #707070 text-decoration none &:hover color #4183c4 .fade-enter-active, .fade-leave-active transition opacity .5s .fade-enter, .fade-leave-to opacity 0 </style> 

Verbinden Sie unsere Komponente in App.vue und genießen Sie das Ergebnis:


App.vue
 <template> <div id="app"> <Search /> <User /> </div> </template> <script> import Search from './components/Search'; import User from './components/User'; export default { name: 'app', components: { User, Search } }; </script> <style lang="stylus"> #app font-family 'Avenir', Helvetica, Arial, sans-serif font-smoothing antialiased margin 10px </style> 

Bild


Tests


Wir werden einfache Tests für unsere Anwendung schreiben.


tests / e2e / specs / test.js


 describe('Github User Search', () => { it('has input for username', () => { cy.visit('/'); cy.get('input'); }); it('has "User not found" caption', () => { cy.visit('/'); cy.contains('User not found'); }); it("finds Linus Torvalds' GitHub page", () => { cy.visit('/'); cy.get('input').type('torvalds'); cy.contains('Linus Torvalds'); cy.get('img'); cy.contains('span', 'Repos'); cy.contains('span', 'Gists'); cy.contains('span', 'Followers'); }); it("doesn't find nonexistent page", () => { cy.visit('/'); cy.get('input').type('_some_random_name_6m92msz23_2'); cy.contains('User not found'); }); }); 

Führen Sie die Tests mit dem Befehl aus


 npm run test:e2e 

Klicken Sie im folgenden Fenster auf die Schaltfläche Alle Spezifikationen ausführen und sehen Sie, ob die Tests bestanden wurden:


Bild


Montage


Vue CLI 3 unterstützt den neuen Anwendungserstellungsmodus, den modernen Modus. Er erstellt zwei Versionen von Skripten: Leichtgewicht für moderne Browser, die die neuesten JavaScript-Funktionen unterstützen, und eine Vollversion mit allen erforderlichen Polyphilen für ältere. Der Hauptcharme ist, dass wir uns absolut nicht um die Bereitstellung einer solchen Anwendung kümmern müssen. Es funktioniert einfach. Wenn der Browser <script type="module"> , wird der Lightweight-Build selbst aufgerufen. Wie das funktioniert, lesen Sie mehr in diesem Artikel .


Fügen Sie das package.json im Befehl build hinzu:


 "build": "vue-cli-service build --modern" 

Ein Projekt zusammenstellen:


 npm run build 

Schauen wir uns die Größe der resultierenden Skripte an:


 8.0K ./app-legacy.cb7436d4.js 8.0K ./app.b16ff4f7.js 116K ./chunk-vendors-legacy.1f6dfb2a.js 96K ./chunk-vendors.a98036c9.js 

Wie Sie sehen können, reduziert die neue Methode die Größe der Baugruppe erheblich. Der Unterschied wird bei großen Projekten noch deutlicher, daher verdient die Funktion definitiv Aufmerksamkeit.


Code


Github


Demo


Das ist alles, danke fürs Zuschauen!

Source: https://habr.com/ru/post/de420351/


All Articles