vue 響應式ui
Are you thinking of building something awesome with one of the popular modern frameworks out there right now, but don’t know how to get started?
您是否正在考慮使用當前流行的現代框架之一來構建出色的東西,但不知道如何入門?
If yes, then this post will help you get a kick started and build something awesome.
如果是的話,那么這篇文章將幫助您入門并建立一些很棒的東西。
What are we going to build?
我們要建造什么?
We will be building a responsive client side search of the 7 wonders of the world with the following features:
我們將通過以下功能對世界7大奇觀進行響應式客戶端搜索:
Text Search & Filters based on Ratings and Likes.
基于評級和喜歡的文本搜索和過濾器 。
2 items per row for Tablet and Desktop, 1 item per row for Mobile.
平板電腦和臺式機每行2項, 移動設備每行1項。
- Fetching data asynchronously from external API on client side. 從客戶端的外部API異步獲取數據。
- Responsive view as shown below: 響應視圖如下圖:
Live Demo: https://vue-responsive-search.herokuapp.com
現場演示 : https : //vue-sensitive-search.herokuapp.com
Source Code: https://github.com/honey93/VueSearchExample
源代碼 : https : //github.com/honey93/VueSearchExample
科技架構 (Tech Architecture)
We will be working with the following technologies:
我們將使用以下技術:
Vue.js: The Progressive JavaScript Framework
Vue.js :漸進式JavaScript框架
BootstrapVue: It provides one of the most comprehensive implementations of Bootstrap V4 components and grid system available for Vue.js 2.5+, complete with extensive and automated WAI-ARIA accessibility markup.
BootstrapVue :它提供了適用于Vue.js 2.5+的Bootstrap V4組件和網格系統的最全面的實現之一,并帶有大量且自動的WAI-ARIA可訪問性標記。
Vue Cli 3: Standard Tooling for Vue.js Development
Vue Cli 3 :用于Vue.js開發的標準工具
項目結構 (Project Structure)
To get started with our Vue project, we need to setup many things like Vue, Bootstrap, Vue Router, Vuex, etc.
要開始我們的Vue項目,我們需要設置許多東西,例如Vue,Bootstrap,Vue Router,Vuex等。
Vue Cli provides us the command to create the project with most of the needed configurations.
Vue Cli向我們提供了使用大多數所需配置來創建項目的命令。
npm install -g @vue/cli
vue create project-name
For the remaining things like BootstrapVue, vue-star-rating, etc, we can use the npm install command.
對于BootstrapVue,vue-star-rating等其余內容,我們可以使用npm install命令。
The default project created using vuecli has the following structure:
使用vuecli創建的默認項目具有以下結構:
/Root Folder Public/src/assets/ /* Static assets like images goes here */components/ /* Small part of a view */views/ /* View represents a page composed of several components*/App.vue /* The main view inside which the routing logic goes */main.js /* App initialisation happens here */router.js /* Router logic is defined here */store.js /* Optional state management library Vuex */package.json /* It consist of all the dependencies of the project. */......
The above things are there to explain the project architecture to you and the way to initialise it.
以上是向您解釋項目架構以及初始化方式的內容。
We can get started by cloning the repository and writing the following commands:
我們可以通過克隆存儲庫并編寫以下命令來開始使用:
npm install
npm run serve
Some important components explained:
一些重要的組件進行了解釋:
components/Header.vue
組件/Header.vue
The header has been created in the form of a single independent component so that it can be reused across pages, avoiding duplication of the code.
標頭以單個獨立組件的形式創建,因此可以在頁面之間重用,從而避免了代碼重復。
/* Vue style of writing component: template, script and style*/
<template><div class="pad-15-hor pad-15-ver header"><div><img src="@/assets/logo.png" width="25px"> Responsive Search</div><div><i class="fas fa-bars"></i></div></div>
</template>
<script>
export default {name: "Header"
};
</script>
<style scoped>
.header {display: flex;flex-flow: row wrap;justify-content: space-between;
}
</style>
components/Main.vue
組件/Main.vue
This component consist of the entire logic of search / filters and display of results fetched from the API.
此組件包含搜索/過濾器的整個邏輯以及從API提取的結果的顯示。
This component is using the above Header by importing it in the script.
該組件通過將其導入腳本中來使用上述標題。
<template><div><Header/><div class="pad-15-hor pad-15-ver search-parent"><div class="search-bar"><b-form-input@input="search_text()"v-model="search.text"type="text"placeholder="Search by Name"></b-form-input><span class="search-icon"><i class="fas fa-search"></i></span></div><div><span class="bold">Total Likes:</span>{{likes.count}}<span class="bold">Hits:</span>{{likes.hit}}</div><div><b-form-select @input="sort()" v-model="search.filter" :options="options"/></div></div>
<div class="container-fluid"><div class="row"><div class="col-md-6 pad-15-ver" v-for="wonder in wonders_data" :key="wonder.id"><divclass="card-inner"@mouseover="show_hover(true,wonder.id)"@mouseout="show_hover(false,0)"><img class="card-img" :src="wonder.imageURL">
<div class="card-bottom pad-15-hor" v-show="!hover_flag || active_id != wonder.id"><div class="min-width-160"><span class="bold">Ratings:</span><star-rating:rating="wonder.ratings":show-rating="false":inline="true":star-size="15"></star-rating></div><div class="max-width-160"><span class="bold">{{wonder.place}}</span></div></div>
<div :class="{'card-hover':1}" v-show="hover_flag && active_id == wonder.id"><span@click="make_active(wonder.id)":class="{'fas':1, 'fa-heart':1, 'absolute-star':1, 'green':check_active(wonder.id)}">{{wonder.likes}}</span><h5>{{wonder.place}}</h5><p>{{wonder.description}}</p></div></div></div></div></div></div>
</template>
<script>
/* Importing Header to use in this component */
import Header from "@/components/Header.vue";
/* Importing axios for async REST calls */
import axios from "axios";
export default {name: "Main",
/* mounted gets called when the component gets mounted. AJAX calls are preferred in mounted lifecycle method */mounted() {this.hover_flag = false;
var inside = this;
axios.get("https://www.mocky.io/v2/5c7b98562f0000c013e59f07").then(function(response) {//console.log(response);
inside.wonders_data_actual = response.data.data;
response.data.data.map(function(wonder) {inside.likes.count += wonder.likes;});
inside.wonders_data_actual = inside.wonders_data_actual.map(function(wonder) {wonder.active_like = false;return wonder;});inside.wonders_data = response.data.data;}).catch(function(error) {// console.log(error);});},
/* All the data variable declaration are done here: */data() {return {hover_flag: false,wonders_data_actual: [],wonders_data: [],active_id: 0,options: [{ value: null, text: "Sort By" },{ value: "a", text: "Ratings" },{ value: "b", text: "Likes" }],search: { filter: null, text: "" },likes: { count: 0, hit: 0 }};},
/* Methods are defined here */methods: {show_hover(flag, active_id) {this.hover_flag = flag;this.active_id = active_id;},sort() {//console.log(this.search.filter);this.search.filter == "b"? this.wonders_data.sort(function(a, b) {return b.likes - a.likes;}): this.wonders_data.sort(function(a, b) {return b.ratings - a.ratings;});},search_text() {//console.log(this.search.text);
var inside = this;
this.wonders_data = this.wonders_data_actual.filter(function(wonder) {if (wonder.place.toLowerCase().indexOf(inside.search.text.toLowerCase()) != "-1") {return wonder;}});},check_active(id) {var flag = false;this.wonders_data_actual.map(function(wonder) {if (wonder.id == id) {flag = wonder.active_like;}});return flag;},make_active(id) {this.likes.hit++;this.wonders_data_actual = this.wonders_data_actual.map(function(wonder) {if (wonder.id == id) {wonder.active_like = !wonder.active_like;wonder.active_like ? wonder.likes++ : wonder.likes--;}
return wonder;});var inside = this;
inside.likes.count = 0;this.wonders_data_actual.map(function(wonder) {inside.likes.count += wonder.likes;});}},components: {Header}
};
</script>
<style scoped> /* Styles are scoped to this component only.*/
/* Style for Desktop/Tablet */
.search-parent {display: flex;flex-flow: row wrap;justify-content: space-between;background-color: lightgray;
}
.card-inner {position: relative;overflow: hidden;box-shadow: 2px 2px 8px grey;
}
.card-img {width: 100%;
}
.card-bottom {position: absolute;bottom: 0;left: 0;height: 30px;width: 100%;background-color: white;opacity: 0.7;display: flex;justify-content: space-between;
}
.card-hover {position: absolute;right: 15px;left: 15px;top: 15px;bottom: 15px;background-color: white;opacity: 0.7;display: flex;flex-flow: column wrap;justify-content: center;align-items: center;
}
.absolute-star {position: absolute;top: 10px;right: 10px;
}
.card-hover p {font-size: 10px;text-align: center;
}
.bold {font-weight: 500;
}
.rating-div {width: 200px;
}
.search-bar {position: relative;
}
.search-bar input {padding-left: 30px;
}
.search-icon {position: absolute;top: 8px;left: 8px;
}
/* For Mobile Device, we will be going with column wrap approach */
@media screen and (max-width: 550px) {.search-parent {display: flex;flex-flow: column wrap;justify-content: center;align-items: center;background-color: lightgray;}
.search-parent div {width: 100%;text-align: center;}
}
</style>
I hope you have a better understanding of how to get started with Vue and create something awesome.
我希望您對如何開始使用Vue并創建很棒的東西有更好的了解。
If you found this helpful, clap below, give stars to the project repo and share with your friends too.
如果您覺得有幫助,請在下面拍一下,給項目回購加注 星號 ,并與您的朋友分享。
翻譯自: https://www.freecodecamp.org/news/how-to-set-up-responsive-ui-search-in-vue-js-bf6007b7fc0f/
vue 響應式ui