如何使用Vue在GitHub上进行用户搜索

我认为每个人都已经知道如何在ReactSvelteAngular根本没有它们的情况下在GitHub用户上进行搜索。 好吧,没有Vue怎么办? 现在是时候填补这一空白。


图片


因此,今天我们将使用Vue创建相同的应用程序,并在Cypress上为其编写测试,并稍微影响Vue CLI 3。


帖子中有GIF


准备工作


首先,请安装最新版本的Vue CLI:


npm i -g @vue/cli 

并运行项目的创建:


 vue create vue-github-search 

遵循生成器的步骤。 对于我们的项目,我选择了“手动”模式和以下配置:


图片


附加模块


我们将使用手写笔作为样式,因此我们需要手写笔和手写笔加载器。 我们还需要Axios来处理网络请求和Lodash ,我们将从中使用去抖动功能。


转到项目文件夹并安装必要的软件包:


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

检查一下


我们启动项目,并确保一切正常:


  npm run serve 

代码中的所有更改将立即在浏览器中应用,而无需重新加载页面。


店面


让我们从编写所有应用程序数据所在的vuex存储开始。 我们只需要存储任何内容:搜索查询,用户数据和加载过程的标志。
打开store.js并描述应用程序的初始状态和必要的突变:


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

添加操作以从GitHub API加载数据并修改搜索查询(搜索字符串需要它)。 因此,我们的商店将采用以下形式:


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

搜索字符串


components文件夹中创建一个新的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> 

现在,我们将搜索字符串连接到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> 

让我们在浏览器中查看结果,确保所有内容都可以与vue-devtools一起使用:


图片


如您所见,我们已经准备好所有应用程序逻辑! 我们输入用户名,执行请求并将配置文件数据存储在商店中。


用户资料


创建User.vue组件并添加逻辑以指示负载,未找到用户时显示配置文件和错误。 还添加过渡动画。


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> 

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> 

图片


测验


我们将为应用程序编写简单的测试。


测试/ e2e /规格/ 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'); }); }); 

使用命令运行测试


 npm run test:e2e 

在打开的窗口中,单击“运行所有规格”按钮,然后查看测试是否通过:


图片


组装方式


Vue CLI 3支持新的应用程序构建模式,即现代模式。 他创建了两个版本的脚本:轻量级的现代浏览器,支持最新的JavaScript功能;以及完整版的完整版,其中包含所有较旧版本所需的多义字符。 主要的魅力在于,我们绝对不需要理会此类应用程序的部署。 它只是工作。 如果浏览器支持<script type="module"> ,它将拉动轻量级版本本身。 如何运作,您可以在本文中阅读更多内容


在build命令中将modern标志添加到package.json


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

汇总一个项目:


 npm run build 

让我们看一下生成的脚本的大小:


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

如您所见,新方法确实减小了程序集的大小。 在大型项目中,差异将更加明显,因此该功能无疑值得关注。


代号


Github


演示版


就这样,谢谢收看!

Source: https://habr.com/ru/post/zh-CN420351/


All Articles