成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

GraphQL 搭配 Koa 最佳入門(mén)實(shí)踐

MoAir / 3486人閱讀

摘要:如下圖嗯,如圖都已經(jīng)查詢(xún)到我們保存的全部數(shù)據(jù),并且全部返回前端了。如圖沒(méi)錯(cuò),什么都沒(méi)有就是查詢(xún)服務(wù)的界面。寫(xiě)好了之后我們?cè)谂渲靡幌侣酚桑M(jìn)入里面,加入下面幾行代碼。

GraphQL一種用為你 API 而生的查詢(xún)語(yǔ)言,2018已經(jīng)到來(lái),PWA還沒(méi)有大量投入生產(chǎn)應(yīng)用之中就已經(jīng)火起來(lái)了,GraphQL的應(yīng)用或許也不會(huì)太遠(yuǎn)了。前端的發(fā)展的最大一個(gè)特點(diǎn)就是變化快,有時(shí)候應(yīng)對(duì)各種需求場(chǎng)景的變化,不得不去對(duì)接口開(kāi)發(fā)很多版本或者修改。各種業(yè)務(wù)依賴(lài)強(qiáng)大的基礎(chǔ)數(shù)據(jù)平臺(tái)快速生長(zhǎng),如何高效地為各種業(yè)務(wù)提供數(shù)據(jù)支持,是所有人關(guān)心的問(wèn)題。而且現(xiàn)在前端的解決方案是將視圖組件化,各個(gè)業(yè)務(wù)線(xiàn)既可以是組件的使用者,也可以是組件的生產(chǎn)者,如果能夠?qū)⑵渲型ㄓ玫膬?nèi)容抽取出來(lái)提供給各個(gè)業(yè)務(wù)方反復(fù)使用,必然能夠節(jié)省寶貴的開(kāi)發(fā)時(shí)間和開(kāi)發(fā)人力。那么問(wèn)題來(lái)了,前端通過(guò)組件實(shí)現(xiàn)了跨業(yè)務(wù)的復(fù)用,后端接口如何相應(yīng)地提高開(kāi)發(fā)效率呢?GraphQL,就是應(yīng)對(duì)復(fù)雜場(chǎng)景的一種新思路。

官方解釋?zhuān)?/p>

GraphQL 既是一種用于 API 的查詢(xún)語(yǔ)言也是一個(gè)滿(mǎn)足你數(shù)據(jù)查詢(xún)的運(yùn)行時(shí)。 GraphQL 對(duì)你的 API 中的數(shù)據(jù)提供了一套易于理解的完整描述,使得客戶(hù)端能夠準(zhǔn)確地獲得它需要的數(shù)據(jù),而且沒(méi)有任何冗余,也讓 API 更容易地隨著時(shí)間推移而演進(jìn),還能用于構(gòu)建強(qiáng)大的開(kāi)發(fā)者工具。

下面介紹一下GraphQL的有哪些好處:

請(qǐng)求你所要的數(shù)據(jù)不多不少

獲取多個(gè)資源只用一個(gè)請(qǐng)求

自定義接口數(shù)據(jù)的字段

強(qiáng)大的開(kāi)發(fā)者工具

API 演進(jìn)無(wú)需劃分版本

本篇文章中將搭配koa實(shí)現(xiàn)一個(gè)GraphQL查詢(xún)的例子,逐步從簡(jiǎn)單kao服務(wù)到mongodb的數(shù)據(jù)插入查詢(xún)?cè)俚紾raphQL的使用,
讓大家快速看到:

搭建koa搭建一個(gè)后臺(tái)項(xiàng)目

后臺(tái)路由簡(jiǎn)單處理方式

利用mongoose簡(jiǎn)單操作mongodb

掌握GraphQL的入門(mén)姿勢(shì)

項(xiàng)目如下圖所示

1、搭建GraphQL工具查詢(xún)界面。

2、前端用jq發(fā)送ajax的使用方式

入門(mén)項(xiàng)目我們都已經(jīng)是預(yù)覽過(guò)了,下面我們動(dòng)手開(kāi)發(fā)吧?。?!

lets do it

首先建立一個(gè)項(xiàng)目文件夾,然后在這個(gè)項(xiàng)目文件夾新建一個(gè)server.js(node服務(wù))、config文件夾mongodb文件夾router文件夾、controllers文件夾以及public文件夾(這個(gè)主要放前端靜態(tài)數(shù)據(jù)展示頁(yè)面),好啦,項(xiàng)目的結(jié)構(gòu)我們都已經(jīng)建立好,下面在server.js文件夾里寫(xiě)上

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"));

// 路由設(shè)置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

