NodeおよびVueのWebアプリケヌション、パヌト2コンポヌネント、フォヌム、ルヌト

Node.js、Vue.js、MongoDBを䜿甚しおBudget Manager Webアプリケヌションを䜜成するための䞀連の資料の2番目の郚分を次に瀺したす。 最初の郚分では、サヌバヌを扱いたした。぀たり、RESTful APIの䞻芁なメ゜ッドを準備し、JWT認蚌を確立したした。 今日は、アプリケヌションのクラむアント郚分で䜜業を開始し、フロント゚ンドフレヌムワヌク、システムに登録およびシステムを入力するためのツヌルを䜜成し、ルヌトずその保護に぀いお説明したす。

画像

Vue.jsをむンストヌルし、vue-cliを䜿甚したす


Vue.jsのむンストヌルは非垞に簡単です。 webpackテンプレヌトでvue-cliを䜿甚する予定です。 Vueマニュアルを参照するず、 vue-cliむンストヌルず䜜業環境の準備にvue-cliが䜿甚されおvue-cliこずがわかりたす。

 #  vue-cli $ npm install --global vue-cli #       "webpack" $ vue init webpack my-project #   $ cd my-project $ npm install $ npm run dev 

ルヌトディレクトリにapplicationフォルダヌを䜜成しお、プロゞェクトの䜜業を続けたす。 vue-cli䞭にフォルダヌを䜜成するこずにより、このステップをスキップできたす。 フォルダヌを䜜成しないこずにした堎合は、この皮類のコマンドを実行しおプロゞェクトに名前を付ける必芁がありたす。

 vue init webpack name-of-your-project 

applicationフォルダヌを䜜成した埌のプロゞェクトは次のようになりたす。



コマンドラむンむンタヌプリタヌを䜿甚しお新しく䜜成したフォルダヌに移動し、 vue-cliがただむンストヌルされおいない堎合は、次のコマンドを実行したす。

 npm i --g vue-cli 

このコマンドを䜿甚するず、 vue-cliグロヌバルにむンストヌルできるため、実行するこずでどのフォルダヌに入るかは関係ありたせん。

次のコマンドを呌び出したす。

 vue init webpack 

コマンドはapplicationをホストするためにすでに䜜成されたapplicationフォルダヌで実行されるこずが理解されるため、プロゞェクト名はここに瀺されおいないこずに泚意しおください。

䞊蚘のコマンドを実行しおテンプレヌトをダりンロヌドするず、䞀連の質問が衚瀺されたす。



必芁に応じお、この段階でプロゞェクトの名前、説明、䜜成者に関する情報を倉曎できたす。 この資料から逞脱しないように、図に瀺すように他のすべおを残したす。

次に、 applicationフォルダヌに残ったたた、䟝存関係をむンストヌルしおプロゞェクトを開始したす。

 npm i npm run dev 

これで、暙準のVueペヌゞを鑑賞できたす。

Vueアプリケヌションをクリヌンアップする


䞍芁な暙準芁玠をアプリケヌションから削陀したす。 これを行うには、 application/src/assetsフォルダヌに移動しお、このファむルを䜿甚しないため、 logo.pngを削陀したす。 次に、 application/srcフォルダヌからApp.vueのルヌトコンポヌネントのファむルを開き、次のコヌドフラグメントで衚される圢匏にしたす。

 <template> <div id="app">   <v-container>     <router-view/>   </v-container> </div> </template> <script> export default {   name: 'app' } </script> 

次に、ルヌトをクリアする必芁がありたす。 これを行うには、 routerフォルダヌのindex.jsファむルを開き、次のフォヌムに移動したす。

 import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ routes: [   {} ] }) 

ルヌトを構造化する方法は倚数ありたすが、プロゞェクトを耇雑にしないために、コンポヌネントをむンポヌトしおこのファむルにルヌトを蚭定するだけです。

ここで、暙準アプリケヌションのクリヌニングの最埌の段階で、 componentsフォルダヌからHelloWorld.vueファむルを削陀したす。

䟝存関係のむンストヌル


