学习本姿式须要电脑装有node,vue-cli相关环境,以及要有node,express,koa,vue相关基础 css
本文相关demo的github地址: html
node服务:https://github.com/liuming888/graphql_node_demo.git
vue项目:https://github.com/liuming888/graphql_vue_demo.git
简单地讲,对于前端,它就是让你舒舒服服发请求的 前端
严格的说,它是一种api设计思想,用来取代restful api的一种前端处于主导地位的api规范。它把前端所须要的api用相似图数据结构(graph)的方式展示出来,让前端很方便的获取所须要的数据。 vue
须要什么就获取什么数据 node
支持关系数据的查询 react
API无需定义各类路由,彻底数据驱动 git
无需管理API版本,一个版本持续演进 github
支持大部分主流开发语言和平台 web
强大的配套开发工具 sql
若是采用restful api的话,后端要持续维护api doc,可是实际场景是这样的:
1.来了新需求,后端先评估和开发,后端弄得差很少,前端才开始,而后中间后端一顿猛改
2.因为多种缘由,后端常常本身偷偷改掉传参或者返回值,完了接口报错,测试姐姐把前端叫过去一顿批,前端一脸懵圈,仔细检查,发现问题,找后端撕X,这样一个循环很是影响开发效率。
因为上面这一堆的问题,facebook公司2012年内部实践了GraphQL,15年刚开源的时候引发了不少大公司和社区关注,落地了不少规范和框架。须要了解详细历史能够看看底下的youtube视频。
这种叫GraphQL的东西帮助人们通过一系列定义和规范,能够发送gql请求很是方便的拿到想要的数据,甚至还能够修改数据,而不用后台的配合,并且一旦Schema肯定(数据库那边定义好),先后端就能够快速并行开发,例以下图得到某个用户的信息,我想要这个用户的什么属性就写什么,graphiQl工具能够进行完整的详细的提示,请求主体简单明了
query{
student{
id
name
age
}
course{
id
title
}
}
数据库建好模型,先后端能够同步开始开发需求,前端只有少数须要依赖后端接口,前端开发过程当中能够方便的拿到任何想要的数据,从而节省大量联调接口的时间,迅速的完成一个项目。
gql的实现挺复杂的,代码有点难懂,不过原理提及来比较简单易懂
var { graphql, buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
hello: String
}
`);
// The root provides a resolver functionfor each API endpoint
var root = {
hello: () => {
return'Hello world!';
},
};
// Run the GraphQL query '{ hello }' and print out the response
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
如上就是一个最简单的node版的gql服务器 gql把定义好的schema拿到,用root之类的resolve解析器去解析发送来的'{ hello }'请求,而后返回给相应的json值。上面代码打印出的response以下
{
data:
{
hello: 'Hello world!'
}
}
固然,resolve逐层解析会有一些问题,若是resolve请求数据库,就要用到DataLoader
DataLoader是gql服务器性能的关键一环,也是gql社区的主要推进完善方向,就像react里面的shouldComponentUpdate同样制约着gql服务器的性能。
DataLoader 能让咱们从数据库读取数据并让数据能被 GraphQL 处理,咱们使用 DataLoader,而不是直接经过 SQL 查询从数据库获取数据,将 DataLoader 做为代理以减小咱们实际须要发送给数据库的 SQL 查询。 DataLoader 使用批处理和缓存的组合来实现。若是同一个客户端请求会形成屡次请求数据库,DataLoader 会整合这些问题并从数据库批量拉取请求数据。DataLoader 会同时缓存这些数据,当有后续请求须要一样资源时能够直接从缓存获取到。
经过服务端对请求的元数据的type进行严格的定义,咱们只要在客户端发送gql请求就能返回指望的相应类型的数据
下图是请求格式,query【请求】,mutation【修改】和subscribe【订阅】是三种api发送方式,query用的多一些,mutation相对传统的restful来讲不够可靠和安全,subscribe相似websocket
query
{
schema {
types {
id
name // 获取根字段名
fields {
id
name // 获取字段名
}
}
}
}
优势就是后端能够少招几个写接口的
先后端一块儿开发,节约工期
较少维护api文档,节省精力
说了这些,其实单对于前端来讲,帮助不算特别大
后端或者中间层把gql封装相应业务对接数据库是难点,须要高端人力
须要前端多少学一点类sql语句,不过大部分场景能够封装好固定的sql语句
封装gql很差会产生sql性能问题,三级嵌套联查还有n+1的老问题又会冒出来,须要持续优化
前端排除bug须要必定的后端知识,先后端架构多少了解一些
..
npm install graphql
而后使用 node hello.js 以运行 hello.js 中的代码:
var { graphql, buildSchema } = require('graphql');
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = { hello: () => 'Hello world!' };
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
控制台打印出Hello world!
npm install express express-graphql graphql
而后使用 node server.js 以运行 server.js 中的代码:
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = { hello: () => 'Hello world!' };
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true, // 是否开启调试模式(生产环境注意得关掉)
}));
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'));
访问http://localhost:4000/graphql
npm install koa graphql koa-graphql koa-mount
而后使用 node server.js 以运行 server.js 中的代码:
const Koa = require('koa');
const mount = require('koa-mount');
const { buildSchema } = require('graphql');
const graphqlHTTP = require('koa-graphql');
const app = new Koa();
const schema = buildSchema(`
type Query {
hello: String
}
`);
const root = {
hello: () => 'Hello world!',
};
app.use(
mount(
'/graphql',
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
)
);
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
访问 http://localhost:3000/graphql
参考资料:用Node建立GraphQL API:代码量少,性能高
代码看 node-graphql-demo项目 而后yarn npm run dev
github地址: https://github.com/liuming888/graphql_node_demo.git master分支
咱们如今来建立咱们的 project。打开一个新的 terminal,执行如下命令,便可使用缺省值建立 package.json 文件:
mkdir node-graphql-demo
cd node-graphql-demo
npm init -y
接下来,咱们须要安装如下依赖:
npm install graphql express express-graphql sqlite3 --save
这样就会安装 Express 框架,Node.js 上的 GraphQL 实现,Express 和 SQLite3 的 GraphQL 中间件。为简单起见,咱们使用 SQLite3 做为数据库。
graphql 是一个支持库,而且在咱们这里是一个必要的模块
express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你建立各类 Web 应用,和丰富的 HTTP 工具。
express-graphql GraphQL HTTP服务器中间件
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其余数据库同样,您不须要在系统中配置。就像其余数据库,SQLite 引擎不是一个独立的进程,能够按应用程序需求进行静态或动态链接。SQLite 直接访问其存储文件
建立工程并引入基本依赖包以后,如今来建立 API 服务器。在工程文件夹里,建立 index.js 文件,并引入下列内容:
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const graphql = require("graphql");
const ExpressGraphQL = require("express-graphql");
上面的代码的目的是:为Express导入Express,SQLite3,GraphQL和GraphQL中间件。
接下来,添加下列代码,在当前文件夹中建立一个 Express 应用程序和名为 my.db 的 SQLite 3 数据库:
const app = express();
const database = new sqlite3.Database("./my.db");
而后,添加 createContactTable() 方法,在数据库中建立 contacts 表并立刻调用函数:
const createContactTable = () => {
const query = `
CREATE TABLE IF NOT EXISTS contacts (
id integer PRIMARY KEY,
firstName text,
lastName text,
email text UNIQUE)`;
return database.run(query);
}
createContactTable();
咱们建立了一个 SQL 表来存储 contacts的基本信息。每一个 contact 的基本信息包括:惟一的标识、名、姓和 email。
接下来,添加下列代码来定义一个 GraphQL 类型:
const ContactType = new graphql.GraphQLObjectType({
name: "Contact",
fields: {
id: { type: graphql.GraphQLID },
firstName: { type: graphql.GraphQLString },
lastName: { type: graphql.GraphQLString },
email: { type: graphql.GraphQLString }
}
});
咱们使用基本的内置 GraphQL 类型,如 GraphQLID 和 GraphQLString 来建立咱们自定义类型,对应数据库中的 contact。
相关连接:
GraphQLID: https://graphql.github.io/graphql-spec/draft/#sec-ID
GraphQLString: https://graphql.github.io/graphql-spec/draft/#sec-String
接着,定义查询类型,以下所示:
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: {
contacts: {
type: graphql.GraphQLList(ContactType),
resolve: (root, args, context, info) => {
return new Promise((resolve, reject) => {
database.all("SELECT * FROM contacts;", function (err, rows) {
if (err) {
reject([]);
}
resolve(rows);
});
});
}
},
contact: {
type: ContactType,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
}
},
resolve: (root, {
id
}, context, info) => {
return new Promise((resolve, reject) => {
database.all("SELECT * FROM contacts WHERE id = (?);", [id], function (err, rows) {
if (err) {
reject(null);
}
resolve(rows[0]);
});
});
}
}
}
});
咱们的查询有两个字段: contacts,能够用来获取数据库中的全部 contacts,而 contact 则根据 id 获取一个 contact 信息。 contact 字段容许所需的 id 参数为 GraphQLID 类型。
每一个字段都有一个 type,用来讲明返回数据的类型,args 定义指望从客户端获得的参数, resolve 则定义了在获取数据逻辑中实际使用的方法。
对于前两个字段, resolve() 方法是实际逻辑发生的地方—— 咱们简单调用 database.all() 和 database.run() 方法来执行正确的 SQL 查询,以便从 SQLite 获取数据,返回一个 Promise 来处理获得的数据。
咱们能够从resolve()方法的第二个参数访问任何传递的参数。
接下来,咱们建立一个 mutation 类型,用于建立、更新和删除操做: https://graphql.github.io/graphql-spec/draft/#sec-Mutation
var mutationType = new graphql.GraphQLObjectType({
name: 'Mutation',
fields: {
createContact: {
type: ContactType,
args: {
firstName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
lastName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
email: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
}
},
resolve: (root, {
firstName,
lastName,
}) => {
return new Promise((resolve, reject) => {
database.run('INSERT INTO contacts (firstName, lastName, email) VALUES (?,?,?);', [firstName, lastName, email], (err) => {
if (err) {
reject(null);
}
database.get("SELECT last_insert_rowid() as id", (err, row) => {
resolve({
id: row["id"],
firstName: firstName,
lastName: lastName,
email: email
});
});
});
})
}
},
updateContact: {
type: graphql.GraphQLString,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
},
firstName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
lastName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
email: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
}
},
resolve: (root, {
id,
firstName,
lastName,
}) => {
return new Promise((resolve, reject) => {
database.run('UPDATE contacts SET firstName = (?), lastName = (?), email = (?) WHERE id = (?);', [firstName, lastName, email, id], (err) => {
if (err) {
reject(err);
}
resolve(`Contact #${id} updated`);
});
})
}
},
deleteContact: {
type: graphql.GraphQLString,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
}
},
resolve: (root, {
id
}) => {
return new Promise((resolve, reject) => {
database.run('DELETE from contacts WHERE id =(?);', [id], (err) => {
if (err) {
reject(err);
}
resolve(`Contact #${id} deleted`);
});
})
}
}
}
});
咱们的 mutation 类型有三个字段:
createContact 建立 contacts;
updateContact 更新 contacts;
deleteContact 删除 contacts.
全部的字段都接受符合 args 属性定义的参数,并由一个 resolve() 方法来获取传递过来的参数,执行相应的 SQL 操做,并返回一个 Promise。
而后,建立 GraphQL schema: https://graphql.github.io/graphql-spec/draft/#sec-Schema
const schema = new graphql.GraphQLSchema({
query: queryType,
mutation: mutationType
});
GraphQL schema 是 GraphQL 的核心概念,它定义了链接到服务器的客户端可用的功能。咱们传递已定义的 query 和 mutation 类型到 schema。
最后,挂载到 /graphql 端点,在 4000 端口运行 Express 服务器:
app.use("/graphql", ExpressGraphQL({ schema: schema, graphiql: true}));
app.listen(4000, () => {
console.log("GraphQL server running at http://localhost:4000.");
});
保存 index.js 文件,返回到你的 terminal。运行下列命令,启动服务器:
node index.js
构建客户端前,可使用 GraphQL 接口来测试你的 API。
访问网址 : http://localhost:4000/graphql ,并运行下列 mutation query:
mutation {
createContact(firstName: "Jon", lastName: "Snow", email: "jonsnow@thenightswatch.com") {
id,
firstName,
lastName,
}
}
使用下列 mutation,能够更新 id 为 1 的 contact:
mutation {
updateContact(id: 1, firstName: "Aegon", lastName: "Targaryen", email: "aegontargaryen@ironthrone.com")
}
也可使用下列 mutation 来删除 id 为 1 的 contact:
mutation {
deleteContact(id: 1)
}
最后,使用以下 query,能够获取数据库中全部 contacts 信息:
query {
contacts {
id
firstName
lastName
}
}
使用下面 query,能够获取一个 contact 的信息:
query {
contact(id: 1) {
id
firstName
lastName
}
}
这里,咱们获得的是 id 为 1 的 contact 信息。
代码看 koa-demo项目 而后yarn npm run dev
github地址: https://github.com/liuming888/graphql_node_demo.git koa分支
咱们如今来建立咱们的 project。打开一个新的 terminal,执行如下命令,便可使用缺省值建立 package.json 文件:
mkdir koa-demo
cd koa-demo
npm init -y
接下来,咱们须要安装如下依赖:
npm install graphql koa koa-graphql koa-mount sqlite3 --save
这样就会安装 koa库,Node.js 上的 GraphQL 实现,koa 和 SQLite3 的 GraphQL 中间件。为简单起见,咱们使用 SQLite3 做为数据库。
graphql 是一个支持库,而且在咱们这里是一个必要的模块
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 经过利用 async 函数,Koa 帮你丢弃回调函数,并有力地加强错误处理。 Koa 并无捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序
koa-graphql GraphQL HTTP服务器中间件
koa-mount 让多个Koa.js子应用合并成一个父应用,用请求的前缀区分子应用
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其余数据库同样,您不须要在系统中配置。就像其余数据库,SQLite 引擎不是一个独立的进程,能够按应用程序需求进行静态或动态链接。SQLite 直接访问其存储文件
建立工程并引入基本依赖包以后,如今来建立 API 服务器。在工程文件夹里,建立 index.js 文件,并引入下列内容:
const Koa = require('koa');
const mount = require('koa-mount');
const graphql = require('graphql');
const graphqlHTTP = require('koa-graphql');
const sqlite3 = require('sqlite3').verbose();
const app = new Koa();
const database = new sqlite3.Database('./my.db');
const createContactTable = () => {
const query = `
CREATE TABLE IF NOT EXISTS contacts (
id integer PRIMARY KEY,
firstName text,
lastName text,
email text UNIQUE)`;
return database.run(query);
};
// 建立了一个 SQL 表来存储 contacts的基本信息。每一个 contact 的基本信息包括:惟一的标识、名、姓和 email。
createContactTable();
// 定义一个 GraphQL 类型
// 使用基本的内置 GraphQL 类型,如 GraphQLID 和 GraphQLString 来建立咱们自定义类型,对应数据库中的 contact。
const ContactType = new graphql.GraphQLObjectType({
name: 'Contact',
fields: {
id: { type: graphql.GraphQLID },
firstName: { type: graphql.GraphQLString },
lastName: { type: graphql.GraphQLString },
email: { type: graphql.GraphQLString },
},
});
// 定义查询类型
// 查询有两个字段: contacts,能够用来获取数据库中的全部 contacts,而 contact 则根据 id 获取一个 contact 信息。 contact 字段容许所需的 id 参数为 GraphQLID 类型。
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: {
contacts: {
type: graphql.GraphQLList(ContactType),
resolve: (root, args, context, info) => {
return new Promise((resolve, reject) => {
database.all("SELECT * FROM contacts;", function (err, rows) {
if (err) {
reject([]);
}
resolve(rows);
});
});
}
},
contact: {
type: ContactType, // 说明返回数据的类型
args: { // 定义指望从客户端获得的参数
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
}
},
resolve: (root, { // 实际逻辑发生的地方
id // resolve()方法的第二个参数访问任何传递的参数
}, context, info) => {
// 简单调用 database.all() 和 database.run() 方法来执行正确的 SQL 查询,以便从 SQLite 获取数据,返回一个 Promise 来处理获得的数据。
return new Promise((resolve, reject) => {
database.all("SELECT * FROM contacts WHERE id = (?);", [id], function (err, rows) {
if (err) {
reject(null);
}
resolve(rows[0]);
});
});
}
}
}
});
// 建立一个 mutation 类型,用于建立、更新和删除操做
var mutationType = new graphql.GraphQLObjectType({
name: 'Mutation',
fields: { // 全部的字段都接受符合 args 属性定义的参数,并由一个 resolve() 方法来获取传递过来的参数,执行相应的 SQL 操做,并返回一个 Promise。
createContact: { // 建立 contacts
type: ContactType,
args: {
firstName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
lastName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
email: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
}
},
resolve: (root, {
firstName,
lastName,
}) => {
return new Promise((resolve, reject) => {
database.run('INSERT INTO contacts (firstName, lastName, email) VALUES (?,?,?);', [firstName, lastName, email], (err) => {
if (err) {
reject(null);
}
database.get("SELECT last_insert_rowid() as id", (err, row) => {
resolve({
id: row["id"],
firstName: firstName,
lastName: lastName,
email: email
});
});
});
})
}
},
updateContact: { // 更新 contacts
type: graphql.GraphQLString,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
},
firstName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
lastName: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
},
email: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
}
},
resolve: (root, {
id,
firstName,
lastName,
}) => {
return new Promise((resolve, reject) => {
database.run('UPDATE contacts SET firstName = (?), lastName = (?), email = (?) WHERE id = (?);', [firstName, lastName, email, id], (err) => {
if (err) {
reject(err);
}
resolve(`Contact #${id} updated`);
});
})
}
},
deleteContact: { // 删除 contacts
type: graphql.GraphQLString,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLID)
}
},
resolve: (root, {
id
}) => {
return new Promise((resolve, reject) => {
database.run('DELETE from contacts WHERE id =(?);', [id], (err) => {
if (err) {
reject(err);
}
resolve(`Contact #${id} deleted`);
});
})
}
}
}
});
// 建立 GraphQL schema
// GraphQL schema 是 GraphQL 的核心概念,它定义了链接到服务器的客户端可用的功能。咱们传递已定义的 query 和 mutation 类型到 schema。
const schema = new graphql.GraphQLSchema({
query: queryType,
mutation: mutationType
});
app.use(
mount(
'/graphql',
graphqlHTTP({
schema: schema,
graphiql: true, //是否开启本地调试模式
})
)
);
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000,() => {
console.log("GraphQL server running at http://localhost:3000");
});
保存 index.js 文件,返回到你的 terminal。运行下列命令,启动服务器:
node index.js
构建客户端前,可使用 GraphQL 接口来测试你的 API。
访问网址 : http://localhost:4000/graphql ,并运行下列 mutation query:
mutation {
createContact(firstName: "Jon", lastName: "Snow", email: "jonsnow@thenightswatch.com") {
id,
firstName,
lastName,
}
}
使用下列 mutation,能够更新 id 为 1 的 contact:
mutation {
updateContact(id: 1, firstName: "Aegon", lastName: "Targaryen", email: "aegontargaryen@ironthrone.com")
}
也可使用下列 mutation 来删除 id 为 1 的 contact:
mutation {
deleteContact(id: 1)
}
最后,使用以下 query,能够获取数据库中全部 contacts 信息:
query {
contacts {
id
firstName
lastName
}
}
使用下面 query,能够获取一个 contact 的信息:
query {
contact(id: 1) {
id
firstName
lastName
}
}
这里,咱们获得的是 id 为 1 的 contact 信息。
参考资料 使用Vue和GraphQL构建一个CRUD APP (改资料的修改有问题,本文已修复)
相关代码:
node服务: https://github.com/liuming888/graphql_node_demo.git
vue项目: https://github.com/liuming888/graphql_vue_demo.git
打开koa-demo项目的server.js
增长一下代码
const cors = require('@koa/cors');
...
app.use(cors());
而后yarn add @koa/cors 再npm run dev
由于咱们在两个不一样的本地端口之间发送请求,这两个端口被视为两个独立的域,所以咱们须要在服务器中启用跨源资源共享功能
使用 Vue CLI,让咱们继续建立一个 Vue 项目。回到终端机,执行下列命令:
vue create vue-graphql-demo
当提示对预置选项进行选择时,你能够简单地选择默认设置。
等待生成项目,运行如下命令启动开发服务器:
cd vue-graphql-demo
npm run serve
这样,你的应用就运行起来了,在 http://localhost:8080/ 地址下能够访问。
Apollo 是一组实用程序,能够帮助你在 APP 中使用 GraphQL。它以其客户端和服务器而闻名。Apollo 是由 Meteor Development Group开发和维护的:https://www.meteor.io/
打开一个新的终端,进入你的项目文件夹,运行如下命令来安装 Apollo 客户端到你的 Vue 项目中:
yarn add vue-apollo graphql apollo-boost
Apollo Boost 是一种无需任何手动配置就能够开始使用 Apollo 客户端的方式。它包括一些常见的默认值,好比推荐的 InMemoryCache 和 HttpLink,它们是以推荐的参数为你进行配置的。这种零配置的方式适合快速开发使用。
修改src/main.js 文件,代码以下:
import Vue from 'vue';
import ApolloClient from 'apollo-boost';
import VueApollo from 'vue-apollo';
import App from './App.vue';
import router from './router';
import store from './store';
import './registerServiceWorker';
// 建立 Apollo 客户端的一个实例,并传入 GraphQL 端点的 URL
const apolloClient = new ApolloClient({
uri: 'http://localhost:3000/graphql', // graphql服务的地址 (注意服务端开启cors)
});
Vue.use(VueApollo); // 使用 VueApollo 插件将 Apollo 集成到咱们的 Vue APP 中
// 建立了 Apollo Provider,它包含全部 Vue 组件均可以使用的 Apollo Client 实例。
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
});
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
apolloProvider, // 将 Apollo Provider 添加到 Vue 实例中
}).$mount('#app');
将 vue-apollo 添加到 APP 后,全部组件均可以经过 apollo 选项来使用 Apollo
修改App.vue代码以下:
<template>
<div id="app">
<table border='1'
width='100%'
style='border-collapse: collapse;'>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
<tr v-for='contact in contacts'
:key="contact.id">
<td>{{ contact.firstName }}</td>
<td>{{ contact.lastName }}</td>
<td>{{ contact.email }}</td>
<td>
<input type="button"
@click="selectContact(contact)"
value="Select">
<input type="button"
@click="deleteContact(contact.id)"
value="Delete">
</td>
</tr>
</table>
</br>
<form>
<label>First Name</label>
<input type="text"
name="firstName"
v-model="firstName">
</br>
<label>Last Name</label>
<input type="text"
name="lastName"
v-model="lastName">
</br>
<label>Email</label>
<input type="email"
name="email"
v-model="email">
</br>
<input v-if="!id"
type="button"
@click="createContact(firstName, lastName, email)"
value="Add">
<input v-if="id"
type="button"
@click="updateContact(id, firstName, lastName, email)"
value="Update">
<input type="button"
@click="clearForm()"
value="Clear">
</form>
</div>
</template>
<script>
import gql from "graphql-tag";
export default {
data() {
// 定义了四个组件变量,分别是 id、firstName、lastName 和 email。这些变量将被绑定到用于建立新联系人的 HTML Form 中
return {
id: null,
firstName: "",
lastName: "",
email: ""
};
},
apollo: {
// gql 是一个 JavaScript 模板文字标签,它将 GraphQL 查询字符串解析到标准的 GraphQL AST 中。能够在 Github 上的官方库中找到更多详细信息:
// https://github.com/apollographql/graphql-tag
// 在这个 apollo 对象中,咱们添加了一个 contacts 属性,它将保存 contacts 查询的结果。稍后,咱们将使用它在模板中显示联系人。
contacts: gql`
query {
contacts {
id
firstName
lastName
}
}
`
},
methods: {
// 添加 createContact()、updateContact() 和 deleteContact()
// 使用 this.$apollo.mutate() 方法向 GraphQL Server 发送 mutation 查询,并调用 location.reload() 方法来从新加载页面。
createContact(firstName, lastName, email) {
console.log(`Create contact: ${email}`);
this.$apollo.mutate({
mutation: gql`
mutation createContact(
$firstName: String!
$lastName: String!
$email: String!
) {
createContact(
firstName: $firstName
lastName: $lastName
email: $email
) {
id
firstName
lastName
}
}
`,
variables: {
firstName: firstName,
lastName: lastName,
email: email
}
});
location.reload();
},
updateContact(id, firstName, lastName, email) {
console.log(
"id, firstName, lastName, email: ",
id,
firstName,
lastName,
);
console.log(`Update contact: # ${id}`);
this.$apollo.mutate({
mutation: gql`
mutation updateContact(
$id: ID!
$firstName: String!
$lastName: String!
$email: String!
) {
updateContact(
id: $id
firstName: $firstName
lastName: $lastName
email: $email
)
}
`,
variables: {
id: id,
firstName: firstName,
lastName: lastName,
email: email
}
});
location.reload();
},
deleteContact(id) {
console.log(`Delete contact: # ${id}`);
this.$apollo.mutate({
mutation: gql`
mutation deleteContact($id: ID!) {
deleteContact(id: $id)
}
`,
variables: {
id: id
}
});
location.reload();
},
selectContact(contact) {
this.id = contact.id;
this.firstName = contact.firstName;
this.lastName = contact.lastName;
this.email = contact.email;
},
clearForm() {
this.id = null;
this.firstName = "";
this.lastName = "";
this.email = "";
}
}
};
</script>
<style lang="scss">
</style>
保存后,从新启动vue项目,会看到如下页面:
到此,恭喜你已经成功入门graphql了,有兴趣能够自行查询相关资料深刻研究
建立API的目的是使本身的软件具备能够被其余外部服务集成的能力。即便你的程序被单个前端程序所使用,也能够将此前端视为外部服务,为此,当经过API为二者之间提供通讯时,你可以在不一样的项目中工做。
若是你在一个大型团队中工做,能够将其拆分为建立前端和后端团队,从而容许他们使用相同的技术,并使他们的工做更轻松。
优势就是后端能够少招几个写接口的
先后端一块儿开发,节约工期
较少维护api文档,节省精力(代码便是文档)
说了这些,其实单对于前端来讲,帮助不算特别大
后端或者中间层把gql封装相应业务对接数据库是难点,须要高端人力
须要前端多少学一点类sql语句,不过大部分场景能够封装好固定的sql语句
封装gql很差会产生sql性能问题,三级嵌套联查还有n+1的老问题又会冒出来,须要持续优化
前端排除bug须要必定的后端知识,先后端架构多少了解一些
GraphQL是一种适合多种状况的方法。 REST是一种体系结构方法。现在,有大量的文章能够解释为何一个比另外一个好,或者为何你应该只使用REST而不是GraphQL。另外你能够经过多种方式在内部使用GraphQL,并将API的端点维护为基于REST的架构。
你应该作的是了解每种方法的好处,分析本身正在建立的解决方案,评估你的团队使用解决方案的温馨程度,并评估你是否可以指导你的团队快速掌握这些技术。
本文更偏重于实用指南,而不是GraphQL和REST的主观比较。若是你想查看这二者的详细比较,我建议你查看另外一篇文章,为何GraphQL是API的将来。