安裝好上面幾個(gè)模塊,

然后運(yùn)行node server.js,不出什么意外的話(huà),你會(huì)發(fā)現(xiàn)報(bào)如下圖的一個(gè)error

原因是現(xiàn)在的node版本并沒(méi)有支持es6的模塊引入方式。

放心 我們用神器babel-polyfill轉(zhuǎn)譯一下就闊以了。詳細(xì)的請(qǐng)看阮一峰老師的這篇文章

下面在項(xiàng)目文件夾新建一個(gè)start.js,然后在里面寫(xiě)上以下代碼:

start.js
require("babel-core/register")({
  "presets": [
    "stage-3",
    ["latest-node", { "target": "current" }]
  ]
})

require("babel-polyfill")
require("./server")

然后 在命令行,運(yùn)行npm install babel-core babel-polyfill babel-preset-latest-node babel-preset-stage-3 --save-dev安裝幾個(gè)開(kāi)發(fā)模塊。

安裝完畢之后,在命令行運(yùn)行 node start.js,之后你的node服務(wù)安靜的運(yùn)行起來(lái)了。用koa-router中間件做我們項(xiàng)目路由模塊的管理,后面會(huì)寫(xiě)到router文件夾中統(tǒng)一管理。

打開(kāi)瀏覽器,輸入localhost:4000/test,你就會(huì)發(fā)現(xiàn)訪(fǎng)問(wèn)這個(gè)路由node服務(wù)會(huì)返回test page文字。如下圖

yeah~~kao服務(wù)器基本搭建好之后,下面就是,鏈接mongodb然后把數(shù)據(jù)存儲(chǔ)到mongodb數(shù)據(jù)庫(kù)里面啦。

實(shí)現(xiàn)mongodb的基本數(shù)據(jù)模型

tip:這里我們需要mongodb存儲(chǔ)數(shù)據(jù)以及利用mongoose模塊操作mongodb數(shù)據(jù)庫(kù)

mongodb文件夾新建一個(gè)index.jsschema文件夾, 在 schema文件夾文件夾下面新建info.jsstudent.js。

config文件夾下面建立一個(gè)index.js,這個(gè)文件主要是放一下配置代碼。

又一波文件建立好之后,先在config/index.js下寫(xiě)上鏈接數(shù)據(jù)庫(kù)配置的代碼。

config/index.js
export default {
  dbPath: "mongodb://localhost/graphql"
}

然后在mongodb/index.js下寫(xiě)上鏈接數(shù)據(jù)庫(kù)的代碼。

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.jsstuden.js這兩個(gè)分別是學(xué)生的附加信息和基本信息的數(shù)據(jù)模型,為什么會(huì)分成兩個(gè)信息表?原因是順便給大家介紹一下聯(lián)表查詢(xún)的基本方法(嘿嘿~~~)

下面我們分別完成這兩個(gè)數(shù)據(jù)模型

mongodb/schema/info.js
// 引入mongoose
import mongoose from "mongoose"

// 
const Schema = mongoose.Schema

// 實(shí)例InfoSchema
const InfoSchema = new Schema({
  hobby: [String],
  height: String,
  weight: Number,
  meta: {
    createdAt: {
      type: Date,
      default: Date.now()
    },
    updatedAt: {
      type: Date,
      default: Date.now()
    }
  }
})
// 在保存數(shù)據(jù)之前跟新日期
InfoSchema.pre("save", function (next) {
  if (this.isNew) {
    this.meta.createdAt = this.meta.updatedAt = Date.now()
  } else {
    this.meta.updatedAt = Date.now()
  }

  next()
})
// 建立Info數(shù)據(jù)模型
mongoose.model("Info", InfoSchema)

上面的代碼就是利用mongoose實(shí)現(xiàn)了學(xué)生的附加信息的數(shù)據(jù)模型,用同樣的方法我們實(shí)現(xiàn)了student數(shù)據(jù)模型

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)
實(shí)現(xiàn)保存數(shù)據(jù)的控制器

數(shù)據(jù)模型都鏈接好之后,我們就添加一些存儲(chǔ)數(shù)據(jù)的方法,這些方法都寫(xiě)在控制器里面。然后在controler里面新建info.jsstudent.js,這兩個(gè)文件分別對(duì)象,操作info和student數(shù)據(jù)的控制器,分開(kāi)寫(xiě)為了方便模塊化管理。

實(shí)現(xiàn)info數(shù)據(jù)信息的保存,順便把查詢(xún)也先寫(xiě)上去,代碼很簡(jiǎn)單

controlers/info.js
import mongoose from "mongoose"
const Info = mongoose.model("Info")

