6

Nhiều người trong chúng ta đã nhảy shuffle framework JavaScript trong nhiều năm bắt đầu với jQuery, sau đó chuyển sang Angular. Nhưng Angular rất phức tạp, vì vậy chúng tôi chuyển sang React. Với React, những gì có vẻ đơn giản trên bề mặt có thể trở thành một mớ hỗn độn bực bội. Nhập Vue.js. Nó hoạt động như mong đợi. Thật nhanh. Các tài liệu là không thể tin được. Templating là hùng hồn.

Có một sự đồng thuận nhất trí xung quanh cách xử lý quản lý nhà nước, kết xuất có điều kiện, ràng buộc hai chiều, định tuyến và hơn thế nữa. Tôi đã thấy rất nhiều nhà phát triển đi trên con đường tương tự, vì vậy hôm nay tôi muốn hướng dẫn bạn cách xây dựng một ứng dụng cơ bản với Vue.js và Node. Hướng dẫn này sẽ đưa bạn từng bước thông qua việc dàn dựng dự án Vue.js, giảm tải xác thực an toàn cho API OpenID Connect (OIDC) của Okta, khóa các tuyến được bảo vệ và thực hiện các hoạt động CRUD thông qua máy chủ API REST phụ trợ. Hướng dẫn này sử dụng các công nghệ sau nhưng không yêu cầu kiến ​​thức sâu sắc để tuân theo:

Giới thiệu về Vue.js

Vue.js là một khung JavaScript mạnh mẽ nhưng đơn giản. Nó có một trong những rào cản thấp nhất để xâm nhập vào bất kỳ khung hiện đại nào trong khi cung cấp tất cả các tính năng cần thiết cho các ứng dụng web hiệu suất cao.

Hướng dẫn này bao gồm hai bản dựng chính, một ứng dụng web frontend và máy chủ API REST phụ trợ. Frontend sẽ là một ứng dụng trang duy nhất (SPA) với trang chủ, đăng nhập và đăng xuất và trình quản lý bài đăng.

OpenID Connect (OIDC) của Okta  sẽ xử lý xác thực ứng dụng web của chúng tôi thông qua việc sử dụng  SDK Vue của Okta . Nếu người dùng không được xác thực điều hướng đến trình quản lý bài đăng, ứng dụng web sẽ cố gắng xác thực người dùng.

Máy chủ sẽ chạy  Express  với  Sequelize  và  Epilogue . Ở mức cao, với Sequelize và Epilogue, bạn có thể nhanh chóng tạo các điểm cuối REST động chỉ bằng một vài dòng mã.

Bạn sẽ sử dụng xác thực dựa trên JWT khi thực hiện các yêu cầu từ ứng dụng web và  Trình xác minh JWT của Okta  trong phần mềm trung gian Express để xác thực mã thông báo. Ứng dụng của bạn sẽ hiển thị các điểm cuối sau đây, tất cả đều yêu cầu phải có mã thông báo truy cập hợp lệ.

- GET /posts
- GET /posts/:id
- POST /posts
- PUT /posts/:id
- DELETE /posts/:id


Tạo ứng dụng Vue.js của bạn

Để nhanh chóng thực hiện dự án của bạn, bạn có thể tận dụng chức năng của giàn giáo từ  vue-cli . Đối với hướng dẫn này, bạn sẽ sử dụng các  ứng dụng web tiên tiến (PWA) mẫu  bao gồm một số tính năng bao gồm  webpacknạp lại nóng , khai thác CSS, và kiểm tra đơn vị.

Nếu bạn không quen thuộc với các nguyên lý của PWA, hãy xem hướng dẫn cuối cùng của chúng tôi  về các ứng dụng web tiến bộ .

Để cài đặt  vue-cli chạy:

npm install -g vue-cli


Tiếp theo, bạn cần khởi tạo dự án của bạn. Khi bạn chạy  vue init lệnh, chỉ cần chấp nhận tất cả các giá trị mặc định.

vue init pwa my-vue-app
cd ./my-vue-app
npm install
npm run dev


