你听说过GraphQL吗?不妨用它搭个博客吧

GraphQL 

QL?  一看到QL。。。。。。 没错,确实是查询语言
其实GraphQL很早就问世了,但是对于前端来说,工作上好像几乎寻觅不到它的踪影~~ 
(博主搬运代码3年了多了,也没用过, 惭愧惭愧)

据说早在2012年,Facebook内部就开始开发GraphQL,直到2015年才公布于众。
所以自然也是个有脸面的人啦,且看官网是这么介绍它的


官网中文地址: https://graphql.cn/

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。

GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,

也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

这里我们主要关注一句话:准确地获得它需要的数据,而且没有任何冗余
(莫非指哪打哪?百发百中? ~~~~~)
其实通俗的理解是: 我只需要接口里的a,b,c字段, 不需要d,e,f字段,但是有可能后台给我们返回a~f,甚至返回了两个a
这时候就出现了不需要,或者冗余的数据
所以GraphQL的出现,能够解决这种问题

下面我们通过GitHub + GraphQL搭建一个个人博客案例来了解GraphQL 
(相信也有不少大大跟博主一样,用过GitHub写博客的)

省时省力,源码直接获取: https://github.com/YMDaunt/Blog 

这里我们用GitHub的Issues作为写博客的主要工具,也可以理解为它是生成博客内容数据的服务器
这里博主把之前写好的测试Issues拿来用

 

 

 看着好像确实是个不错的目录,当然,要使用GitHub的API,首相还是要和GitHub“说一声,打下招呼”的
接下来就用这几个步骤获取GitHub的token

1.右上角个人,选择Settings
2.左边菜单栏选择Developer settings
3.左边菜单栏选择Personal access tokens
4.Generate new token 创建一个新的token
5.Token description ——> 输入token的描述
6.Select scopes 选择一些权限 这里选择user > read:user 即可
7.点击创建,创建完会有个token,必须记下来,因为刷新完就再也看不到,也查不到

这部分的具体我就不一一罗列了,给大伙留下个地址,可以参考下
https://blog.csdn.net/qq_15174755/article/details/83306497

接下来,有数据了,那么就是看GraphQL如何将这些数据拿到手~~ 

先上完整代码: 

<template>
   <div class="wrap">
       <div class="nav">
            <ul>
                <li @click="searchAll()">首页</li>
                <li v-for="(item, index) in navArr" v-bind:key="index" v-bind:data-name="item.name" @click="searchNeed($event)">{{item.name}}</li>
            </ul>
        </div>
        <div class="con">
            <ul>
                <li v-for="(item, index) in articleArr" v-bind:key="index">
                    <h2><a :href="'#/article?id='+ item.node.number" v-bind:data-id="item.node.number">{{item.node.title}}</a></h2>
                    <p>{{item.node.bodyText}}</p>
                    <span v-html="(item.node.updatedAt).replace(/[a-zA-Z]/g, ' ')"></span>
                </li>
            </ul>
        </div>
   </div>
</template>
<script>
    import Vue from 'vue/dist/vue.js';
    import axios from 'axios';
    import githubToken from '../../config/githubConfig';
    import '../css/index.less'
    
    export default {
        name: 'index',
        components: {

        },
        data() {
            return {
                searchData: {
                    query: `query {
                        repository(owner:"YMDaunt", name: "Blog") {
                            issues(orderBy:{field: UPDATED_AT, direction: DESC} , labels: null, first: 10) {
                                edges{
                                    cursor
                                    node{
                                        title
                                        updatedAt
                                        bodyText
                                        number
                                    }
                                }
                            }
                            labels(first: 100){
                                nodes {
                                    name
                                }
                            }
                        }
                    }`
                },
                navArr: [],
                articleArr: [],
                needKey: '',  //搜索指定文章用的key
            }
        },
        created: function(){
            this.searchAll();
        },
        methods: {
            // 搜索所有
            searchAll() {
                var searchStr = JSON.stringify(this.searchData)
                axios.post('https://api.github.com/graphql?access_token=' + githubToken, searchStr)
                .then(res => {
                    let data = res.data.data.repository
                    this.navArr = data.labels.nodes
                    this.articleArr = data.issues.edges
                    console.log(this.navArr, this.articleArr)
                })
                .catch(err => {
                    console.log(err);
                })
            },

            // 搜索指定的类型文章
            searchNeed(e) {
                this.needKey = e.target.getAttribute('data-name');
                var needQuery = {
                    query: `query {
                        repository(owner:"YMDaunt", name: "Blog") {
                            issues(orderBy:{field: UPDATED_AT, direction: DESC} , labels: "${this.needKey}", first: 10) {
                                edges{
                                    cursor
                                    node{
                                        title
                                        updatedAt
                                        bodyText
                                        number
                                    }
                                }
                            }
                        }
                    }`
                }
                needQuery = JSON.stringify(needQuery)

                axios.post('https://api.github.com/graphql?access_token=' + githubToken, needQuery)
                .then(res => {
                    let data = res.data.data.repository
                    this.articleArr = []
                    this.articleArr = data.issues.edges
                })
                .catch(err => {
                    console.log(err)
                })
            }
        },
        mounted: function(){

        }
    }
</script>  

 


然后我们解释下JS代码里面的东西
我们import了 githubToken文件,这个token就是大家从GitHub上申请的token,就是这边需要用到。
为了灵活使用,还是建议大家单独创建token的js,内容如下

