Cara melakukan pencarian pengguna di GitHub menggunakan Vue

Saya pikir semua orang sudah tahu cara menulis pencarian pada pengguna GitHub di React , Svelte , Angular , atau tanpa mereka sama sekali . Nah, bagaimana Anda bisa melakukannya tanpa Vue? Saatnya untuk mengisi celah ini.


gambar


Jadi, hari ini kita akan membuat aplikasi yang sama menggunakan Vue, menulis tes untuk itu di Cypress untuk itu dan sedikit mempengaruhi Vue CLI 3.


Ada gif di pos


Persiapan


Untuk memulai, instal Vue CLI versi terbaru:


npm i -g @vue/cli 

Dan jalankan pembuatan proyek:


 vue create vue-github-search 

Ikuti langkah-langkah generator. Untuk proyek kami, saya memilih mode Manual dan konfigurasi berikut:


gambar


Modul tambahan


Kami akan menggunakan Stylus sebagai gaya, jadi kami membutuhkan stylus dan stylus-loader. Kami juga membutuhkan Axios untuk permintaan jaringan dan Lodash , dari mana kami akan mengambil fungsi debounce.


Buka folder proyek dan instal paket yang diperlukan:


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

Periksa


Kami memulai proyek dan memastikan semuanya bekerja:


  npm run serve 

Semua perubahan dalam kode akan langsung diterapkan di browser tanpa memuat ulang halaman.


Toko


Mari kita mulai dengan menulis vuex store, di mana semua data aplikasi akan berada. Kami hanya perlu menyimpan apa pun: kueri penelusuran, data pengguna, dan bendera proses pemuatan.
Buka store.js dan jelaskan keadaan awal aplikasi dan mutasi yang diperlukan:


 ... 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 } }); 

Tambahkan tindakan untuk memuat data dari API GitHub dan untuk memodifikasi kueri pencarian (kami membutuhkannya untuk string pencarian). Akibatnya, toko kami akan mengambil bentuk berikut:


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); } } }); 

Cari string


Buat komponen Search.vue baru di folder components . Tambahkan properti yang dihitung untuk mengaitkan komponen dengan toko. Ketika permintaan pencarian berubah, kami akan memanggil pencarian dengan debounce.


Cari.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> 

Sekarang kita akan menghubungkan string pencarian kita ke komponen utama App.vue dan secara bersamaan menghapus baris tambahan yang dibuat oleh generator.


Aplikasi


 <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> 

Mari kita lihat hasilnya di browser, memastikan semuanya berfungsi dengan vue-devtools:


gambar


Seperti yang Anda lihat, kami memiliki semua logika aplikasi siap! Kami memasukkan nama pengguna, permintaan dieksekusi dan data profil disimpan di toko.


Profil pengguna


Buat komponen User.vue dan tambahkan logika untuk menunjukkan beban, menampilkan profil dan kesalahan ketika pengguna tidak ditemukan. Juga tambahkan animasi transisi.


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> 

Hubungkan komponen kami di App.vue dan nikmati hasilnya:


Aplikasi
 <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> 

gambar


Tes


Kami akan menulis tes sederhana untuk aplikasi kami.


test / 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'); }); }); 

Jalankan tes dengan perintah


 npm run test:e2e 

Di jendela yang terbuka, klik tombol Jalankan semua spesifikasi dan lihat bahwa tes lulus:


gambar


Majelis


Vue CLI 3 mendukung mode pembuatan aplikasi baru, mode modern. Ia membuat 2 versi skrip: ringan untuk peramban modern yang mendukung fitur JavaScript terbaru, dan versi lengkap dengan semua polifile yang diperlukan untuk yang lebih lama. Pesona utama adalah bahwa kita benar-benar tidak perlu repot dengan penyebaran aplikasi semacam itu. Itu hanya bekerja. Jika browser mendukung <script type="module"> , itu akan menarik bangunan ringan itu sendiri. Cara kerjanya, Anda bisa membaca selengkapnya di artikel ini .


Tambahkan bendera modern ke package.json di perintah build:


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

Menyusun proyek:


 npm run build 

Mari kita lihat ukuran skrip yang dihasilkan:


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

Seperti yang Anda lihat, metode baru benar-benar mengurangi ukuran perakitan. Perbedaannya akan lebih terlihat pada proyek-proyek besar, sehingga fitur ini pasti patut diperhatikan.


Kode


Github


Demo


Itu saja, terima kasih sudah menonton!

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


All Articles