Trỏ trình duyệt yêu thích của bạn  http://localhost:8080 và bạn sẽ thấy thành quả lao động của mình:

Tín dụng bổ sung : Kiểm tra các mẫu khác   có sẵn cho  vue-cli.

Cài đặt Bootstrap

Hãy cài đặt  bootstrap-vue  để bạn có thể tận dụng các thành phần có sẵn khác nhau   (cộng với bạn có thể tập trung vào chức năng chứ không phải CSS tùy chỉnh):

npm i --save bootstrap-vue bootstrap


Để hoàn tất cài đặt, hãy sửa đổi  ./src/main.js để bao gồm  bootstrap-vue  và nhập các tệp CSS cần thiết. Tệp của bạn  ./src/main.js sẽ trông như thế này:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})


Thêm xác thực với Okta

Xử lý xác thực trong một ứng dụng web là nguyên nhân tồn tại của mọi nhà phát triển. Đó là nơi Okta đến để bảo mật các ứng dụng web của bạn với mã tối thiểu. Để bắt đầu, bạn sẽ cần tạo một ứng dụng OIDC trong Okta. Đăng ký tài khoản nhà phát triển miễn phí mãi mãi  (hoặc đăng nhập nếu bạn đã có tài khoản ).

Sau khi đăng nhập, hãy tạo một ứng dụng mới bằng cách nhấp vào Thêm Thêm ứng dụng.

Chọn tùy chọn nền tảng ứng dụng duy nhất của Trang.

Các cài đặt ứng dụng mặc định phải giống như trong ảnh.

Để cài đặt SDK Okta Vue, hãy chạy lệnh sau:

npm i --save @okta/okta-vue


Mở  ./src/router/index.js và thay thế toàn bộ tập tin với mã sau đây.

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import PostsManager from '@/components/PostsManager'
import Auth from '@okta/okta-vue'

Vue.use(Auth, {
  issuer: 'https://{yourOktaDomain}.com/oauth2/default',
  client_id: '{yourClientId}',
  redirect_uri: 'http://localhost:8080/implicit/callback',
  scope: 'openid profile email'
})

Vue.use(Router)

let router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    },
    {
      path: '/implicit/callback',
      component: Auth.handleCallback()
    },
    {
      path: '/posts-manager',
      name: 'PostsManager',
      component: PostsManager,
      meta: {
        requiresAuth: true
      }
    }
  ]
})

router.beforeEach(Vue.prototype.$auth.authRedirectGuard())

export default router


Bạn sẽ cần phải thay thế  {yourOktaDomain} và  {yourClientId} có thể tìm thấy trên trang tổng quan về ứng dụng của bạn trong Bảng điều khiển dành cho nhà phát triển Okta. Điều này sẽ đưa một  authClient đối tượng vào đối tượng Vue của bạn có thể được truy cập bằng cách gọi this.$auth bất cứ nơi nào trong đối tượng Vue  của bạn.

Vue.use(Auth, {
  issuer: 'https://{yourOktaDomain}.com/oauth2/default',
  client_id: '{yourClientId}',
  redirect_uri: 'http://localhost:8080/implicit/callback',
  scope: 'openid profile email'
})


Bước cuối cùng của luồng xác thực của Okta là chuyển hướng người dùng quay lại ứng dụng của bạn với các giá trị mã thông báo trong URL. Thành  Auth.handleCallback() phần có trong SDK xử lý chuyển hướng và duy trì mã thông báo trên trình duyệt.

{
  path: '/implicit/callback',
  component: Auth.handleCallback()
}


Bạn cũng cần khóa các tuyến được bảo vệ khỏi sự truy cập của người dùng không được xác thực. Điều này được thực hiện bằng cách thực hiện một  bảo vệ điều hướng . Như tên cho thấy,  bảo vệ điều hướng  chủ yếu được sử dụng để bảo vệ điều hướng bằng cách chuyển hướng hoặc hủy bỏ.

