지난 8월에 저는 미드웨스트 JS 미네소타주 미니애폴리스에 위치한 회사에서 일하고 있습니다. 아시다시피 저는 자바스크립트 스택으로 풀 스택 애플리케이션을 개발하는 것을 매우 좋아합니다. 이번 컨퍼런스에서 제가 발표했던 내용도 바로 이것입니다.
제 세션에는 많은 개발자가 참석했고 많은 개발자가 Couchbase와 함께 Node.js를 사용하여 RESTful API를 개발하는 방법과 클라이언트 대면 계층으로 Angular를 사용하는 방법을 배웠습니다.
약속드린 대로 프레젠테이션에서 살펴본 내용을 다시 한 번 살펴보고 개념과 코드를 재현하고 확장할 수 있도록 하겠습니다.
앞으로는 다음과 같은 가정이 전제됩니다. 카우치베이스 서버, Node.js및 아이오닉 프레임워크 CLI 설치 및 구성. Couchbase는 NoSQL 데이터베이스가 되고, Node.js는 백엔드를 구동하며, Ionic Framework는 Angular로 구동되는 웹 프론트엔드를 제공합니다.
Midwest JS에서 만든 프로젝트를 통해 비디오 게임 콘솔과 다양한 콘솔용 비디오 게임에 대한 정보를 저장할 수 있었습니다. 이 프로젝트는 CRUD의 사용과 NoSQL 문서 간의 관계, 그리고 Couchbase가 이를 쉽게 만드는 방법을 보여주었습니다.
Couchbase NoSQL 백엔드로 Node.js 만들기
개발을 시작하기 전에 새 Node.js 프로젝트를 만들어야 합니다. 명령줄에서 다음을 실행합니다:
1 2 |
npm init -y npm 설치 카우치베이스 express body-파서 uuid cors --저장 |
위의 명령은 프로젝트를 생성합니다. package.json 파일을 열고 프로젝트 종속성을 설치합니다. 프로젝트의 cors
패키지를 사용하면 교차 오리진 리소스 공유 오류 없이 두 개의 다른 포트에서 로컬로 Node와 Angular를 사용할 수 있습니다. 그리고 uuid
패키지를 사용하면 문서 키로 사용할 고유 문자열을 생성할 수 있습니다. 문서 키에 본문 파서
패키지를 사용하면 HTTP 요청으로 JSON 데이터를 전송할 수 있습니다. 여기서는 다른 두 패키지를 설명하는 Express와 Couchbase를 사용하겠습니다.
만들기 app.js 파일을 생성합니다. 이 파일에는 Node.js 애플리케이션의 모든 소스 코드가 포함됩니다. 상용구는 다음과 같아야 합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var 카우치베이스 = require("couchbase"); var Express = require("express"); var 바디파서 = require("body-parser"); var UUID = require("uuid"); var Cors = require("cors"); var 앱 = Express(); var N1qlQuery = 카우치베이스.N1qlQuery; 앱.사용(바디파서.json()); 앱.사용(바디파서.urlencoded({ 확장: true })); 앱.사용(Cors()); var 클러스터 = new 카우치베이스.클러스터("couchbase://localhost"); var 버킷 = 클러스터.오픈버킷("default", ""); 앱.get("/콘솔", (요청, 응답) => {}); 앱.post("/console", (요청, 응답) => {}); 앱.post("/game", (요청, 응답) => {}); 앱.get("/games", (요청, 응답) => {}); 앱.get("/게임/:id", (요청, 응답) => {}); var 서버 = 앱.듣기(3000, () => { 콘솔.로그("포트에서 듣기" + 서버.주소().포트 + "..."); }); |
다운로드한 각 종속 요소를 가져오고, Express를 초기화 및 구성하고, Couchbase 클러스터의 버킷에 연결했음을 알 수 있습니다.
이 애플리케이션에는 5개의 서로 다른 RESTful API 엔드포인트가 있습니다.
가장 먼저 논리적으로 해야 할 일은 비디오 게임 콘솔을 만들어 게임을 추가하는 것입니다. 다음 엔드포인트 코드를 살펴보세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
앱.post("/console", (요청, 응답) => { 만약(!요청.body.title) { 반환 응답.상태(401).보내기({ "메시지": "`제목`이 필요합니다." }); } var id = UUID.v4(); 요청.body.유형 = "콘솔"; 버킷.삽입(id, 요청.body, (오류, 결과) => { 만약(오류) { 반환 응답.상태(500).보내기(오류); } 응답.보내기(결과); }); }); |
위의 로직에서, 우리는 다음을 검증하고 있습니다. title
가 요청에 존재하는지 확인합니다. 존재하는 경우 새 ID를 생성하고, 새 ID를 할당합니다. 유형
를 요청의 데이터에 추가하고 Couchbase에 삽입합니다. 삽입의 성공 또는 실패 응답은 클라이언트에 반환되며, 이는 결국 Angular 애플리케이션이 됩니다.
비디오 게임 콘솔을 쿼리하려면 다음을 기반으로 쿼리해야 합니다. 유형
속성을 사용할 수 없습니다. 따라서 ID로 조회하는 대신 N1QL 쿼리를 사용해야 합니다.
1 2 3 4 5 6 7 8 9 10 11 |
앱.get("/콘솔", (요청, 응답) => { var 문 = "SELECT `" + 버킷._name + "`.*, META().id FROM `" + 버킷._name + "` WHERE 유형 = '콘솔'"; var 쿼리 = N1qlQuery.fromString(문); 쿼리.일관성(N1qlQuery.일관성.REQUEST_PLUS); 버킷.쿼리(쿼리, (오류, 결과) => { 만약(오류) { 반환 응답.상태(500).보내기(오류); } 응답.보내기(결과); }); }); |
N1QL 쿼리는 단지 간단한 선택
문으로 쿼리를 실행합니다. 쿼리를 실행한 후 클라이언트에 응답을 반환합니다.
이제 실제 비디오 게임으로 넘어갑니다. 상황이 조금 더 복잡해지지만 더 어렵지는 않습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
앱.post("/game", (요청, 응답) => { 만약(!요청.body.title) { 반환 응답.상태(401).보내기({ "메시지": "`제목`이 필요합니다." }); } else 만약(!요청.body.cid) { 반환 응답.상태(401).보내기({ "메시지": "`cid`가 필요합니다." }); } var id = UUID.v4(); 요청.body.유형 = "game"; 버킷.삽입(id, 요청.body, (오류, 결과) => { 만약(오류) { 반환 응답.상태(500).보내기(오류); } 응답.보내기(결과); }); }); |
위의 엔드포인트 로직에서는 데이터베이스에 새 비디오 게임을 삽입할 계획입니다. 이는 새 비디오 게임 콘솔을 데이터베이스에 삽입할 때와 다르지 않습니다. 우리는 유형
속성도 있지만 cid
가 존재합니다. The cid
는 데이터와의 관계를 설정할 수 있는 콘솔 ID가 됩니다.
관계를 맺으면 다음과 같은 이점이 있습니다. JOIN
작업을 수행합니다.
1 2 3 4 5 6 7 8 9 10 11 |
앱.get("/games", (요청, 응답) => { var 문 = "SELECT game.title AS game_title, console.title AS console_title FROM `" + 버킷._name + "` AS 게임 JOIN `" + 버킷._name + "` AS 콘솔 ON KEYS game.cid WHERE game.type = 'game'"; var 쿼리 = N1qlQuery.fromString(문); 쿼리.일관성(N1qlQuery.일관성.REQUEST_PLUS); 버킷.쿼리(쿼리, (오류, 결과) => { 만약(오류) { 반환 응답.상태(500).보내기(오류); } 응답.보내기(결과); }); }); |
위의 엔드포인트에서는 또 다른 N1QL 쿼리를 수행하고 있지만 이번에는 JOIN
연산이 필요합니다. 반환하는 것은 유용하지 않습니다. cid
비디오 게임을 쿼리할 때, 저희는 JOIN
를 클릭하고 해당 정보를 다른 문서의 콘솔 제목으로 바꿉니다.
특정 비디오 게임을 찾으려고 할 때도 비슷한 쿼리가 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
앱.get("/게임/:id", (요청, 응답) => { 만약(!요청.매개변수.id) { 반환 응답.상태(401).보내기({ "메시지": "`ID`가 필요합니다." }); } var 문 = "SELECT game.title AS game_title, console.title AS console_title FROM `" + 버킷._name + "` AS 게임 JOIN `" + 버킷._name + "` 콘솔에서 콘솔로 게임.cid에 게임.유형 = '게임' 그리고 메타(게임).id = $id"; var 쿼리 = N1qlQuery.fromString(문); 버킷.쿼리(쿼리, { "id": 요청.매개변수.id }, (오류, 결과) => { 만약(오류) { 반환 응답.상태(500).보내기(오류); } 응답.보내기(결과); }); }); |
N1QL 사용의 대안 및 JOIN
연산은 ID를 기준으로 두 번의 조회를 수행하는 것입니다. 이 관행이 잘못된 것은 아니지만 제 생각에는 데이터베이스가 그냥 JOIN
대신 JOIN
애플리케이션 계층을 통해
이제 클라이언트 프론트엔드로 이동합니다.
앵귤러 프론트엔드로 Ionic 프레임워크 만들기
앞서 언급했듯이 이번에는 앵귤러를 사용하는 Ionic 프레임워크를 사용하고 있습니다. 부트스트랩이나 파운데이션으로 매력적인 프론트엔드를 만들기에는 너무 게으르다는 생각이 들어서 이 방법을 선택했습니다.
Ionic 프레임워크 CLI를 사용할 수 있는 상태에서 다음을 실행합니다:
1 |
이온 시작 pwa 사이드 메뉴 |
위의 명령은 다음과 같은 프로젝트를 생성합니다. pwa Ionic 프레임워크 사용 사이드 메뉴
템플릿을 사용합니다.
기본 템플릿은 유용하지만 필요한 모든 것이 포함되어 있지는 않습니다. 애플리케이션에 몇 페이지를 추가해야 합니다.
Ionic 프레임워크 생성기를 사용하거나 수동으로 다음을 생성합니다. 콘솔, 게임및 게임 페이지로 이동합니다. 이러한 각 페이지에는 HTML, SCSS 및 TypeScript 파일이 있어야 하며 각 페이지 디렉토리는 페이지 디렉터리로 이동합니다.
프로젝트의 app/app.component.ts 파일을 열고 다음과 같이 만듭니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
가져오기 { 구성 요소, ViewChild } 에서 '@angular/core'; 가져오기 { 탐색, 플랫폼 } 에서 '이온-각형'; 가져오기 { 상태 표시줄 } 에서 '@ionic-native/status-bar'; 가져오기 { 스플래시 화면 } 에서 '@ionic-native/splash-screen'; 가져오기 { 게임 페이지 } 에서 '../pages/games/games'; 가져오기 { 콘솔 페이지 } 에서 '../페이지/콘솔/콘솔'; @구성 요소({ templateUl: 'app.html' }) 내보내기 클래스 MyApp { @ViewChild(탐색) 탐색: 탐색; rootPage: any = 게임 페이지; 페이지: 배열<{title: 문자열, 컴포넌트: any}>; 생성자(public 플랫폼: 플랫폼, public statusBar: 상태 표시줄, public 스플래시 화면: 스플래시 화면) { 이.초기화 앱(); // ngFor 및 탐색의 예에 사용됨 이.페이지 = [ { title: '게임', 컴포넌트: 게임 페이지 }, { title: '콘솔', 컴포넌트: 콘솔 페이지 } ]; } 초기화 앱() { 이.플랫폼.준비().다음(() => { // 이제 플랫폼이 준비되었고 플러그인을 사용할 수 있습니다. // 여기에서 필요한 모든 상위 수준의 네이티브 작업을 수행할 수 있습니다. 이.statusBar.스타일 기본값(); 이.스플래시 화면.숨기기(); }); } 오픈페이지(페이지) { // 이 페이지만 표시되도록 콘텐츠 탐색을 재설정합니다. // 이 시나리오에서는 뒤로 버튼이 표시되지 않기를 원합니다. 이.탐색.setRoot(페이지.컴포넌트); } } |
다음을 가져온 것을 확인할 수 있습니다. 게임 페이지
그리고 콘솔 페이지
를 업데이트하여 페이지
배열을 추가하고 기본 루트 페이지를 게임 페이지
. 이렇게 하면 애플리케이션이 시작될 때 탐색 및 기본 페이지가 설정됩니다.
설정을 완료하려면 프로젝트의 앱/앱.모듈.ts 파일을 만듭니다. 다음과 같이 만듭니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
가져오기 { 브라우저 모듈 } 에서 '@각/플랫폼-브라우저'; 가져오기 { 오류 처리기, NgModule } 에서 '@angular/core'; 가져오기 { IonicApp, 이온 오류 처리기, 이온 모듈 } 에서 '이온-각형'; 가져오기 { HttpModule } 에서 "@angular/http"; 가져오기 { MyApp } 에서 './app.component'; 가져오기 { 게임 페이지 } 에서 '../pages/games/games'; 가져오기 { 게임 페이지 } 에서 '../pages/game/game'; 가져오기 { 콘솔 페이지 } 에서 '../페이지/콘솔/콘솔'; 가져오기 { 상태 표시줄 } 에서 '@ionic-native/status-bar'; 가져오기 { 스플래시 화면 } 에서 '@ionic-native/splash-screen'; @NgModule({ 선언: [ MyApp, 게임 페이지, 게임 페이지, 콘솔 페이지 ], 수입: [ 브라우저 모듈, HttpModule, 이온 모듈.forRoot(MyApp), ], 부트스트랩: [IonicApp], 항목 구성 요소: [ MyApp, 게임 페이지, 게임 페이지, 콘솔 페이지 ], 공급자: [ 상태 표시줄, 스플래시 화면, {제공: 오류 처리기, 사용 클래스: 이온 오류 처리기} ] }) 내보내기 클래스 앱 모듈 {} |
새 페이지를 각각 가져와서 새 페이지를 선언
그리고 항목 구성 요소
배열의 @NgModule
블록.
이제 애플리케이션 개발과 API 연결에 집중할 수 있습니다.
프로젝트의 src/pages/games/games.ts 파일을 열고 다음과 같이 만듭니다. 다음에 어떤 일이 일어나는지 자세히 설명하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
가져오기 { 구성 요소 } 에서 '@angular/core'; 가져오기 { NavController, 모달 컨트롤러 } 에서 '이온-각형'; 가져오기 { Http, 헤더, 요청 옵션 } 에서 "@angular/http"; 가져오기 "rxjs/Rx"; 가져오기 { 게임 페이지 } 에서 "../게임/게임"; @구성 요소({ 선택기: 'page-games', templateUl: 'games.html' }) 내보내기 클래스 게임 페이지 { public 게임: 배열<any>; public 생성자(public navCtrl: NavController, 비공개 http: Http, 비공개 modalCtrl: 모달 컨트롤러) { 이.게임 = []; } public ionViewDidEnter() { 이.http.get("http://localhost:3000/games") .지도(결과 => 결과.json()) .구독(결과 => { 이.게임 = 결과; }); } public create() { let 게임 모달 = 이.modalCtrl.create(게임 페이지); 게임 모달.onDidDismiss(데이터 => { let 헤더 = new 헤더({ "콘텐츠 유형": "application/json" }); let 옵션 = new 요청 옵션({ 헤더: 헤더 }); 이.http.post("http://localhost:3000/game", JSON.문자열화(데이터), 옵션) .구독(결과 => { 이.게임.push({ "game_title": 데이터.title, "콘솔_제목": ""}); }); }); 게임 모달.현재(); } } |
내 게임 페이지
클래스에는 다음과 같은 공용 변수가 있습니다. 게임
. 이 파일은 공개되어 있으므로 HTML을 통해 액세스할 수 있습니다. 여기에는 Node.js 애플리케이션에서 반환된 모든 게임이 포함됩니다.
페이지가 로드되면 엔드포인트를 쿼리하려고 합니다. 이 작업은 절대로 생성자
메서드를 사용할 수 없으므로 대신 ionViewDidEnter
메서드를 호출합니다. 요청을 실행하면 결과가 JSON으로 변환된 다음 공용 변수에 로드됩니다.
데이터베이스에 새 게임을 만들려면 상황이 조금 달라집니다. 모달 대화 상자를 표시하고 입력을 수집할 것입니다.
1 2 3 4 5 6 7 8 9 10 11 12 |
public create() { let 게임 모달 = 이.modalCtrl.create(게임 페이지); 게임 모달.onDidDismiss(데이터 => { let 헤더 = new 헤더({ "콘텐츠 유형": "application/json" }); let 옵션 = new 요청 옵션({ 헤더: 헤더 }); 이.http.post("http://localhost:3000/game", JSON.문자열화(데이터), 옵션) .구독(결과 => { 이.게임.push({ "game_title": 데이터.title, "콘솔_제목": ""}); }); }); 게임 모달.현재(); } |
그리고 create
메서드는 게임 페이지
를 입력하면 모달 형식이 됩니다. 모달의 양식에 입력된 모든 데이터는 다시 게임 페이지
를 호출하고 HTTP 요청을 통해 API로 전송합니다.
먼저 다음을 살펴보기 전에 게임 페이지
를 구동하는 HTML을 살펴보겠습니다. 게임 페이지
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<ion-헤더> <ion-navbar> <버튼 ion-버튼 메뉴토글> <ion-아이콘 이름="메뉴"></ion-아이콘> </버튼> <ion-title>게임</ion-title> <ion-버튼 끝> <버튼 ion-버튼 아이콘-만 (클릭)="create()"> <ion-아이콘 이름="추가"></ion-아이콘> </버튼> </ion-버튼> </ion-navbar> </ion-헤더> <ion-콘텐츠 패딩> <ion-목록> <버튼 ion-항목 *ngFor="렛 게임 오브 게임"> {{게임.게임 제목}} <span 클래스="item-note">{{게임.콘솔 제목}}</span> </버튼> </ion-목록> </ion-콘텐츠> |
위의 HTML에서, 우리는 공개적인 게임
배열을 사용합니다. 배열의 각 객체는 목록 내에서 화면에 렌더링됩니다. Angular가 모든 무거운 작업을 처리합니다.
프로젝트의 src/pages/game/game.ts 파일을 열고 다음을 포함하세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
가져오기 { 구성 요소 } 에서 '@angular/core'; 가져오기 { IonicPage, NavController, NavParams, ViewController } 에서 '이온-각형'; 가져오기 { Http, 헤더, 요청 옵션 } 에서 "@angular/http"; 가져오기 "rxjs/Rx"; @IonicPage() @구성 요소({ 선택기: 'page-game', templateUl: 'game.html', }) 내보내기 클래스 게임 페이지 { public 콘솔: 배열<any>; public 입력: any; 생성자(public navCtrl: NavController, public navParams: NavParams, public viewCtrl: ViewController, 비공개 http: Http) { 이.콘솔 = []; 이.입력 = { "cid": "", "title": "" } } ionViewDidEnter() { 이.http.get("http://localhost:3000/consoles") .지도(결과 => 결과.json()) .구독(결과 => { 에 대한(let i = 0; i < 결과.길이; i++) { 이.콘솔.push(결과[i]); } }); } public 저장() { 이.viewCtrl.dismiss(이.입력); } } |
이 모달 로직은 이미 살펴본 것과 유사합니다. HTML과 타입스크립트에 바인딩된 폼이 있습니다. 이 양식에서 ionViewDidEnter
트리거가 발생하면 콘솔 정보를 쿼리합니다. 이 콘솔 정보는 결국 사용자가 선택할 수 있는 라디오 목록에 사용됩니다.
사용자가 저장
메서드를 사용하면 공개 양식에 바인딩된 데이터가 이전 게임 페이지
페이지로 이동합니다.
이 모달을 구동하는 HTML은 다음에서 찾을 수 있습니다. src/pages/game/game.html 는 다음과 같이 보입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<ion-헤더> <ion-navbar> <ion-title>신규 게임</ion-title> </ion-navbar> </ion-헤더> <ion-콘텐츠 패딩> <ion-목록> <ion-항목> <ion-레이블 쌓인>제목</ion-레이블> <ion-입력 유형="text" [(ngModel)]="input.title"></ion-입력> </ion-항목> <ion-항목> <ion-레이블>콘솔</ion-레이블> <ion-선택 [(ngModel)]="input.cid"> <ion-옵션 *ngFor="콘솔의 콘솔" 값="{{ console.id }}">{{ 콘솔.title }}</ion-옵션> </ion-선택> </ion-항목> <ion-항목> <버튼 ion-버튼 전체 (클릭)="save()">저장</버튼> </ion-항목> </ion-목록> </ion-콘텐츠> |
양식을 구성하는 간단한 목록이 있습니다. 양식 요소는 TypeScript 변수에 바인딩되고 콘솔 정보가 루프되어 HTML을 채웁니다. 선택
요소입니다.
이제 Angular 프론트엔드의 마지막 페이지로 이동합니다.
프로젝트의 src/pages/consoles/consoles.ts 파일을 열고 다음을 포함하세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
가져오기 { 구성 요소 } 에서 '@angular/core'; 가져오기 { NavController, NavParams, AlertController } 에서 '이온-각형'; 가져오기 { Http, 헤더, 요청 옵션 } 에서 "@angular/http"; 가져오기 "rxjs/Rx"; @구성 요소({ 선택기: '페이지 콘솔', templateUl: '콘솔.html' }) 내보내기 클래스 콘솔 페이지 { public 콘솔: 배열<any>; public 생성자(public navCtrl: NavController, 비공개 http: Http, 비공개 alertCtrl: AlertController) { 이.콘솔 = []; } public ionViewDidEnter() { 이.http.get("http://localhost:3000/consoles") .지도(결과 => 결과.json()) .구독(결과 => { 이.콘솔 = 결과; }); } public create() { let 알림 = 이.alertCtrl.create({ title: '콘솔 추가', 입력: [ { 이름: 'title', 플레이스홀더: 'Title' }, { 이름: 'year', 플레이스홀더: 'Year' } ], 버튼: [ { 텍스트: '취소', 역할: '취소', 핸들러: 데이터 => { 콘솔.로그('취소 클릭'); } }, { 텍스트: '저장', 핸들러: 데이터 => { let 헤더 = new 헤더({ "콘텐츠 유형": "application/json" }); let 옵션 = new 요청 옵션({ 헤더: 헤더 }); 이.http.post("http://localhost:3000/console", JSON.문자열화(데이터), 옵션) .구독(결과 => { 이.콘솔.push(데이터); }, 오류 => {}); } } ] }); 알림.현재(); } } |
기존에 보셨던 것과 크게 다르지는 않지만 새로운 기능이 추가되었습니다. 새로운 비디오 게임 콘솔 정보에 대한 입력을 수집하기 위해 팝업 대화 상자를 사용하고 있습니다.
팝업이 닫히면 다음이 실행됩니다:
1 2 3 4 5 6 7 8 |
핸들러: 데이터 => { let 헤더 = new 헤더({ "콘텐츠 유형": "application/json" }); let 옵션 = new 요청 옵션({ 헤더: 헤더 }); 이.http.post("http://localhost:3000/console", JSON.문자열화(데이터), 옵션) .구독(결과 => { 이.콘솔.push(데이터); }, 오류 => {}); } |
그러면 양식에서 찾은 정보를 가져와 HTTP를 통해 API로 전송하고, API는 콘솔 정보를 데이터베이스에 저장합니다.
멋지지 않나요?
프로젝트의 src/pages/consoles/consoles.html 파일은 다음과 같습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<ion-헤더> <ion-navbar> <버튼 ion-버튼 메뉴토글> <ion-아이콘 이름="메뉴"></ion-아이콘> </버튼> <ion-title>콘솔</ion-title> <ion-버튼 끝> <버튼 ion-버튼 아이콘-만 (클릭)="create()"> <ion-아이콘 이름="추가"></ion-아이콘> </버튼> </ion-버튼> </ion-navbar> </ion-헤더> <ion-콘텐츠> <ion-목록> <버튼 ion-항목 *ngFor="콘솔의 콘솔"> {{ 콘솔.title }} <span 클래스="item-note" 항목-오른쪽> {{ 콘솔.년 }} </span> </버튼> </ion-목록> </ion-콘텐츠> |
다시 말하지만, 앞서 살펴본 다른 HTML 파일과 거의 동일합니다.
결론
방금 Midwest JS 2017에서 제가 다룬 모든 내용을 요약해 드렸습니다. NoSQL 데이터베이스인 Couchbase와 통신하는 Node.js API를 만드는 방법과 Angular 및 Ionic Framework를 사용하여 프런트엔드를 만드는 방법을 살펴봤습니다. 이는 전체 스택 애플리케이션의 몇 가지 구성 요소에 불과합니다.
다음에 대한 자세한 정보 Node.js 사용 카우치베이스의 카우치베이스 개발자 포털. 제가 다시 미드웨스트 JS로 돌아오길 원하시면 댓글로 알려주세요.