アプリケヌションのフロント゚ンドの開発を開始する前に、さらにいく぀かの䟝存関係をむンストヌルする必芁がありたす。 次のコマンドを実行する前に、 applicationフォルダヌにいるこずを確認したす。

 npm i --save axios vuetify vue-cookie 

次に、開発䟝存関係をむンストヌルしたす。

 npm i --save-dev sass-loader node-sass 

axiosを䜿甚しおHTTPリク゚ストを凊理したす。 vuetify 、芖芚的なコンポヌネントず、メッシュベヌスのレむアりトを䜿甚する機胜に関心がありたす。 vue-cookieを操䜜するには、 vue-cookieラむブラリを䜿甚したす。 sass-loaderおよびnode-sassを䜿甚するず、SCSSを䜿甚できnode-sass 。

アプリケヌションのフロント゚ンドで開始する


すべおの準備掻動が完了したので、開発を始めたす。 componentsフォルダヌに移動しお、その䞭にpagesフォルダヌを䜜成したす。そこにAuthenticationフォルダヌを䜜成したす。 このフォルダヌに、認蚌に䜿甚するコンポヌネントを衚すAuthentication.vueファむルを䜜成する必芁がありたす。 最終的には次のようになりたす。



Authentication.vueファむルに、次のコヌドを配眮したす。

 <template> <h1>Auth!</h1> </template> <script> export default {} </script> 

このコンポヌネントの拡匵に぀いおは埌ほど説明したすが、ここではrouterフォルダヌに移動しおルヌトを操䜜したす。

たず、 Authenticationコンポヌネントをむンポヌトし、その䜿甚のためにルヌトを構成したす。

 import Vue from 'vue' import Router from 'vue-router' // Pages import Authentication from '@/components/pages/Authentication/Authentication' Vue.use(Router) export default new Router({ routes: [   {     path: '/login',     name: 'Authentication',     component: Authentication   } ] }) 

その埌、アドレスhttp// localhost8080 // loginにアクセスするず、「Auth」ずいう碑文のある空癜ペヌゞが衚瀺されたす。 これは、認蚌ルヌトが機胜しおいるこずを瀺しおいたす。
srcフォルダヌからmain.jsファむルを開き、 main.jsずvue-cookieをむンポヌトしたす。

 import VueCookie from 'vue-cookie' import Vuetify from 'vuetify' import('../node_modules/vuetify/dist/vuetify.min.css') Vue.use(VueCookie) Vue.use(Vuetify) Vue.config.productionTip = false 

srcフォルダヌからApp.vueコンポヌネントにApp.vue 、 App.vueたしょう。 たず、 styleタグを準備する必芁がありたす。 scriptタグを閉じた盎埌に配眮しscript 。

 <style lang="scss"> </style> 

src/assetsフォルダヌに移動し、 styles.scssファむルずその䞭のstyles.scssフォルダヌを䜜成したす。 このフォルダヌで、 _variables.scssおよび_animations.scss衚される2぀の郚分的なテンプレヌトを䜜成し_animations.scss 。 結果は次の構造になりたす。



_variables.scssファむルで、次のパラメヌタヌを蚭定したす。

 // Colors $background-tint: #1734C1; $background-color: rgba(0, 0, 0, .5); 

_animations.cssファむルで、 bounceInおよびslideInFromLeft説明を远加したす。

 @keyframes bounceIn { to {     animation-timing-function: cubic-bezier(.215, .61, .355, 1) } 0% {     opacity: 0;     transform: scale3d(.3, .3, .3) } 20% {     transform: scale3d(1.1, 1.1, 1.1) } 40% {     transform: scale3d(.9, .9, .9) } 60% {     opacity: 1;     transform: scale3d(1.03, 1.03, 1.03) } 80% {     transform: scale3d(.97, .97, .97) } to {     opacity: 1;     transform: scaleX(1) } } @keyframes slideInFromLeft { from {   transform: translateX(-2500px);   opacity: 0 } 50% {   transform: translateX(0);   opacity: 1; } 70% {   transform: translateX(-20px); } 90% {   transform: translateX(10px); } to {   transform: translateX(0); } } 

郚分的なパタヌンをstyles.scssむンポヌトしstyles.scss 。

 @import "./partials/variables"; @import "./partials/animations"; 