SDK đi kèm với phương pháp  auth.authRedirectGuard() kiểm tra siêu dữ liệu của các tuyến phù hợp với khóa  requiresAuth và chuyển hướng người dùng đến luồng xác thực nếu chúng không được xác thực.

router.beforeEach(Vue.prototype.$auth.authRedirectGuard())


Với bảo vệ điều hướng này được cài đặt, bất kỳ tuyến đường nào có siêu dữ liệu sau sẽ được bảo vệ.

meta: {
  requiresAuth: true
}


Tùy chỉnh bố cục ứng dụng của bạn trong Vue

Bố cục của ứng dụng web nằm trong một thành phần  ./src/App.vue. Bạn có thể sử dụng   thành phần xem bộ định tuyến để hiển thị thành phần phù hợp cho đường dẫn đã cho.

Đối với menu chính, bạn sẽ muốn thay đổi mức độ hiển thị của các mục menu nhất định dựa trên trạng thái của  activeUser:

  • Không được xác thực: Chỉ hiển thị  Đăng nhập
  • Đã xác thực: Chỉ hiển thị  Đăng xuất

Bạn có thể chuyển đổi mức độ hiển thị của các mục menu này bằng cách sử dụng lệnh  v-if trong Vue.js để kiểm tra sự tồn tại của  activeUserthành phần. Khi thành phần được tải (mà gọi  created()) hoặc khi một tuyến đường thay đổi, chúng tôi muốn làm mới  activeUser.

Mở  ./src/App.vue và sao chép / dán mã sau đây.

<template>
  <div id="app">
    <b-navbar toggleable="md" type="dark" variant="dark">
      <b-navbar-toggle target="nav_collapse"></b-navbar-toggle>
      <b-navbar-brand to="/">My Vue App</b-navbar-brand>
      <b-collapse is-nav id="nav_collapse">
        <b-navbar-nav>
          <b-nav-item to="/">Home</b-nav-item>
          <b-nav-item to="/posts-manager">Posts Manager</b-nav-item>
          <b-nav-item href="#" @click.prevent="login" v-if="!activeUser">Login</b-nav-item>
          <b-nav-item href="#" @click.prevent="logout" v-else>Logout</b-nav-item>
        </b-navbar-nav>
      </b-collapse>
    </b-navbar>
    <!-- routes will be rendered here -->
    <router-view />
  </div>
</template>

<script>

export default {
  name: 'app',
  data () {
    return {
      activeUser: null
    }
  },
  async created () {
    await this.refreshActiveUser()
  },
  watch: {
    // everytime a route is changed refresh the activeUser
    '$route': 'refreshActiveUser'
  },
  methods: {
    login () {
      this.$auth.loginRedirect()
    },
    async refreshActiveUser () {
      this.activeUser = await this.$auth.getUser()
    },
    async logout () {
      await this.$auth.logout()
      await this.refreshActiveUser()
      this.$router.push('/')
    }
  }
}
</script>


Mỗi lần đăng nhập phải có đăng xuất. Đoạn mã sau sẽ đăng xuất người dùng của bạn, làm mới người dùng đang hoạt động (hiện không có giá trị) và sau đó chuyển hướng người dùng đến trang chủ. Phương pháp này được gọi khi người dùng nhấp vào liên kết đăng xuất trong điều hướng.

async logout () {
  await this.$auth.logout()
  await this.refreshActiveUser()
  this.$router.push('/')
}


Các thành phần  là các khối xây dựng trong Vue.js. Mỗi trang của bạn sẽ được xác định trong ứng dụng dưới dạng một thành phần. Vì mẫu webpack vue-cli sử dụng  trình tải vue , các tệp nguồn thành phần của bạn có một quy ước tách biệt mẫu, tập lệnh và kiểu ( xem tại đây ).

Bây giờ bạn đã thêm vue-bootstrap, hãy sửa đổi  ./src/components/Hello.vue để xóa các liên kết soạn sẵn mà vue-cli tạo ra.

<template>
  <div class="hero">
    <div>
      <h1 class="display-3">Hello World</h1>
      <p class="lead">This is the homepage of your vue app</p>
    </div>
  </div>