// 保存info信息
export const saveInfo = async (ctx, next) => {
  // 獲取請(qǐng)求的數(shù)據(jù)
  const opts = ctx.request.body
  
  const info = new Info(opts)
  const saveInfo = await info.save() // 保存數(shù)據(jù)
  console.log(saveInfo)
  // 簡(jiǎn)單判斷一下 是否保存成功,然后返回給前端
  if (saveInfo) {
    ctx.body = {
      success: true,
      info: saveInfo
    }
  } else {
    ctx.body = {
      success: false
    }
  }
}

// 獲取所有的info數(shù)據(jù)
export const fetchInfo = async (ctx, next) => {
  const infos = await Info.find({}) // 數(shù)據(jù)查詢(xún)

  if (infos.length) {
    ctx.body = {
      success: true,
      info: infos
    }
  } else {
    ctx.body = {
      success: false
    }
  }
}

上面的代碼,就是前端用post(路由下面一會(huì)在寫(xiě))請(qǐng)求過(guò)來(lái)的數(shù)據(jù),然后保存到mongodb數(shù)據(jù)庫(kù),在返回給前端保存成功與否的狀態(tài)。也簡(jiǎn)單實(shí)現(xiàn)了一下,獲取全部附加信息的的一個(gè)方法。下面我們用同樣的道理實(shí)現(xiàn)studen數(shù)據(jù)的保存以及獲取。

實(shí)現(xiàn)studen數(shù)據(jù)的保存以及獲取

controllers/sdudent.js
import mongoose from "mongoose"
const Student = mongoose.model("Student")

// 保存學(xué)生數(shù)據(jù)的方法
export const saveStudent = async (ctx, next) => {
  // 獲取前端請(qǐng)求的數(shù)據(jù)
  const opts = ctx.request.body
  
  const student = new Student(opts)
  const saveStudent = await student.save() // 保存數(shù)據(jù)

  if (saveStudent) {
    ctx.body = {
      success: true,
      student: saveStudent
    }
  } else {
    ctx.body = {
      success: false
    }
  }
}

// 查詢(xún)所有學(xué)生的數(shù)據(jù)
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
    }
  }
}

// 查詢(xún)學(xué)生的數(shù)據(jù)以及附加數(shù)據(jù)
export const fetchStudentDetail = async (ctx, next) => {

  // 利用populate來(lái)查詢(xún)關(guān)聯(lián)info的數(shù)據(jù)
  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
    }
  }
}
實(shí)現(xiàn)路由,給前端提供API接口

數(shù)據(jù)模型和控制器在上面我們都已經(jīng)是完成了,下面就利用koa-router路由中間件,來(lái)實(shí)現(xiàn)請(qǐng)求的接口。我們回到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() // 鏈接數(shù)據(jù)庫(kù)并且初始化數(shù)據(jù)模型

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"
});

// 設(shè)置每一個(gè)路由對(duì)應(yīng)的相對(duì)的控制器
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設(shè)置,info以及student控制器,然后鏈接數(shù)據(jù)庫(kù),并且設(shè)置每一個(gè)設(shè)置每一個(gè)路由對(duì)應(yīng)的我們定義的的控制器。

安裝一下mongoose模塊 npm install mongoose --save

然后在命令行運(yùn)行node start,我們服務(wù)器運(yùn)行之后,然后在給info和student添加一些數(shù)據(jù)。這里是通過(guò)postman的谷歌瀏覽器插件來(lái)請(qǐng)求的,如下圖所示

yeah~~~保存成功,繼續(xù)按照步驟多保存幾條,然后按照接口查詢(xún)一下。如下圖

嗯,如圖都已經(jīng)查詢(xún)到我們保存的全部數(shù)據(jù),并且全部返回前端了。不錯(cuò)不錯(cuò)。下面繼續(xù)保存學(xué)生數(shù)據(jù)。

tip: 學(xué)生數(shù)據(jù)保存的時(shí)候關(guān)聯(lián)了信息里面的數(shù)據(jù)哦。所以把id寫(xiě)上去了。

同樣的一波操作,我們多保存學(xué)生幾條信息,然后查詢(xún)學(xué)生信息,如下圖所示。

好了 ,數(shù)據(jù)我們都已經(jīng)保存好了,鋪墊也做了一大把了,下面讓我們真正的進(jìn)入,GrapgQL查詢(xún)的騷操作吧~~~~

重構(gòu)路由,配置GraphQL查詢(xún)界面

別忘了,下面我們建立了一個(gè)router文件夾,這個(gè)文件夾就是統(tǒng)一管理我們路由的模塊,分離了路由個(gè)應(yīng)用服務(wù)的模塊。在router文件夾新建一個(gè)index.js。并且改造一下server.js里面的路由全部復(fù)制到router/index.js。