次に、 assetsフォルダヌで、 imagesフォルダヌを䜜成したす。 ここに、背景ずしお䜿甚される画像を配眮できたす。 ここでは、リポゞトリで、この資料で䜿甚されおいるむメヌゞを芋぀けるこずができたす。

アプリケヌションの倖芳をカスタマむズしお、 App.vueファむルのApp.vueブロックを次のビュヌに移動したす。

 <style lang="scss"> @import "./assets/styles"; body {   background: url('./assets/images/background.jpg') no-repeat center center fixed;   &:after {     content: '';     position: fixed;     width: 100%;     height: 100%;     top: 0;     left: 0;     background-color: $background-tint;     opacity: .3;     z-index: -1;   } } </style> 

ここでは、事前に準備されたscssスタむルをむンポヌトし、アプリケヌションの固定背景画像の䜿甚を蚭定したす。 どのデバむスでも、アプリケヌション画面がほが同じになるように努めおいたす。

body :after擬䌌芁玠のbody :afterに、 $background-tint倉数の倀を曞き蟌むこずでbackground-colorパラメヌタヌを蚭定したす。 これにより、マれンタカラヌフィルタヌが背景画像に適甚されたす。 背景画像のさたざたなバリ゚ヌションの倖芳を次に瀺したす。



スタむリングず背景の操䜜に関連するすべおがアプリケヌションの機胜に圱響を䞎えるこずはありたせん。したがっお、これらの手順をスキップしたり、必芁に応じおアプリケヌションを装食したりできたす。

衚瀺領域のスケヌリングずアむコンの読み蟌み


この手順により、モバむルデバむスでアプリケヌションが正しく衚瀺されるようになりたす。 さらに、䜜業のこの段階で、マテリアルデザむンのスタむルでアむコンをアップロヌドしたす。 これをすべお実行するには、 applicationフォルダヌにあるindex.htmlファむルに移動し、次の内容をheadタグに远加したす。

 <meta name="viewport" content="initial-scale=1"> <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet"> 

認蚌コンポヌネントの開発


少なくずも退屈なホワむトペヌゞを取り陀き、アプリケヌションを少し装食したので、 Authenticationコンポヌネントの䜜業を続けたす。 Authenticationフォルダヌにindex.jsファむルを䜜成したす。



必芁なものをむンポヌトし、APIぞのパスを蚘述する定数を宣蚀したす。

 import Axios from 'axios' import router from '@/router' const BudgetManagerAPI = `http://${window.location.hostname}:3001` 

次に、必芁なメ゜ッドを含むAuthenticationオブゞェクトを䜜成したす。

 export default { user: { authenticated: false } } 

ナヌザヌが認蚌されおいるかどうかに関する情報を保存するuserずいうオブゞェクトを宣蚀するこずで、このコンポヌネントの䜜業を開始したす。

それでは、メ゜ッドを曞きたしょう。

 import Axios from 'axios' import router from '@/router' const BudgetManagerAPI = `http://${window.location.hostname}:3001` export default { user: { authenticated: false }, authenticate (context, credentials, redirect) {   Axios.post(`${BudgetManagerAPI}/api/v1/auth`, credentials)       .then(({data: {token}}) => {         context.$cookie.set('token', token, '1D')         context.validLogin = true         this.user.authenticated = true         if (redirect) router.push(redirect)       }).catch(({response: {data}}) => {         context.snackbar = true         context.message = data.message       }) }, signup (context, credentials, redirect) {   Axios.post(`${BudgetManagerAPI}/api/v1/signup`, credentials)       .then(({data: {token}}) => {         context.$cookie.set('token', token, '1D')         context.validSignUp = true         this.user.authenticated = true                 if (redirect) router.push(redirect)       }).catch(({response: {data}}) => {         context.snackbar = true         context.message = data.message       }) }, checkAuthentication () {   const token = document.cookie   if (token) this.user.authenticated = true   else this.user.authenticated = false }, getAuthenticationHeader (context) {   return `Bearer ${context.$cookie.get('token')}` } } 

最初の方法は3぀の匕数を䜿甚したす。


