Vue + GraphQL初试

简介:
  • 基本用法
  • GraphQL概述
    • GraphQL基本语法特性
    • GraphQL类型系统
    • GraphQL类型系统内置基础类型
    • GraphQL类型系统内置修饰符
    • GraphQL工作原理
    • GraphQL执行过程
  • Vue工程接入GraphQL

基本用法(如何去用)

package.json



"dependencies": {
	"apollo-server-koa": "^1.3.6",
	"graphql": "^0.13.2",
	"graphql-import": "^0.6.0",
	"graphql-tools": "^3.0.2",
	"koa": "^2.5.1",
	"koa-bodyparser": "^4.2.1",
	"koa-router": "^7.4.0",
	"koa-websocket": "^5.0.1"
},
"devDependencies": {
	"babel-cli": "^6.26.0",
	"babel-preset-env": "^1.7.0"
}

server.js



import koa from 'koa'
import koaRouter from 'koa-router'
import koaBody from 'koa-bodyparser'
import websocketify from 'koa-websocket'
import { graphqlKoa, graphiqlKoa } from 'apollo-server-koa'
import { makeExecutableSchema } from 'graphql-tools'

const app = websocketify(new koa())
const router = new koaRouter()
const PORT = 3000

// fake data
const moments = [
  {
    user: {
      id: 1000,
      name: '锐雯',
      avatar: 'http://imgsrc.baidu.com/imgad/pic/item/42a98226cffc1e17d31927154090f603738de974.jpg'
    },
    main: {
      content: '这是一条朋友圈',
      pics: [
        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529219875063&di=bc0bcc78ae800c1c21c198f52697f515&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F4a36acaf2edda3ccd53548ea0be93901203f9223.jpg',
        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529219893624&di=8d9e418df27e1fdb6afb1d993801a980&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F3801213fb80e7beca9004ec5252eb9389b506b38.jpg'
      ]
    },
    comments: [
      {
        user: {
          id: 233122,
          name: '亚索'
        },
        reply: '面对疾风吧'
      }
    ]
  }
]

const typeDefs = `
  type Query {
    moments: [Moment]
  }
  type Mutation {
    addComment(
      entity: Add_Comment
    ) : Comment
  }
  type Moment {
    user: User
    main: Main
    comments: [Comment]
  }
  type User {
    id: Int
    name: String
    avatar: String
  }
  type Comment {
    user: User
    reply: String
  }
  type Main {
    content: String
    pics: [String]
  }
  input Add_User {
    id: Int
    name: String
  }
  input Add_Comment {
    user: Add_User
    reply: String
  }

  # 定义graphqlf服务哪个是RootQuery以及RootMutation
  schema {
    query: Query
    mutation: Mutation
  }
`

const resolvers = {
  Query: {
    moments () {
      return moments
    }
  },
  Mutation: {
    addComment (_, { entity }, unknown, context) {
      console.log(entity)
      moments[0].comments.push(entity)
      return entity
    }
  }
}

const schema = makeExecutableSchema({
  typeDefs,
  resolvers
})

// koaBody is needed just for POST.
router.post('/graphql', koaBody(), graphqlKoa({ schema: schema }))
// router.get('/graphql', graphqlKoa({ schema: schema }))

router.get('/graphiql', graphiqlKoa({ endpointURL: '/graphql' }))

async function responseMiddleware(ctx, next) {
  ctx.set('Access-Control-Allow-Origin', 'http://localhost:8080')
  ctx.set('Access-Control-Allow-Methods', 'POST,OPTIONS')
  ctx.set('Access-Control-Allow-Headers', 'authorization,content-type')
  // ctx.set('Access-Control-Allow-Credentials', 'true')
  await next()
}

app.use(responseMiddleware)
app.use(router.routes())
app.use(router.allowedMethods())

app.ws.use(responseMiddleware)
app.ws.use(router.routes())
app.ws.use(router.allowedMethods())

app.listen(PORT)

GraphQL概述

GraphQL基本语法特性

包括有fields,alias,arguments,fragments,variables,directives,inline fragments

  • field

GraphQL类型系统

主要由RootQuery + RootMutation两种入口类型(操作)加上RootValue(resolvers)构成GraphQL Schema。(此处用graphql-tools是为了将所有的类型定义在一个字符串中,后续会移到一个.graphql文件中,然后用graphql-import导入)

GraphQL类型系统内置基础类型

  • 标量类型(Scalar Types)

    • Int: 有符号的32位整数
    • Float: 有符号双精度浮点值
    • String: UTF-8字符序列
    • Boolean: true or false
    • ID:ID 标量类型表示一个唯一标识符(类似一种UUID),通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化。
  • 枚举类型(Enumeration Types)

是一种特殊的标量类型



enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

  • 数组类型(Array Types)

用方括号[]标记列表

  • 接口类型(Interface Types)

是一种抽象类型,与java的interface机制类似。

  • 联合类型(Union Types)


{
  search(text: "an") {
    ... on Human {
      name
      height
    }
    ... on Droid {
      name
      primaryFunction
    }
    ... on Starship {
      name
      length
    }
  }
}

  • 输入类型(Input Types)

与之前提到的所有Types对立,这是一种也是唯一一种输入类型,其主要用于mutations时传递整个对象的case,它没有参数。

内置修饰符

  • !: 表示非空。如下


query DroidById($id: ID!) {
  droid(id: $id) {
    name
  }
}

GraphQL工作原理

GraphQL中每个查询字段是返回子类型的父类型函数。每个类型的字段对应由一个resolver函数支持,当字段被执行时,响应的resolver被调用并return结果。

如果字段产生结果为标量类型值,比如字符串或数字,则执行完成。否则递归执行对应解析器直至结果为标量类型值。

GraphQL基本数据流

每个GraphQL服务端应用的顶层必定会有一个入口点,通常为Root或者Query类型,接着执行该字段预设的解析器(同步或异步),而每个字段被解析的结果被放置在键值映射中,字段名(或别名)作为键,解析器的值作为值,这个过程从查询字段的底部叶子节点开始返回,直到Query类型的起始节点,最后生成镜像查询结果返回给客户端

Vue工程接入GraphQL

安装vue-cli3.x


npm i -g @vue/cli

初始化工程


vue create [project-name]

引入apollo插件
cd [project-name]
vue add apollo

FriendCircle.vue
<template>
  <div>
    <div v-for="(item, index) in moments" :key="index">
      {{item}}
    </div>
    <input type="text" v-model="comment.reply" placeholder="请输入要回复的内容">
    <button @click="addComment">回复</button>
  </div>
</template>

<script>
import gql from 'graphql-tag'

const QUERY_LIST = gql`
  query {
    moments {
      user {
        id
        name
        avatar
      }
      main {
        content
        pics
      }
      comments {
        user {
          id
          name
        }
        reply
      }
    }
  }
`

export default {
  data () {
    return {
      moments: [],
      comment: {
        user: {
          id: (Math.random() * 10000).toFixed(0),
          name: '费德提克'
        },
        reply: ''
      }
    }
  },
  apollo: {
    moments: {
      query: QUERY_LIST
    }
  },
  methods: {
    addComment () {
      this.$apollo.mutate({
        mutation: gql`
          mutation addComment($comment: Add_Comment) {
            addComment(entity: $comment) {
              user {
                id
                name
              }
              reply
            }
          }
        `,
        variables: {
          comment: this.comment
        },
        update: (store, { data: { addComment } }) => {
          // Read the data from our cache for this query.
          const data = store.readQuery({ query: QUERY_LIST })
          // set first moment's comment
          data.moments[0].comments.push(addComment)
          // Write our data back to the cache.
          store.writeQuery({ query: QUERY_LIST, data })
        }
      })
    }
  }
}
</script>

涉及的知识点有Root_Query,Root_Mutation,variables以及store cache

cache

其核心机制包括以下两点

  1. 对所有(包括嵌套的)非标量类型递归进行缓存,往往通过类型id或_id以及__typename唯一组合标识,然后在一个扁平的数据结构中存储
  2. 可以设置不同缓存策略:cache-and-network,no-cache,network-only

update回调

this.$apollo.mutate(options) options中有一个update回调,在成功响应数据后触发,并且可以直接读取并操作由apollo-cache-inmemory生成的store。上述例子中使用此回调同步更新缓存以及UI

注:所有绑定的变量均不可直接修改,内部使用Object.freeze将对象冻结,无法直接增删。



文发布时间为:2018年06月17日
原文作者:清风0o0

本文来源: 掘金 如需转载请联系原作者




相关文章
|
6月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
536 137
|
7月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
619 2
|
9月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
440 0
|
9月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
641 1
|
10月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1059 0
|
10月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
10月前
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
623 1
|
10月前
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
650 17
|
10月前
|
存储 JavaScript 前端开发
如何高效实现 vue 文件批量下载及相关操作技巧
在Vue项目中,实现文件批量下载是常见需求。例如文档管理系统或图片库应用中,用户可能需要一次性下载多个文件。本文介绍了三种技术方案:1) 使用`file-saver`和`jszip`插件在前端打包文件为ZIP并下载;2) 借助后端接口完成文件压缩与传输;3) 使用`StreamSaver`解决大文件下载问题。同时,通过在线教育平台的实例详细说明了前后端的具体实现步骤,帮助开发者根据项目需求选择合适方案。
918 0
|
10月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
478 0