[Статья устарела, вы можете прочитать ее непосредственнокод, есть последние обновления]
GraphQL имеет язык запросов для вашего API, прибыл 2018 года, и PWA не был введен в много денег, а приложение GraphQl не может быть слишком далеко. Самая большая особенность фронтальной разработки является быстрой, а иногда есть много версий или модификаций для разработки многих версий или модификаций к интерфейсу. Различный бизнес полагается на мощную базовую платформу данных быстро растут, насколько эффективно предоставляет поддержку данных для различных услуг и обеспокоен всем. И теперь верхнее решение состоит в том, чтобы сделать компонент просмотра, каждая линия движения может быть либо пользователем, либо изготовителем компонента, если можно предоставить ему содержимое содержимого, необходимо его использовать , это неизбежно. Сохранить ценное время развития и развитие рабочей силы. Затем возникает проблема, передний конец проходит мультиплексирование кросс-службы через компоненты, как задний интерфейс улучшает эффективность разработки? GraphQL - это новая идея, чтобы ответить на сложные сцены.
Официальное объяснение:
GraphQL — это и язык запросов для API, и среда выполнения, которая удовлетворяет вашим запросам данных. GraphQL предоставляет полное и простое для понимания описание данных в вашем API, позволяя клиентам получать именно те данные, которые им нужны, без какой-либо избыточности, упрощая развитие API с течением времени, и может использоваться для создания мощных инструментов разработчика. .
Вот некоторые из преимуществ GraphQL:
-
Запрашивать не больше и не меньше данных
-
Получение нескольких ресурсов одним запросом
-
Поля для пользовательских данных интерфейса
-
Мощные инструменты разработчика
-
Эволюция API без управления версиями
В этой статье мы реализуем пример запроса GraphQL с koa, постепенно от простого сервиса kao до запроса на вставку данных mongodb и использования GraphQL, Пусть все быстро увидят:
- Создайте koa для создания серверного проекта
- Простой метод обработки фоновой маршрутизации
- Простая работа mongodb с мангустом
- Начало работы с GraphQL
Проект показан ниже
1. Создайте интерфейс запроса инструмента GraphQL.
2. Как использовать jq для отправки ajax на внешний интерфейс
Мы уже просмотрели проекты начального уровня, давайте приступим к их разработке! ! !
lets do it
Сначала создайте папку проекта, а затем создайте новую в этой папке проекта.server.js
(сервис узла),config文件夹
,mongodb文件夹
,router文件夹
,controllers文件夹
так же какpublic文件夹
(Это в основном размещается на странице отображения статических данных переднего плана), хорошо, мы уже установили структуру проекта, следующее находится вserver.js
пиши в папку
server.js
// 引入模块
import Koa from 'koa'
import KoaStatic from 'koa-static'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'
const app = new Koa()
const router = new Router();
// 使用 bodyParser 和 KoaStatic 中间件
app.use(bodyParser());
app.use(KoaStatic(__dirname + '/public'));
// 路由设置test
router.get('/test', (ctx, next) => {
ctx.body="test page"
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(4000);
console.log('graphQL server listen port: ' + 4000)
в командной строкеnpm install koa koa-static koa-router koa-bodyparser --save
Установите вышеуказанные модули,
затем бегиnode server.js
, если ничего неожиданного, вы обнаружите ошибку, как показано ниже
Причина в том, что текущая версия не поддерживает внедрение модуля узла ES6.
Не волнуйтесь, мы используем артефактbabel-polyfill
Достаточно перевести. Подробности см. в книге Учителя Жуань Ифэн.эта статья
Создайте новый в папке проектаstart.js
, а затем напишите в нем следующий код:
start.js
require('babel-core/register')({
'presets': [
'stage-3',
["latest-node", { "target": "current" }]
]
})
require('babel-polyfill')
require('./server')
Затем в командной строке запуститеnpm install babel-core babel-polyfill babel-preset-latest-node babel-preset-stage-3 --save-dev
Установите несколько модулей разработки.
После установки запустите в командной строкеnode start.js
, и тогда служба вашего узла будет работать спокойно. использоватьkoa-routerПромежуточное ПО управляет модулем маршрутизации нашего проекта, который будет написан позжеrouter文件夹
Централизованное управление.
Откройте браузер и введитеlocalhost:4000/test
, вы обнаружите, что доступ к этой службе узла маршрутизации вернетtest page
Слово. Как показано ниже
да~~ после того, как сервер kao в основном настроен, следующая ссылкаmongodb
затем сохраните данные вmongodb
Внутри базы данных.
Реализовать базовую модель данных mongodb
Совет: здесь нам нужноmongodb
хранить данные и использовать ихmongoose
Работа модуляmongodb
база данных
-
существует
mongodb文件夹
создать новыйindex.js
а такжеschema文件夹
, существуетschema文件夹
новая папка нижеinfo.js
а такжеstudent.js
. -
существует
config文件夹
Создатьindex.js
, Этот файл в основном предназначен для размещения кода конфигурации.
После создания очередной волны файлов сначалаconfig/index.js
Запишите код для конфигурации связанной базы данных.
config/index.js
export default {
dbPath: 'mongodb://localhost/graphql'
}
затем вmongodb/index.js
Напишите код для связи с базой данных.
mongodb/index.js
// 引入mongoose模块
import mongoose from 'mongoose'
import config from '../config'
// 同步引入 info model和 studen model
require('./schema/info')
require('./schema/student')
// 链接mongodb
export const database = () => {
mongoose.set('debug', true)
mongoose.connect(config.dbPath)
mongoose.connection.on('disconnected', () => {
mongoose.connect(config.dbPath)
})
mongoose.connection.on('error', err => {
console.error(err)
})
mongoose.connection.on('open', async () => {
console.log('Connected to MongoDB ', config.dbPath)
})
}
Над нашим кодом также загруженinfo.js
а такжеstuden.js
Это две модели данных дополнительной информации и основной информации учащихся, почему они разделены на две информационные таблицы? Причина в том, чтобы, кстати, познакомить вас с основным методом запроса объединенной таблицы (хе-хе~~~)
Ниже мы завершаем две модели данных по отдельности.
mongodb/schema/info.js
// 引入mongoose
import mongoose from 'mongoose'
//
const Schema = mongoose.Schema
// 实例InfoSchema
const InfoSchema = new Schema({
hobby: [String],
height: String,
weight: Number,
meta: {
createdAt: {
type: Date,
default: Date.now()
},
updatedAt: {
type: Date,
default: Date.now()
}
}
})
// 在保存数据之前跟新日期
InfoSchema.pre('save', function (next) {
if (this.isNew) {
this.meta.createdAt = this.meta.updatedAt = Date.now()
} else {
this.meta.updatedAt = Date.now()
}
next()
})
// 建立Info数据模型
mongoose.model('Info', InfoSchema)
Приведенный выше код используетmongoose
Реализована модель данных дополнительной информации студентов, и точно так же реализуем модель данных студента.
mongodb/schema/student.js
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const ObjectId = Schema.Types.ObjectId
const StudentSchema = new Schema({
name: String,
sex: String,
age: Number,
info: {
type: ObjectId,
ref: 'Info'
},
meta: {
createdAt: {
type: Date,
default: Date.now()
},
updatedAt: {
type: Date,
default: Date.now()
}
}
})
StudentSchema.pre('save', function (next) {
if (this.isNew) {
this.meta.createdAt = this.meta.updatedAt = Date.now()
} else {
this.meta.updatedAt = Date.now()
}
next()
})
mongoose.model('Student', StudentSchema)
Реализовать контроллер, сохраняющий данные
После того, как модель данных связана, мы добавляем несколько методов для хранения данных, которые прописываются в контроллере. Затем создайте новый в контроллереinfo.js
а такжеstudent.js
, эти два файла являются соответственно объектами, контроллерами для операционной информации и данных учащихся, и они написаны отдельно для облегчения модульного управления.
- Реализовать сохранение инфо данных информации, кстати сначала напишите запрос, код очень простой
controlers/info.js
import mongoose from 'mongoose'
const Info = mongoose.model('Info')
// 保存info信息
export const saveInfo = async (ctx, next) => {
// 获取请求的数据
const opts = ctx.request.body
const info = new Info(opts)
const saveInfo = await info.save() // 保存数据
console.log(saveInfo)
// 简单判断一下 是否保存成功,然后返回给前端
if (saveInfo) {
ctx.body = {
success: true,
info: saveInfo
}
} else {
ctx.body = {
success: false
}
}
}
// 获取所有的info数据
export const fetchInfo = async (ctx, next) => {
const infos = await Info.find({}) // 数据查询
if (infos.length) {
ctx.body = {
success: true,
info: infos
}
} else {
ctx.body = {
success: false
}
}
}
Приведенный выше код представляет собой данные, запрашиваемые внешним интерфейсом с публикацией (маршрут будет написан через некоторое время), а затем сохраняются в базе данных mongodb и возвращаются на внешний интерфейс, чтобы сохранить статус успеха или нет. Это также простой способ получить всю дополнительную информацию. Далее мы используем тот же принцип для сохранения и получения данных о студентах.
- Реализовать сохранение и получение данных учащихся
controllers/sdudent.js
import mongoose from 'mongoose'
const Student = mongoose.model('Student')
// 保存学生数据的方法
export const saveStudent = async (ctx, next) => {
// 获取前端请求的数据
const opts = ctx.request.body
const student = new Student(opts)
const saveStudent = await student.save() // 保存数据
if (saveStudent) {
ctx.body = {
success: true,
student: saveStudent
}
} else {
ctx.body = {
success: false
}
}
}
// 查询所有学生的数据
export const fetchStudent = async (ctx, next) => {
const students = await Student.find({})
if (students.length) {
ctx.body = {
success: true,
student: students
}
} else {
ctx.body = {
success: false
}
}
}
// 查询学生的数据以及附加数据
export const fetchStudentDetail = async (ctx, next) => {
// 利用populate来查询关联info的数据
const students = await Student.find({}).populate({
path: 'info',
select: 'hobby height weight'
}).exec()
if (students.length) {
ctx.body = {
success: true,
student: students
}
} else {
ctx.body = {
success: false
}
}
}
Реализовать маршрутизацию и предоставить интерфейсы API для внешнего интерфейса.
Мы уже завершили модель данных и контроллер выше, и мы будем использовать следующееkoa-router
Промежуточное ПО маршрутизации для реализации запрошенного интерфейса. мы возвращаемсяserver.js
, добавьте код выше. следующим образом
server.js
import Koa from 'koa'
import KoaStatic from 'koa-static'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'
import {database} from './mongodb' // 引入mongodb
import {saveInfo, fetchInfo} from './controllers/info' // 引入info controller
import {saveStudent, fetchStudent, fetchStudentDetail} from './controllers/student' // 引入 student controller
database() // 链接数据库并且初始化数据模型
const app = new Koa()
const router = new Router();
app.use(bodyParser());
app.use(KoaStatic(__dirname + '/public'));
router.get('/test', (ctx, next) => {
ctx.body="test page"
});
// 设置每一个路由对应的相对的控制器
router.post('/saveinfo', saveInfo)
router.get('/info', fetchInfo)
router.post('/savestudent', saveStudent)
router.get('/student', fetchStudent)
router.get('/studentDetail', fetchStudentDetail)
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(4000);
console.log('graphQL server listen port: ' + 4000)
Приведенный выше код только что сделан, в нем представлены настройки mongodb, информация и контроллеры учеников, затем связывание базы данных и настройка контроллеров, которые мы определили для каждого параметра и каждого маршрута.
Установите модуль мангустаnpm install mongoose --save
а затем запустить в командной строкеnode start
, после того как наш сервер заработает, а затем добавим некоторые данные в info и student. вот черезpostman
Плагин Google Chrome для запроса, как показано ниже.
да~~~ Сохранено успешно, продолжайте сохранять еще несколько в соответствии с шагами, а затем запрашивайте в соответствии с интерфейсом. Как показано ниже
Итак, как показано на рисунке, все сохраненные нами данные были запрошены и возвращены во внешний интерфейс. Неплохо. Продолжайте сохранять данные учащихся ниже.
подсказка: при сохранении данных учащегося данные в информации связываются. Так напишите id.
В той же волне операций мы сохраняем еще несколько частей информации об ученике, а затем запрашиваем информацию об ученике, как показано на рисунке ниже.
Что ж, мы сохранили данные, и мы сделали много предзнаменований.
Рефакторинг маршрутизации и настройка интерфейса запросов GraphQL
Не забывайте, ниже мы создаемrouter文件夹
, эта папка является модулем, который управляет нашей маршрутизацией унифицированным образом и разделяет модули, которые маршрутизируют каждую службу приложения. существуетrouter文件夹
создать новыйindex.js
. и преобразовать егоserver.js
Все маршруты внутри копируются вrouter/index.js
.
Кстати, добавьте в этот файл маршрутизации,graphql-server-koaмодуль, который представляет собой модуль сервера graphql, интегрированный koa. graphql server — это поддерживаемый сообществом сервер graphql с открытым исходным кодом, который работает со всеми фреймворками http-сервера node.js: express, connect, hapi, koa и restify. Вы можете щелкнуть ссылку, чтобы просмотреть подробные точки знаний.
Присоединяйсяgraphql-server-koa
Код файла маршрутизации выглядит следующим образом:
router/index.js
import { graphqlKoa, graphiqlKoa } from 'graphql-server-koa'
import {saveInfo, fetchInfo} from '../controllers/info'
import {saveStudent, fetchStudent, fetchStudentDetail} from '../controllers/student'
const router = require('koa-router')()
router.post('/saveinfo', saveInfo)
.get('/info', fetchInfo)
.post('/savestudent', saveStudent)
.get('/student', fetchStudent)
.get('/studentDetail', fetchStudentDetail)
.get('/graphiql', async (ctx, next) => {
await graphiqlKoa({endpointURL: '/graphql'})(ctx, next)
})
module.exports = router
тогда поставьserver.js
Код после удаления кода маршрутизации выглядит следующим образом:
server.js
import Koa from 'koa'
import KoaStatic from 'koa-static'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'
import {database} from './mongodb'
database()
const GraphqlRouter = require('./router')
const app = new Koa()
const router = new Router();
const port = 4000
app.use(bodyParser());
app.use(KoaStatic(__dirname + '/public'));
router.use('', GraphqlRouter.routes())
app.use(router.routes())
.use(router.allowedMethods());
app.listen(port);
console.log('GraphQL-demo server listen port: ' + port)
Ну а после разделения, лаконично и ясно. Затем мы перезапускаем службу узла. Введите в адресной строке браузераhttp://localhost:4000/graphiql
, вы получите следующий интерфейс. Как показано на рисунке:
Правильно, ничто не является интерфейсом к службе запросов GraphQL. Давайте усовершенствуем этот сервис запросов GraphQL.
Написание схем GraphQL
Взгляните на нашу первую картинку, какие данные нам нужны, какие поля прописаны в интерфейсе запросов GraphQL, мы можем их запрашивать, а бэкэнд должен определить эти форматы данных. Это требует от нас определения схемы GraphQL.
Во-первых, мы создаем новый корневой каталогgraphql文件夹
, эта папка используется для хранения и управления js-файлами, связанными с graphql. затем вgraphql文件夹
создать новыйschema.js
.
Здесь мы используемgraphqlМодуль, этот модуль предназначен для реализации запроса graphql со ссылкой на javascript. Если вам нужно узнать подробно, пожалуйста, нажмите на ссылку трудно.
Давайте сначала напишемinfo
метод запроса. Потом остальные примерно такие же.
graphql/schema.js
// 引入GraphQL各种方法类型
import {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLList,
GraphQLNonNull,
isOutputType
} from 'graphql';
import mongoose from 'mongoose'
const Info = mongoose.model('Info') // 引入Info模块
// 定义日期时间 类型
const objType = new GraphQLObjectType({
name: 'mete',
fields: {
createdAt: {
type: GraphQLString
},
updatedAt: {
type: GraphQLString
}
}
})
// 定义Info的数据类型
let InfoType = new GraphQLObjectType({
name: 'Info',
fields: {
_id: {
type: GraphQLID
},
height: {
type: GraphQLString
},
weight: {
type: GraphQLString
},
hobby: {
type: new GraphQLList(GraphQLString)
},
meta: {
type: objType
}
}
})
// 批量查询
const infos = {
type: new GraphQLList(InfoType),
args: {},
resolve (root, params, options) {
return Info.find({}).exec() // 数据库查询
}
}
// 根据id查询单条info数据
const info = {
type: InfoType,
// 传进来的参数
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID) // 参数不为空
}
},
resolve (root, params, options) {
return Info.findOne({_id: params.id}).exec() // 查询单条数据
}
}
// 导出GraphQLSchema模块
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Queries',
fields: {
infos,
info
}
})
})
При просмотре кода рекомендуется смотреть снизу вверх ~~~~ В приведенном выше коде говорится, что устанавливается GraphQLSchema информации и информации, а затем определяется формат данных, запрашиваются данные или один фрагмент данных запрашивается в соответствии с параметрами, а затем возвращается.
После написания инфосхемы настраиваем маршрутизацию и входимrouter/index.js
Внутри добавьте следующие строки кода.
router/index.js
import { graphqlKoa, graphiqlKoa } from 'graphql-server-koa'
import {saveInfo, fetchInfo} from '../controllers/info'
import {saveStudent, fetchStudent, fetchStudentDetail} from '../controllers/student'
// 引入schema
import schema from '../graphql/schema'
const router = require('koa-router')()
router.post('/saveinfo', saveInfo)
.get('/info', fetchInfo)
.post('/savestudent', saveStudent)
.get('/student', fetchStudent)
.get('/studentDetail', fetchStudentDetail)
router.post('/graphql', async (ctx, next) => {
await graphqlKoa({schema: schema})(ctx, next) // 使用schema
})
.get('/graphql', async (ctx, next) => {
await graphqlKoa({schema: schema})(ctx, next) // 使用schema
})
.get('/graphiql', async (ctx, next) => {
await graphiqlKoa({endpointURL: '/graphql'})(ctx, next) // 重定向到graphiql路由
})
module.exports = router
Подробности смотрите в примечаниях, а то забыли установитьnpm install graphql-server-koa graphql --save
эти два модуля. После завершения установки перезапустите серверnode start
(Вы можете использовать nodemon для запуска службы локального узла без необходимости запуска туда и обратно.)
затем обновитеhttp://localhost:4000/graphiql
, вы обнаружите, что справа будет документ запроса, а слева напишите метод запроса, как показано ниже.
Реорганизуйте структуру кода Graphql, чтобы выполнить все запросы данных.
Теперь мы записали и схему, и тип в файл.Если данных слишком много, будет очень сложно поддерживать и просматривать, если слишком много полей, поэтому мы разделяем определение типа и схемы и делаем то, что говорим Делать.
существуетgraphql文件夹
новыйinfo.js
,studen.js
, файл, первая запись типа информации вinfo.js
код показывает, как показано ниже
graphql/info.js
import {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLList,
GraphQLNonNull,
isOutputType
} from 'graphql';
import mongoose from 'mongoose'
const Info = mongoose.model('Info')
const objType = new GraphQLObjectType({
name: 'mete',
fields: {
createdAt: {
type: GraphQLString
},
updatedAt: {
type: GraphQLString
}
}
})
export let InfoType = new GraphQLObjectType({
name: 'Info',
fields: {
_id: {
type: GraphQLID
},
height: {
type: GraphQLString
},
weight: {
type: GraphQLString
},
hobby: {
type: new GraphQLList(GraphQLString)
},
meta: {
type: objType
}
}
})
export const infos = {
type: new GraphQLList(InfoType),
args: {},
resolve (root, params, options) {
return Info.find({}).exec()
}
}
export const info = {
type: InfoType,
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
resolve (root, params, options) {
return Info.findOne({
_id: params.id
}).exec()
}
}
После выделения типа информации мы кстати доделаем тип studen.Код следующий, и принцип тот же, что и у типа информации.
graphql/student.js
import {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLList,
GraphQLNonNull,
isOutputType,
GraphQLInt
} from 'graphql';
import mongoose from 'mongoose'
import {InfoType} from './info'
const Student = mongoose.model('Student')
let StudentType = new GraphQLObjectType({
name: 'Student',
fields: {
_id: {
type: GraphQLID
},
name: {
type: GraphQLString
},
sex: {
type: GraphQLString
},
age: {
type: GraphQLInt
},
info: {
type: InfoType
}
}
})
export const student = {
type: new GraphQLList(StudentType),
args: {},
resolve (root, params, options) {
return Student.find({}).populate({
path: 'info',
select: 'hobby height weight'
}).exec()
}
}
Советы: приведенное выше цитируется из-за запроса на объединенную таблицу.
info.js
затем отрегулируйтеschema.js
Код выглядит следующим образом:
import {
GraphQLSchema,
GraphQLObjectType
} from 'graphql';
// 引入 type
import {info, infos} from './info'
import {student} from './student'
// 建立 schema
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Queries',
fields: {
infos,
info,
student
}
})
})
Приятно видеть, что код такой свежий и усовершенствованный. Что ж, запрос данных graophql, вероятно, относительно завершен. Вы можете сами написать данные курса, или сразу перейти ко мнегитхаб проектКоторый я не буду копировать, скажем, дублировать.
Давайте напишем, как запрашивается передний интерфейс, а затем пусть данные вернутся в браузер для отображения страницы.
Вызов внешнего интерфейса
существуетpublic文件夹
Создайте новый нижеindex.html
,js文件夹
,css文件夹
, затем вjs文件夹
Создатьindex.js
, существуетcss文件夹
Создатьindex.css
, код показывает, как показано ниже
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GraphQL-demo</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<h1 class="app-title">GraphQL-前端demo</h1>
<div id="app">
<div class="course list">
<h3>课程列表</h3>
<ul id="courseList">
<li>暂无数据....</li>
</ul>
</div>
<div class="student list">
<h3>班级学生列表</h3>
<ul id="studentList">
<li>暂无数据....</li>
</ul>
</div>
</div>
<div class="btnbox">
<div class="btn" id="btn1">点击常规获取课程列表</div>
<div class="btn" id="btn2">点击常规获取班级学生列表</div>
<div class="btn" id="btn3">点击graphQL一次获取所有数据,问你怕不怕?</div>
</div>
<div class="toast"></div>
<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
Мы в основном смотрим на метод запроса js, код выглядит следующим образом
window.onload = function () {
$('#btn2').click(function() {
$.ajax({
url: '/student',
data: {},
success:function (res){
if (res.success) {
renderStudent (res.data)
}
}
})
})
$('#btn1').click(function() {
$.ajax({
url: '/course',
data: {},
success:function (res){
if (res.success) {
renderCourse(res.data)
}
}
})
})
function renderStudent (data) {
var str = ''
data.forEach(function(item) {
str += '<li>姓名:'+item.name+',性别:'+item.sex+',年龄:'+item.age+'</li>'
})
$('#studentList').html(str)
}
function renderCourse (data) {
var str = ''
data.forEach(function(item) {
str += '<li>课程:'+item.title+',简介:'+item.desc+'</li>'
})
$('#courseList').html(str)
}
// 请求看query参数就可以了,跟查询界面的参数差不多
$('#btn3').click(function() {
$.ajax({
url: '/graphql',
data: {
query: `query{
student{
_id
name
sex
age
}
course{
title
desc
}
}`
},
success:function (res){
renderStudent (res.data.student)
renderCourse (res.data.course)
}
})
})
}
Я не буду публиковать код css. Вы можете перейти на проект и получить его напрямую.
После того, как все было завершено, перезапустите службу узла, а затем получите доступ,http://localhost:4000/
Вы увидите следующий интерфейс. Интерфейс уродлив, нет дизайна для украшения ячеек, пожалуйста, слегка распылите ~~~~
После того, как операция будет нажата, она будет такой же, как вторая картинка.
Все эффекты отключены, и на этом статья заканчивается.
Прикрепите адрес проекта:GitHub.com/naihe138/gr…
p.s. Если понравилось, подкиньте мне звездочку