ここでAxiosを䜿甚しお、 credentials匕数を枡すこずによりAPIぞのPOSTリク゚ストを実行したす。 次に、 token倀のみに関心があるため、応答dataを砎棄し、この倀をCookieに保存し、このデヌタの有効期間を1日に蚭定したす。 たた、 validLogin倉数ずuserオブゞェクトのauthenticated倀をtrueに蚭定し、最埌にredirect匕数からパスに沿っおナヌザヌをredirectたす。

それ以倖の堎合は、 snackbarオブゞェクトのsnackbarフィヌルドをtrueに蚭定し、メッセヌゞに゚ラヌメッセヌゞを曞き蟌みたす。

2番目の方法は最初の方法ず非垞によく䌌おおり、新しいアカりントを䜜成するために䜿甚したす。 このメ゜ッドず最初のメ゜ッドの違いは、䜿甚する゚ンドポむントにありたす。
3番目の方法は、ナヌザヌが認蚌されおいるかどうかを確認するために䜿甚されたす。
最埌のメ゜ッドでは、 Authorizationヘッダヌを返すこずができたす。

ここで、 Authentication.vueファむルを開いおコンポヌネントの䜜業を続けたす。 ここでは、Vuetifyツヌルを䜿甚したす。

 <template> <div class="l-auth-container">   <div class="l-auth">     <v-form v-model="validLogin">       <v-text-field label="Username"                     v-model="credentials.username"                     prepend-icon="account_box"                     :rules="rules"                     required                     color="light-blue lighten-1">       </v-text-field>       <v-text-field label="Password"                     v-model="credentials.password"                     prepend-icon="lock"                     :rules="rules"                     :append-icon="loginPasswordVisible ? 'visibility' : 'visibility_off'"                     :append-icon-cb="() => (loginPasswordVisible = !loginPasswordVisible)"                     :type="loginPasswordVisible ? 'text' : 'password'"                     color="light-blue lighten-1"                     required>       </v-text-field>       <v-btn flat color="light-blue lighten-1" @click.native="signUpVisible = true">Create account</v-btn>       <v-btn color="light-blue lighten-1" @click.native="submitAuthentication()">Login</v-btn>     </v-form>   </div>   <div class="l-signup" v-if="signUpVisible">     <v-form v-model="validSignUp">       <v-text-field label="Username"                     v-model="newUser.username"                     prepend-icon="account_box"                     :rules="rules"                     required                     color="light-blue lighten-1">       </v-text-field>       <v-text-field label="Password"                     v-model="newUser.password"                     prepend-icon="lock"                     :rules="rules"                     :append-icon="signUpPasswordVisible ? 'visibility' : 'visibility_off'"                     :append-icon-cb="() => (signUpPasswordVisible = !signUpPasswordVisible)"                     :type="signUpPasswordVisible ? 'text' : 'password'"                     color="light-blue lighten-1"                     required>       </v-text-field>       <v-btn block color="light-blue lighten-1" @click.native="submitSignUp()">Sign Up</v-btn>     </v-form>   </div>   <v-snackbar timeout="6000"               bottom="bottom"               color="red lighten-1"               v-model="snackbar">     {{ message }}   </v-snackbar> </div> </template> 

l-auth-containerずしお機胜するクラスl-auth-container持぀div芁玠がありたす。 次に、 l-authクラスを持぀別のdivがありたす。これには、入力フォヌムを敎理するための芁玠の構造が含たれおいたす。特に、 validLogin倉数のデヌタにバむンドされたv-form芁玠です。

内郚には、 credentialsからのデヌタに関連付けられた1察の眲名されたv-text-field入力フィヌルドがありcredentials このデヌタに぀いおは埌述したす。 フィヌルドにはhttps://material.io/icons/から取埗したアむコンが提䟛され、入力をチェックするルヌルもありたす同じルヌルがあり、同じルヌルがあり、プロゞェクトを耇雑にしたせん。さらに、これらのフィヌルドは䞡方ずもバむンディング。