const githubToken = '89aedea252f1511f8052ddbfb4270252366806ce';
export default githubToken

然后我们看下data中定义了那些数据

data() {
            return {
                searchData: {
                    query: `query {
                        repository(owner:"YMDaunt", name: "Blog") {
                            issues(orderBy:{field: UPDATED_AT, direction: DESC} , labels: null, first: 10) {
                                edges{
                                    cursor
                                    node{
                                        title
                                        updatedAt
                                        bodyText
                                        number
                                    }
                                }
                            }
                            labels(first: 100){
                                nodes {
                                    name
                                }
                            }
                        }
                    }`
                },
                navArr: [],
                articleArr: [],
                needKey: '',  //搜索指定文章用的key
            }
        },
navArr是博客类型数组,用于导航栏切换搜索
articleArr是博客文章数组

needKey为指定的文章id
searchData,搜索的关键参数,这部分就是GraphQL获取数据的核心

 

我们主要说说searchData中的参数:

repository代表查询指定的仓库,参数owner代表所有者,name为你创建仓库的名字

issues表示要查询的issue列表,里面包含如下参数

  orderBy为排序方式,根据更新时间UPDATED_AT和倒序DESC来,

labels为指定查询name,能够返回博客所有分类,

first表示一次查询返回的issues数量,

after传上一个issue的id,可用来分页。

title,updatedAt,bodyText,number这些字段刚好就是Issues中文章的信息

我们想要的数据,都告知给GraphQL,GraphQL就会给我们返回什么

然后我们得到如下数据:

  

 

 

 

不仅我们拿到了Issues中的所有文章,也拿到了labels的分类数据,因此就能够实现一个包含分类导航的博客主页
以下我们先不考虑样式,且先看结果:

 

 

 

是不是感觉这个方案可行?


有首页目录以及导航,那接下来就是文章内容了

通过上面的搜索结果,我们发现每一篇博客文章都有自己的id标识,也就是接口返回的number

 

 

有了它,我们就可以精确到搜索哪篇博客文章了

 

那就先上文章搜索页的代码

 

 

<template>
   <div class="wrap">
       <div class="nav">
           <ul>
               <li>
                   <a href="#/index">首页</a>
               </li>
           </ul>
       </div>
        <div class="c-con">
            <h2>{{articelTitle}}</h2>
            <span>{{articelTime}}</span>
            <div class="text-con markdown-body">
                <div v-html="articelTxt"></div>
            </div>
        </div>
   </div>
</template>
<script>
    import Vue from 'vue/dist/vue.js';
    import axios from 'axios';
    import githubToken from '../../config/githubConfig';
    import '../css/index.less'
    import 'github-markdown-css'

    export default {
        name: 'articel',
        components: {

        },
        data() {
            return {
                articelId: 0,
                articelArr: [],
                articelTitle: '',  //题目
                articelTime: '',   //时间
                articelTxt: '',    //内容
            }
        },
        created: function(){
            // 获取文章id
            this.articelId = this.GetUrlParam('id')
            // 搜索该文章数据
            this.searchArticle(this.articelId)
        },
        methods: {
            // 搜索对应文章
            searchArticle(id) {
                var searchData = {
                    query: `query {
                        repository(owner:"YMDaunt", name: "Blog") {
                        issue(number: ${id}) {
                            title
                            updatedAt
                            bodyHTML
                        }
                        }
                    }`
                }
                searchData = JSON.stringify(searchData)

                axios.post('https://api.github.com/graphql?access_token=' + githubToken, searchData)
                .then(res => {
                    let data = res.data.data.repository
                    this.articelArr = data.issue
                    console.log(this.articelArr)
                    this.articelTitle = this.articelArr.title
                    this.articelTime = this.articelArr.updatedAt
                    this.articelTxt = this.articelArr.bodyHTML
                })
                .catch(err => {
                    console.log(err);
                })
            },

            // 获取参数
            GetUrlParam(paraName) {
                var url = document.location.toString()
                var arrObj = url.split("?")
            if (arrObj.length > 1) {
              var arrPara = arrObj[1].split("&")
              var arr
              for (var i = 0; i < arrPara.length; i++) {
                arr = arrPara[i].split("=")
                if (arr != null && arr[0] == paraName) {
                  return arr[1]
                }
              }
              return ""
            }
            else {
              return ""
            }
            },
        },
        mounted: function(){

        }
    }
</script>  

 

我们点击首页目录,通过目录中的number传给文章页作为文章id参数  
例如:我们点击进入id为7的文章,就可以得到以下效果

 

 

 没错,文章详情页也能进来看了,并且它的样式与Issues是一样的,原因就在于我们引用了github-markdown-css
也就是Issues中的富文本CSS样式,没错它就是开源可用的
相当于将做了一次“Issues的搬运工”
(看来,可以做农夫山泉了~~~~我们是大自然的搬运工)

最后,小伙伴们不妨自己试下,

这边仅仅是介绍了GraphQL的简单应用,至于它为啥没能火起来呢? 

因为目前使用GraphQL作为后端语言的公司并不多,要转型到GraphQL需要按照GraphQL的做法,费时费力!



 

posted @ 2020-03-17 16:54  EdgeQAQ  阅读(647)  评论(0)    收藏  举报