Vue.js에서 반응 형 UI 검색을 설정하는 방법

현재 널리 사용되는 최신 프레임 워크 중 하나를 사용하여 멋진 것을 만들려고하는데 시작하는 방법을 모르십니까?

그렇다면이 게시물은 시작을 시작하고 멋진 것을 만드는 데 도움이 될 것입니다.

무엇을 만들까요?

다음 기능을 사용하여 세계 7 대 불가사의에 대한 반응 형 클라이언트 측 검색을 구축 할 것입니다.

  1. 평점 및 좋아요를 기반으로 한 텍스트 검색필터 .
  2. 태블릿데스크톱의 경우 행당 2 개 항목 , 모바일의 경우 행당 1 개 항목 .
  3. 클라이언트 측의 외부 API에서 비동기 적으로 데이터를 가져옵니다.
  4. 아래와 같이 반응 형보기 :

라이브 데모 : //vue-responsive-search.herokuapp.com

소스 코드 : //github.com/honey93/VueSearchExample

기술 아키텍처

우리는 다음 기술로 작업 할 것입니다.

  1. Vue.js : 프로그레시브 자바 스크립트 프레임 워크
  2. BootstrapVue : Vue.js 2.5 이상에서 사용할 수있는 가장 포괄적 인 Bootstrap V4 구성 요소 및 그리드 시스템 구현 중 하나를 제공하며, 광범위하고 자동화 된 WAI-ARIA 접근성 마크 업을 완성합니다.
  3. Vue Cli 3 : Vue.js 개발을위한 표준 도구

프로젝트 구조

Vue 프로젝트를 시작하려면 Vue, Bootstrap, Vue Router, Vuex 등과 같은 많은 것을 설정해야합니다.

Vue Cli는 필요한 대부분의 구성으로 프로젝트를 생성하는 명령을 제공합니다.

npm install -g @vue/cli vue create project-name

BootstrapVue, vue-star-rating 등과 같은 나머지 항목에 대해서는 npm install 명령을 사용할 수 있습니다.

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. */ ......

위의 내용은 프로젝트 아키텍처와이를 초기화하는 방법을 설명하기위한 것입니다.

저장소 를 복제 하고 다음 명령을 작성하여 시작할 수 있습니다 .

npm install npm run serve 

몇 가지 중요한 구성 요소를 설명했습니다.

components / Header.vue

헤더는 단일 독립 구성 요소의 형태로 만들어 졌으므로 코드 중복을 방지하여 여러 페이지에서 재사용 할 수 있습니다.

/* Vue style of writing component: template, script and style*/  Responsive Search  export default { name: "Header" };   .header { display: flex; flex-flow: row wrap; justify-content: space-between; } 

components / Main.vue

이 구성 요소는 검색 / 필터의 전체 로직과 API에서 가져온 결과의 표시로 구성됩니다.

이 컴포넌트는 위의 Header를 스크립트로 가져와 사용하고 있습니다.

 Total Likes: {{likes.count}} Hits: {{likes.hit}}  Ratings: {{wonder.place}} {{wonder.likes}} 
{{wonder.place}}

{{wonder.description}}

/* 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("//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 } }; /* 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; } }

Vue를 시작하고 멋진 것을 만드는 방법을 더 잘 이해 하셨기를 바랍니다.

도움이 되었다면 아래 에서 박수를 치시고 프로젝트 저장소에 을 주고 친구들과도 공유하세요.