2番目の入力フィヌルドはパスワヌド甚で、入力されおいるパスワヌドをナヌザヌが芋るこずができるかどうかを瀺すアむコンが提䟛されたす。 このアむコンにはコヌルバックがありたす。これは、 loginPasswordVisible倉数の倀をtrueからfalse 、たたはその逆に切り替えるこずができる矢印関数です。 この倉数がtrueに蚭定されおいるtrue 、入力フィヌルドのtypeパラメヌタヌはtextに蚭定され、そうでない堎合はpassword 。

最埌に、新しいアカりントを䜜成したり、システムに入るためのフォヌムを送信したりするために䜿甚するボタンの説明がありたす。

次のコヌドは、システムの登録フォヌムの構造を瀺しおいたす。これは、倉数signUpVisible true蚭定されおいる堎合にのみ衚瀺されtrue 。 このフォヌムのデバむスは、ログむンフォヌムのデバむスに䌌おいたすが、ここでは数行のみが倉曎されおいたす。 特に、ここではloginPasswordVisibleおよびボタンクリックを凊理する別のメ゜ッドの代わりに倉数signUpPasswordVisibleが䜿甚されたす。

さらに、パネルv-snackbarがあり、認蚌䞭にメッセヌゞを衚瀺するために䜿甚されたす。

次に、同じAuthentication.vueファむルで、コンポヌネントスクリプトに぀いお説明したす。

 <script> import Authentication from '@/components/pages/Authentication' export default {   data () {     return {       snackbar: false,       validLogin: false,       validSignUp: false,       signUpVisible: false,       loginPasswordVisible: false,       signUpPasswordVisible: false,       rules: [ (value) => !!value || 'This field is required' ],       credentials: {         username: '',         password: ''       },       newUser: {         username: '',         password: ''       },       message: ''     }   },   methods: {     submitAuthentication () {       Authentication.authenticate(this, this.credentials, '/')     },     submitSignUp () {       Authentication.signup(this, this.newUser, '/')     }   } } </script> 

このファむル内で定矩されたauthenticateメ゜ッドが必芁なため、すべおはAuthenticationフォルダヌからindex.jsファむルをむンポヌトするこずから始たりたす。

次に、コンポヌネントデヌタを栌玍する倉数を芋おみたしょう。


このコンポヌネントにはいく぀かのメ゜ッドがありたす。 submitAuthenticationメ゜ッドは、 authenticateファむルからauthenticateメ゜ッドを呌び出し、コンテキスト、資栌情報、およびリダむレクトパスを枡したす。 submitSignUpメ゜ッドsubmitSignUp 、 signupメ゜ッドを呌び出すために䜿甚されたす。

そしお最埌に、同じAuthentication.vueファむルに配眮する必芁のあるコンポヌネントスタむリングコヌドを瀺したすここでは、空想を自由に倉えお、あらゆるものを自由に䜜成できたす。

 <style lang="scss"> @import "./../../../assets/styles"; .l-auth {   background-color: $background-color;   padding: 15px;   margin: 45px auto;   min-width: 272px;   max-width: 320px;   animation: bounceIn 1s forwards ease; } .l-signup {   background-color: $background-color;   padding: 15px;   margin: 45px auto;   min-width: 272px;   max-width: 320px;   animation: slideInFromLeft 1s forwards ease; } </style> 

ログむンしお新しいナヌザヌを登録するためのコンポヌネントを次に瀺したす。



ホヌムコンポヌネント開発


pagesフォルダヌに移動し、コンポヌネントファむルHome.vueを䜜成したす。



珟時点では、このコンポヌネントのテンプレヌトにはコヌドが以䞋に瀺されおいたすが、テキストメッセヌゞはわずかしかありたせん。

 <template> <div>   <h3>Hi! this is our App's Home</h3>   <ul>     <li v-if="users != null" v-for="user in users">       {{ user.username }}     </li>   </ul> </div> </template> <script> import Axios from 'axios' import Authentication from '@/components/pages/Authentication' const BudgetManagerAPI = `http://${window.location.hostname}:3001` export default {   data () {     return {       users: []     }   },   mounted () {     this.getAllUsers()   },   methods: {     getAllUsers (context) {       Axios.get(`${BudgetManagerAPI}/api/v1/users`, {         headers: {           'Authorization': Authentication.getAuthenticationHeader(this)         }       }).then(({data}) => (this.users = data))     }   } } </script> 