</template>

<style>
  .hero {
    height: 90vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }
  .hero .lead {
    font-weight: 200;
    font-size: 1.5rem;
  }
</style>


Tại thời điểm này, bạn có thể bỏ qua trang Trình quản lý bài để kiểm tra luồng xác thực của mình. Khi bạn xác nhận hoạt động xác thực, bạn sẽ bắt đầu xây dựng các lệnh gọi và các thành phần API cần thiết để thực hiện các thao tác CRUD trên mô hình Bài đăng của mình.

Tạo một tệp mới  ./src/components/PostsManager.vue và dán mã sau đây:

<template>
  <div class="container-fluid mt-4">
    <h1 class="h1">Posts Manager</h1>
    <p>Only authenticated users should see this page</p>
  </div>
</template>


Hãy sử dụng Vue.js Frontend và Auth Flows để lái thử

Trong thiết bị đầu cuối của bạn chạy  npm run dev (nếu nó chưa chạy). Điều hướng đến  http://localhost:8080 và bạn sẽ thấy trang chủ mới.

Nếu bạn nhấp vào  Trình quản lý bài đăng  hoặc  Đăng nhập,  bạn sẽ được chuyển đến luồng của Okta. Nhập thông tin tài khoản dev Okta của bạn.

LƯU Ý:  Nếu bạn đã đăng nhập vào Tài khoản nhà phát triển Okta, bạn sẽ được chuyển hướng tự động trở lại ứng dụng. Bạn có thể kiểm tra điều này bằng cách sử dụng chế độ duyệt web ẩn danh hoặc riêng tư.

Nếu thành công, bạn nên quay lại trang chủ đăng nhập.

Nhấp vào   liên kết Trình quản lý bài đăng sẽ hiển thị thành phần được bảo vệ.

Thêm một máy chủ API REST cuối cùng

Giờ đây, người dùng có thể xác thực an toàn, bạn có thể xây dựng máy chủ API REST để thực hiện các thao tác CRUD trên mô hình bài đăng. Thêm các phụ thuộc sau vào dự án của bạn:

npm i --save express cors @okta/jwt-verifier sequelize sqlite3 epilogue axios


Sau đó, tạo tập tin  ./src/server.js và dán mã sau đây.

const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const Sequelize = require('sequelize')
const epilogue = require('epilogue')
const OktaJwtVerifier = require('@okta/jwt-verifier')

const oktaJwtVerifier = new OktaJwtVerifier({
  clientId: '{yourClientId}',
  issuer: 'https://{yourOktaDomain}.com/oauth2/default'
})

let app = express()
app.use(cors())
app.use(bodyParser.json())

// verify JWT token middleware
app.use((req, res, next) => {
  // require every request to have an authorization header
  if (!req.headers.authorization) {
    return next(new Error('Authorization header is required'))
  }
  let parts = req.headers.authorization.trim().split(' ')
  let accessToken = parts.pop()
  oktaJwtVerifier.verifyAccessToken(accessToken)
    .then(jwt => {
      req.user = {
        uid: jwt.claims.uid,
        email: jwt.claims.sub
      }
      next()
    })
    .catch(next) // jwt did not verify!
})

// For ease of this tutorial, we are going to use SQLite to limit dependencies
let database = new Sequelize({
  dialect: 'sqlite',
  storage: './test.sqlite'
})

// Define our Post model
// id, createdAt, and updatedAt are added by sequelize automatically
let Post = database.define('posts', {
  title: Sequelize.STRING,
  body: Sequelize.TEXT
})

// Initialize epilogue
epilogue.initialize({
  app: app,
  sequelize: database
})

// Create the dynamic REST resource for our Post model
let userResource = epilogue.resource({
  model: Post,
  endpoints: ['/posts', '/posts/:id']
})

// Resets the database and launches the express app on :8081
database
  .sync({ force: true })
  .then(() => {
    app.listen(8081, () => {
      console.log('listening to port localhost:8081')
    })
  })