順便在這個(gè)路由文件中加入,graphql-server-koa模塊,這是koa集成的graphql服務(wù)器模塊。graphql server是一個(gè)社區(qū)維護(hù)的開(kāi)源graphql服務(wù)器,可以與所有的node.js http服務(wù)器框架一起工作:express,connect,hapi,koa和restify。可以點(diǎn)擊鏈接查看詳細(xì)知識(shí)點(diǎn)。

加入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)

恩,分離之后簡(jiǎn)潔,明了了很多。然后我們?cè)谥匦聠?dòng)node服務(wù)。在瀏覽器地址欄輸入http://localhost:4000/graphiql,就會(huì)得到下面這個(gè)界面。如圖:

沒(méi)錯(cuò),什么都沒(méi)有 就是GraphQL查詢(xún)服務(wù)的界面。下面我們把這個(gè)GraphQL查詢(xún)服務(wù)完善起來(lái)。

編寫(xiě)GraphQL Schema

看一下我們第一張圖,我們需要什么數(shù)據(jù),在GraphQL查詢(xún)界面就編寫(xiě)什么字段,就可以查詢(xún)到了,而后端需要定義好這些數(shù)據(jù)格式。這就需要我們定義好GraphQL Schema。

首先我們?cè)诟夸浶陆ㄒ粋€(gè)graphql文件夾,這個(gè)文件夾用于存放管理graphql相關(guān)的js文件。然后在graphql文件夾新建一個(gè)schema.js

這里我們用到graphql模塊,這個(gè)模塊就是用javascript參考實(shí)現(xiàn)graphql查詢(xún)。向需要詳細(xì)學(xué)習(xí),請(qǐng)使勁戳鏈接。

我們先寫(xiě)好info的查詢(xún)方法。然后其他都差不多滴。

graphql/schema.js
// 引入GraphQL各種方法類(lèi)型

import {
  graphql,
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLID,
  GraphQLList,
  GraphQLNonNull,
  isOutputType
} from "graphql";

import mongoose from "mongoose"
const Info = mongoose.model("Info") // 引入Info模塊

// 定義日期時(shí)間 類(lèi)型
const objType = new GraphQLObjectType({
  name: "mete",
  fields: {
    createdAt: {
      type: GraphQLString
    },
    updatedAt: {
      type: GraphQLString
    }
  }
})

// 定義Info的數(shù)據(jù)類(lèi)型
let InfoType = new GraphQLObjectType({
  name: "Info",
  fields: {
    _id: {
      type: GraphQLID
    },
    height: {
      type: GraphQLString
    },
    weight: {
      type: GraphQLString
    },
    hobby: {
      type: new GraphQLList(GraphQLString)
    },
    meta: {
      type: objType
    }
  }
})

// 批量查詢(xún)
const infos = {
  type: new GraphQLList(InfoType),
  args: {},
  resolve (root, params, options) {
    return Info.find({}).exec() // 數(shù)據(jù)庫(kù)查詢(xún)
  }
}

// 根據(jù)id查詢(xún)單條info數(shù)據(jù)

const info = {
  type: InfoType,
  // 傳進(jìn)來(lái)的參數(shù)
  args: {
    id: {
      name: "id",
      type: new GraphQLNonNull(GraphQLID) // 參數(shù)不為空
    }
  },
  resolve (root, params, options) {
    return Info.findOne({_id: params.id}).exec() // 查詢(xún)單條數(shù)據(jù)
  }
}

// 導(dǎo)出GraphQLSchema模塊

export default new GraphQLSchema({
  query: new GraphQLObjectType({
    name: "Queries",
    fields: {
      infos,
      info
    }
  })
})

看代碼的時(shí)候建議從下往上看~~~~,上面代碼所說(shuō)的就是,建立info和infos的GraphQLSchema,然后定義好數(shù)據(jù)格式,查詢(xún)到數(shù)據(jù),或者根據(jù)參數(shù)查詢(xún)到單條數(shù)據(jù),然后返回出去。

寫(xiě)好了info schema之后 我們?cè)谂渲靡幌侣酚桑M(jìn)入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

詳細(xì)請(qǐng)看注釋?zhuān)缓蟊煌洶惭b好npm install graphql-server-koa graphql --save這兩個(gè)模塊。安裝完畢之后,重新運(yùn)行服務(wù)器的node start(你可以使用nodemon來(lái)啟動(dòng)本地node服務(wù),免得來(lái)回啟動(dòng)。)