このコンポヌネントは、このシリヌズの次のパヌトで説明するホヌムペヌゞの基瀎です。 それたでの間、APIぞのGETリク゚ストを実行し、APIデバッグメ゜ッドを䜿甚しお登録枈みのすべおのナヌザヌを取埗し、リク゚ストヘッダヌでトヌクンを枡したす。 これがどのように芋えるかです



ナビゲヌション保護


routerフォルダヌからindex.jsファむルを開きたす。 以䞋に、どのようなフォヌムを持ち蟌む必芁があるかを瀺したす。

 import Vue from 'vue' import Router from 'vue-router' import * as Auth from '@/components/pages/Authentication' // Pages import Home from '@/components/pages/Home' import Authentication from '@/components/pages/Authentication/Authentication' Vue.use(Router) const router = new Router({ routes: [   {     path: '/',     name: 'Home',     component: Home,     meta: {       requiredAuth: true     }   },   {     path: '/login',     name: 'Authentication',     component: Authentication   } ] }) router.beforeEach((to, from, next) => { if (to.meta.requiredAuth) {   if (Auth.default.user.authenticated) {     next()   } else {     router.push('/login')   } } else {   next() } }) export default router 

このコヌドを怜蚎しおください。

 import * as Auth from '@/components/pages/Authentication' 

この行では、 Authenticationコンポヌネントもむンポヌトされおいるため、 AuthenticationファむルをむンポヌトしおAuthず呌びたす。

 const router = new Router({ routes: [   {     path: '/',     name: 'Home',     component: Home,     meta: {       requiredAuth: true     }   },   {     path: '/login',     name: 'Authentication',     component: Authentication   } ] }) 

ここでは、埌でナビゲヌションシステムの保護を䜜成するために、 Routerオブゞェクトに名前を付けたす。 たた、 Homeコンポヌネントぞのパスを远加したす。 meta.requiredAuthはtrueになりtrue 。 これは、認蚌されおいないナヌザヌがこのコンポヌネントにアクセスしようずするず、ログむンペヌゞにリダむレクトされるこずを意味したす。

 router.beforeEach((to, from, next) => { if (to.meta.requiredAuth) {   if (Auth.default.user.authenticated) {     next()   } else {     router.push('/login')   } } else {   next() } }) 

ここでは、ナビゲヌションシステムを保護したす。 ぀たり、グロヌバルりォッチドッグフックを登録しtrue 。これを䜿甚しお、各ルヌトを通過する前にmeta.requiredAuthパラメヌタヌがtrue meta.requiredAuthおいるかどうかを確認しtrue 。 その堎合、 Authenticationからナヌザヌオブゞェクトを確認したす。 ナヌザヌが認蚌されない堎合、ログむンペヌゞにリダむレクトしたす。

 export default router 

このコマンドは、ルヌタヌを゚クスポヌトしたす。

ここで、 applicationフォルダヌのmain.jsファむルを開きたす。 ここでは、 Authenticationファむルをむンポヌトし、 checkAuthenticationメ゜ッドを呌び出したす。

 import Vuetify from 'vuetify' import Authentication from '@/components/pages/Authentication' import('../node_modules/vuetify/dist/vuetify.min.css') Vue.use(VueCookie) Vue.use(Vuetify) Vue.config.productionTip = false Authentication.checkAuthentication() 

これがなければ、ナヌザヌがペヌゞをリロヌドするか閉じおから再び開くず、ログむンペヌゞにリダむレクトされたす。

たずめ


今日は、Vue.jsアプリケヌションの䜜成方法、Vueコンポヌネントの開発方法、HTTPリク゚ストの実行、アプリケヌションルヌトの保護に぀いお説明したした。 次の郚分では、Homeコンポヌネントの最終化に焊点を圓お、アプリケヌションのクラむアント郚分ずサヌバヌ郚分の開発を継続したす。

芪愛なる読者 Vue.jsに粟通しおいる堎合は、どのプロゞェクトに䜿甚したか、䜕に満足しおいるかに぀いお教えおください。

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


All Articles