Đảm bảo thay thế các biến  {yourOktaDomain} và  {clientId} trong đoạn mã trên bằng các giá trị từ ứng dụng OIDC của bạn trong Okta.

Thêm phần tiếp theo

Sequelize  là ORM dựa trên lời hứa cho Node.js. Nó hỗ trợ các phương ngữ PostgreSQL, MySQL, SQLite và MSSQL và có tính năng hỗ trợ giao dịch vững chắc, quan hệ, sao chép đọc, v.v.

Để dễ dàng cho hướng dẫn này, bạn sẽ sử dụng SQLite để hạn chế các phụ thuộc bên ngoài. Đoạn mã sau khởi tạo một thể hiện Sequelize bằng SQLite làm trình điều khiển của bạn.

let database = new Sequelize({
  dialect: 'sqlite',
  storage: './test.sqlite'
})


Mỗi bài có một  title và  body. (Các trường  createdAtvà  updatedAt được thêm vào bởi Sequelize tự động). Với Sequelize, bạn xác định các mô hình bằng cách gọi  define() ví dụ của bạn.

let Post = database.define('posts', {
  title: Sequelize.STRING,
  body: Sequelize.TEXT
})


Thêm phần kết

Epilogue  tạo các điểm cuối REST linh hoạt từ các mô hình Sequelize trong ứng dụng Express. Nếu bạn đã từng mã hóa các điểm cuối REST, bạn sẽ biết có bao nhiêu sự lặp lại. FTW KHÔ!

// Initialize epilogue
epilogue.initialize({
  app: app,
  sequelize: database
})

// Create the dynamic REST resource for our Post model
let userResource = epilogue.resource({
  model: Post,
  endpoints: ['/posts', '/posts/:id']
})


Xác nhận JWT của bạn

Đây là thành phần quan trọng nhất của máy chủ API REST của bạn. Không có phần mềm trung gian này, bất kỳ người dùng nào cũng có thể thực hiện các thao tác CRUD trên cơ sở dữ liệu của chúng tôi. Nếu không có tiêu đề ủy quyền nào hoặc mã thông báo truy cập không hợp lệ, lệnh gọi API sẽ thất bại và trả về lỗi.

// verify JWT token middleware
app.use((req, res, next) => {
  // require every request to have an authorization header
  if (!req.headers.authorization) {
    return next(new Error('Authorization header is required'))
  }
  let parts = req.headers.authorization.trim().split(' ')
  let accessToken = parts.pop()
  oktaJwtVerifier.verifyAccessToken(accessToken)
    .then(jwt => {
      req.user = {
        uid: jwt.claims.uid,
        email: jwt.claims.sub
      }
      next()
    })
    .catch(next) // jwt did not verify!
})


Chạy máy chủ

Mở một cửa sổ terminal mới và chạy máy chủ bằng lệnh  node ./src/server. Bạn sẽ thấy thông tin gỡ lỗi từ Sequelize và ứng dụng nghe trên cổng 8081.

Hoàn thành thành phần quản lý bài viết

Bây giờ máy chủ API REST đã hoàn tất, bạn có thể bắt đầu kết nối trình quản lý bài đăng của mình để tìm nạp bài đăng, tạo bài đăng, chỉnh sửa bài đăng và xóa bài đăng.

Tôi luôn tập trung các tích hợp API của mình vào một mô đun trợ giúp duy nhất. Điều này giữ cho mã trong các thành phần sạch hơn nhiều và cung cấp vị trí duy nhất trong trường hợp bạn cần thay đổi bất cứ điều gì với yêu cầu API.

Tạo một tệp  ./src/api.js và sao chép / dán đoạn mã sau vào nó:

import Vue from 'vue'
import axios from 'axios'

const client = axios.create({
  baseURL: 'http://localhost:8081/',
  json: true
})

export default {
  async execute (method, resource, data) {
    // inject the accessToken for each request
    let accessToken = await Vue.prototype.$auth.getAccessToken()
    return client({
      method,
      url: resource,
      data,
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
    }).then(req => {
      return req.data
    })
  },
  getPosts () {
    return this.execute('get', '/posts')
  },
  getPost (id) {
    return this.execute('get', `/posts/${id}`)
  },
  createPost (data) {
    return this.execute('post', '/posts', data)
  },
  updatePost (id, data) {
    return this.execute('put', `/posts/${id}`, data)
  },
  deletePost (id) {
    return this.execute('delete', `/posts/${id}`)
  }
}


Khi bạn xác thực bằng OIDC, mã thông báo truy cập được duy trì cục bộ trong trình duyệt. Vì mỗi yêu cầu API phải có mã thông báo truy cập, bạn có thể tìm nạp nó từ ứng dụng khách xác thực và đặt nó trong yêu cầu.

let accessToken = await Vue.prototype.$auth.getAccessToken()
return client({
  method,
  url: resource,
  data,
  headers: {
    Authorization: `Bearer ${accessToken}`
  }
})


Bằng cách tạo các phương thức proxy sau bên trong trình trợ giúp API của bạn, mã bên ngoài mô đun trình trợ giúp vẫn sạch và có ngữ nghĩa.

getPosts () {
  return this.execute('get', '/posts')
},
getPost (id) {
  return this.execute('get', `/posts/${id}`)
},
createPost (data) {
  return this.execute('post', '/posts', data)
},
updatePost (id, data) {
  return this.execute('put', `/posts/${id}`, data)
},
deletePost (id) {
  return this.execute('delete', `/posts/${id}`)
}


Bây giờ bạn có tất cả các thành phần cần thiết để kết nối thành phần trình quản lý bài đăng của mình để thực hiện các thao tác CRUD thông qua API REST. Mở  ./src/components/PostsManager.vue và sao chép / dán mã sau đây.

<template>
  <div class="container-fluid mt-4">
    <h1 class="h1">Posts Manager</h1>
    <b-alert :show="loading" variant="info">Loading...</b-alert>
    <b-row>
      <b-col>
        <table class="table table-striped">
          <thead>
            <tr>
              <th>ID</th>
              <th>Title</th>
              <th>Updated At</th>
              <th>&nbsp;</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="post in posts" :key="post.id">
              <td>{{ post.id }}</td>
              <td>{{ post.title }}</td>
              <td>{{ post.updatedAt }}</td>
              <td class="text-right">
                <a href="#" @click.prevent="populatePostToEdit(post)">Edit</a> - 
                <a href="#" @click.prevent="deletePost(post.id)">Delete</a>
              </td>
            </tr>
          </tbody>
        </table>
      </b-col>
      <b-col lg="3">
        <b-card :title="(model.id ? 'Edit Post ID#' + model.id : 'New Post')">
          <form @submit.prevent="savePost">
            <b-form-group label="Title">
              <b-form-input type="text" v-model="model.title"></b-form-input>
            </b-form-group>
            <b-form-group label="Body">
              <b-form-textarea rows="4" v-model="model.body"></b-form-textarea>
            </b-form-group>
            <div>
              <b-btn type="submit" variant="success">Save Post</b-btn>
            </div>
          </form>
        </b-card>
      </b-col>
    </b-row>
  </div>
</template>

<script>
import api from '@/api'
export default {
  data () {
    return {
      loading: false,
      posts: [],
      model: {}
    }
  },
  async created () {
    this.refreshPosts()
  },
  methods: {
    async refreshPosts () {
      this.loading = true
      this.posts = await api.getPosts()
      this.loading = false
    },
    async populatePostToEdit (post) {
      this.model = Object.assign({}, post)
    },
    async savePost () {
      if (this.model.id) {
        await api.updatePost(this.model.id, this.model)
      } else {
        await api.createPost(this.model)
      }
      this.model = {} // reset form
      await this.refreshPosts()
    },
    async deletePost (id) {
      if (confirm('Are you sure you want to delete this post?')) {
        // if we are editing a post we deleted, remove it from the form
        if (this.model.id === id) {
          this.model = {}
        }
        await api.deletePost(id)
        await this.refreshPosts()
      }
    }
  }
}
</script>


Danh sách bài viết

Bạn sẽ sử dụng  api.getPosts() để tìm nạp các bài đăng từ máy chủ API REST của mình. Bạn nên làm mới danh sách các bài đăng khi thành phần được tải và sau bất kỳ hoạt động đột biến nào (tạo, cập nhật hoặc xóa).

async refreshPosts () {
  this.loading = true
  this.posts = await api.getPosts()
  this.loading = false
}


Thuộc tính  this.loading được bật để UI có thể phản ánh lệnh gọi API đang chờ xử lý. Bạn có thể không thấy thông báo tải vì yêu cầu API không được truy cập internet.

Tạo bài viết

Một hình thức được bao gồm trong thành phần để lưu một bài. Nó được nối dây để gọi  savePosts() khi biểu mẫu được gửi và đầu vào của nó được liên kết với  model đối tượng trên thành phần.

Khi  savePost() được gọi, nó sẽ thực hiện cập nhật hoặc tạo dựa trên sự tồn tại của  model.id. Đây chủ yếu là một phím tắt để không phải xác định hai hình thức riêng biệt để tạo và cập nhật.

async savePost () {
  if (this.model.id) {
    await api.updatePost(this.model.id, this.model)
  } else {
    await api.createPost(this.model)
  }
  this.model = {} // reset form
  await this.refreshPosts()
}


Đang cập nhật bài viết

Khi cập nhật một bài đăng, trước tiên bạn phải tải bài vào biểu mẫu. Bộ  model.id này sẽ kích hoạt một bản cập nhật  savePost().

async populatePostToEdit (post) {
  this.model = Object.assign({}, post)
}


Quan trọng:  Cuộc  Object.assign() gọi sao chép giá trị của đối số bài thay vì tham chiếu. Khi xử lý đột biến các đối tượng trong Vue, bạn phải luôn đặt thành giá trị, không tham chiếu.

Xóa bài viết

Để xóa một bài viết chỉ cần gọi  api.deletePost(id). Luôn luôn tốt để xác nhận trước khi xóa, vì vậy hãy ném vào hộp cảnh báo xác nhận gốc để đảm bảo nhấp chuột là có chủ ý.

async deletePost (id) {
  if (confirm('Are you sure you want to delete this post?')) {
    await api.deletePost(id)
    await this.refreshPosts()
  }
}


Kiểm tra ứng dụng Vue.js + Node CRUD của bạn

Hãy chắc chắn rằng cả máy chủ và frontend đang chạy.

Nhà ga số 1

node ./src/server


Nhà ga số 2

npm run dev


Điều hướng đến  http://localhost:8080 và cho nó một xoáy.

Làm nhiều hơn với Vue!

Như tôi đã nói ở đầu bài này, tôi nghĩ Vue đứng đầu và vai trên các khuôn khổ khác. Dưới đây là năm lý do nhanh chóng tại sao:

Tôi đã trình bày rất nhiều tài liệu trong hướng dẫn này nhưng đừng cảm thấy tồi tệ nếu bạn không nắm bắt mọi thứ lần đầu tiên. Bạn càng làm việc với các công nghệ này, chúng sẽ càng trở nên quen thuộc hơn.

Để tìm hiểu thêm về Vue.js, hãy truy  cập https://vuejs.org  hoặc xem các tài nguyên tuyệt vời khác từ  nhóm @oktadev :

Bạn có thể tìm mã nguồn cho ứng dụng được phát triển trong bài đăng này tại  https://github.com/oktadeveloper/okta-vue-node-example .

Hãy phản hồi ý kiến ​​của tôi bằng bất kỳ câu hỏi nào và như mọi khi, hãy theo dõi  @oktadev  trên Twitter để xem tất cả nội dung thú vị mà nhóm phát triển của chúng tôi đang tạo ra.

Xây dựng Ứng dụng CRUD cơ bản với Vue.js và Node ban đầu được xuất bản trên blog của nhà phát triển Okta vào ngày 15 tháng 2 năm 2018.

|