然后刷新http://localhost:4000/graphiql,你會(huì)發(fā)現(xiàn)右邊會(huì)有查詢(xún)文檔,在左邊寫(xiě)上查詢(xún)方式,如下圖

重整Graphql代碼結(jié)構(gòu),完成所有數(shù)據(jù)查詢(xún)

現(xiàn)在是我們把schema和type都寫(xiě)到一個(gè)文件上面了去了,如果數(shù)據(jù)多了,字段多了變得特別不好維護(hù)以及review,所以我們就把定義type的和schema分離開(kāi)來(lái),說(shuō)做就做。

graphql文件夾新建info.js,studen.js,文件,先把info type 寫(xiě)到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()
  }
}

分離好info type 之后,一鼓作氣,我們順便把studen type 也完成一下,代碼如下,原理跟info type 都是相通的,

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()
  }
}

tips: 上面因?yàn)橛辛寺?lián)表查詢(xún),所以引用了info.js

然后調(diào)整一下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數(shù)據(jù)查詢(xún)都已經(jīng)是大概比較完善了。
課程的數(shù)據(jù)大家可以自己寫(xiě)一下,或者直接到我的github項(xiàng)目里面copy過(guò)來(lái)我就不一一重復(fù)的說(shuō)了。

下面寫(xiě)一下前端接口是怎么查詢(xún)的,然后讓數(shù)據(jù)返回瀏覽器展示到頁(yè)面的。

前端接口調(diào)用

public文件夾下面新建一個(gè)index.html,js文件夾,css文件夾,然后在js文件夾建立一個(gè)index.js, 在css文件夾建立一個(gè)index.css,代碼如下

public/index.html



  
  
  GraphQL-demo
  


  

GraphQL-前端demo

課程列表

  • 暫無(wú)數(shù)據(jù)....

班級(jí)學(xué)生列表

  • 暫無(wú)數(shù)據(jù)....
點(diǎn)擊常規(guī)獲取課程列表
點(diǎn)擊常規(guī)獲取班級(jí)學(xué)生列表
點(diǎn)擊graphQL一次獲取所有數(shù)據(jù),問(wèn)你怕不怕?

我們主要看js請(qǐng)求方式 代碼如下

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 += "
  • 姓名:"+item.name+",性別:"+item.sex+",年齡:"+item.age+"
  • " }) $("#studentList").html(str) } function renderCourse (data) { var str = "" data.forEach(function(item) { str += "
  • 課程:"+item.title+",簡(jiǎn)介:"+item.desc+"
  • " }) $("#courseList").html(str) } // 請(qǐng)求看query參數(shù)就可以了,跟查詢(xún)界面的參數(shù)差不多 $("#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的代碼 我就不貼出來(lái)啦。大家可以去項(xiàng)目直接拿嘛。

    所有東西都已經(jīng)完成之后,重新啟動(dòng)node服務(wù),然后訪(fǎng)問(wèn),http://localhost:4000/就會(huì)看到如下界面。界面丑,沒(méi)什么設(shè)計(jì)美化細(xì)胞,求輕噴~~~~

    操作點(diǎn)擊之后就會(huì)想第二張圖一樣了。

    所有效果都出來(lái)了,本篇文章也就到此結(jié)束了。

    附上項(xiàng)目地址: https://github.com/naihe138/GraphQL-demo

    ps:喜歡的話(huà)丟一個(gè)小星星(star)給我嘛

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90692.html

    相關(guān)文章

    • 編寫(xiě) Node.js Rest API 的 10 個(gè)最佳實(shí)踐

      摘要:要對(duì)進(jìn)行黑盒測(cè)試測(cè)試的最好辦法是對(duì)他們進(jìn)行黑盒測(cè)試,黑盒測(cè)試是一種不關(guān)心應(yīng)用內(nèi)部結(jié)構(gòu)和工作原理的測(cè)試方法,測(cè)試時(shí)系統(tǒng)任何部分都不應(yīng)該被。此外,有了黑盒測(cè)試并不意味著不需要單元測(cè)試,針對(duì)的單元測(cè)試還是需要編寫(xiě)的。 本文首發(fā)于之乎專(zhuān)欄前端周刊,全文共 6953 字,讀完需 8 分鐘,速度需 2 分鐘。翻譯自:RingStack 的文章 https://blog.risingstack.co...

      ermaoL 評(píng)論0 收藏0
    • 關(guān)于Vue2一些值得推薦的文章 -- 五、六月份

      摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

      sutaking 評(píng)論0 收藏0
    • 關(guān)于Vue2一些值得推薦的文章 -- 五、六月份

      摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

      khs1994 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <