Vue下滚动到页面底部无限加载数据Demo

看到一篇Implementing an Infinite Scroll with Vue.js, 觉得挺实用的就看了下, 顺便简单翻译了一下给需要的人参考.
从这个项目中可以加深对Vue的生命周期的理解, 何时开始axios请求, 如何结合Vue使用原生js来写scroll事件等等, 我这里主要是对原文的重点提取和补充

Vue下滚动到页面底部无限加载数据Demo

看到一篇Implementing an Infinite Scroll with Vue.js, 觉得挺实用的就看了下, 顺便简单翻译了一下给需要的人参考.

从这个项目中可以加深对Vue的生命周期的理解, 何时开始axios请求, 如何结合Vue使用原生js来写scroll事件等等, 我这里主要是对原文的重点提取和补充

本文技术要点

  • Vue生命周期
  • axios简单用法
  • moment.js格式化日期
  • 图片懒加载
  • 结合原生js来写scroll事件
  • 请求节流

创建项目

首先创建一个简单的vue项目

# vue init webpack-simple infinite-scroll-vuejs

然后安装项目所需要用的一些插件

# npm install axios moment

初始化用户数据

项目搭建完后, 跑起来看看

# npm run dev

打开http://localhost:8080无误后, 我们开始修改代码, 先看看获取用户数据这块,

<script>
import axios from 'axios'
import moment from 'moment'
export default {
  name: 'app',
  // 创建一个存放用户数据的数组
  data() {
    return {
      persons: []
    }
  },
  methods: {
    // axios请求接口获取数据
    getInitialUsers() {
      for (var i = 0; i < 5; i++) {
        axios.get(`https://randomuser.me/api/`).then(response => {
          this.persons.push(response.data.results[0])
        })
      }
    },
    formatDate(date) {
      if (date) {
        return moment(String(date)).format('MM/DD/YYYY')
      }
    },
  beforeMount() {
    // 在页面挂载前就发起请求
    this.getInitialUsers()
  }
}
</script>

这里原作者也专门提醒, 完全没有必要也不建议在加载页面的时候请求5次, 只是这个接口一次只能返回1条数据, 仅用于测试才这样做的. 当然我这里也可以通过Mock来模拟数据, 就不详细说了~

接下来来写模板结构和样式, 如下:

<template>
  <div id="app">
    <h1>Random User</h1>
    <div class="person" v-for="(person, index) in persons" :key="index">
      <div class="left">
        <img :src="person.picture.large" alt="">
      </div>
      <div class="right">
        <p>{{ person.name.first}} {{ person.name.last }}</p>
        <ul>
          <li>
            <strong>Birthday:</strong> {{ formatDate(person.dob)}}
          </li>
          <div class="text-capitalize">
            <strong>Location:</strong> {{ person.location.city}}, {{ person.location.state }}
          </div>
        </ul>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.person {
  background: #ccc;
  border-radius: 2px;
  width: 20%;
  margin: 0 auto 15px auto;
  padding: 15px;

  img {
    width: 100%;
    height: auto;
    border-radius: 2px;
  }

  p:first-child {
    text-transform: capitalize;
    font-size: 2rem;
    font-weight: 900;
  }

  .text-capitalize {
    text-transform: capitalize;
  }
}
</style>

这样页面就能显示5个人的个人信息了.

处理无限滚动加载逻辑

我们接下来需要在methods里面添加scroll()来监听滚动, 并且这个事件是应该在mounted()这个生命周期内的. 代码如下:

<script>
  // ...
  methods: {
    // ...
    scroll(person) {
      let isLoading = false
      window.onscroll = () => {
        // 距离底部200px时加载一次
        let bottomOfWindow = document.documentElement.offsetHeight - document.documentElement.scrollTop - window.innerHeight <= 200
        if (bottomOfWindow && isLoading == false) {
          isLoading = true
          axios.get(`https://randomuser.me/api/`).then(response => {
            person.push(response.data.results[0])
            isLoading = false
          })
        }
      }
    }
  },
  mounted() {
    this.scroll(this.persons)
  }
}
</script>

这段代码原文是有一点拼写错误的. 我这里修正了, 另外增加了距离底部即开始加载数据, 并进行截流.

保存好, 回到浏览器, 查看效果, 已经没有问题了~

总结

滚动到页面底部无限加载的功能在Vue上实现其实和普通的页面开发差不多, 每次滚动加载未完成的情况下不会触发请求下一次, 每次请求push到数组内, 通过<img :src="">的数据绑定实现了懒加载(其实0 0我不太认可…), 看完是不是感觉挺简单的.

最后, 我把这个也弄了一份在GitHub上面, 有需要的可以看看infinite-scroll-vuejs-demo~

Clevo W350ETQ(神舟K590S)安装黑苹果10.13总结

作为一名爱瞎折腾的前端来说, 学会使用MacOSX, 或许是有必要的, 于是想着去买一台MBP, 可是无奈电脑太多, 不想再添置, 于是把我的神级Clevo W350ETQ(也是神舟后来出的K590S)忍痛的挂在了闲鱼上, 自己一直保养很好, 后来怒加4G条子和SSD, 所以卖的比一般的二手贵, 无人识相, 遂继续自用.

作为一名爱瞎折腾的前端来说, 学会使用MacOSX, 或许是有必要的, 于是想着去买一台MBP, 可是无奈电脑太多, 不想再添置, 于是把我的神级Clevo W350ETQ(也是神舟后来出的K590S)忍痛的挂在了闲鱼上, 自己一直保养很好, 后来怒加4G条子和SSD, 所以卖的比一般的二手贵, 无人识相, 遂继续自用.

我的电脑配置及相关评测曾经也在博客(相关索引)中提到. 在当年来说是非常强悍的一款游戏本, 至今依然能算一台中端性能笔记本, 只是便携性太差, 一直以来都作为办公台式机使用, 我这台配置如下:

处理器名称: Mobile QuadCore Intel Core i7-3612QM, 3000 MHz (30 x 100)
主板名称: Clevo W35_37ET
主板芯片组: Intel Panther Point HM77, Intel Ivy Bridge
系统内存: 8084 MB (4 GB * 2 DDR3-1600)
显示适配器:
  Intel(R) HD Graphics 4000
  NVIDIA GeForce GTX 660M
显示器: LG Philips LP156WF1-TLC1 [15.6" LCD]
音频适配器: Realtek ALC269 @ Intel Panther Point PCH - High Definition Audio Controller [C-1]
IDE 控制器: Intel(R) 7 Series Chipset Family SATA AHCI Controller
IDE 控制器: Realtek PCIE CardReader
硬盘驱动器: OCZ-VERTEX4
硬盘驱动器: ST9500423AS
光盘驱动器: TSSTcorp CDDVDW SN-208AB
键盘: PS/2 标准键盘
鼠标: ELAN Input Device
网络适配器: Realtek PCIe GBE Family Controller
网络适配器: Realtek RTL8723AE Wireless LAN 802.11n PCI-E NIC (192.168.31.248)
USB 设备: BisonCam, NB Pro
USB 设备: Realtek Bluetooth 4.0 Adapter
USB 设备: TouchStrip Fingerprint Sensor (WBF advanced mode)
DMI 系统制造商: CLEVO CO.
DMI 系统产品: W35_37ET

只有先弄清楚配置才能接下来进行黑苹果的安装, 其实几年前我尝试过安装黑苹果, 最终以失败告终, 然而本来是抱着看看的心理, 又跑去看远景论坛, 看到一个帖子: 【初春之献】macOS High Sierra 10.13.4 17E199 With Clover 4423修正原版镜像, 一下子又动了心, 于是这清明几天假又没有休息好, 为了安装上黑苹果简直比上班工作的状态还要投入, 一下子三天过去了, 我后背越发疼了. 心想这几天本来可以好好休息顺便学习下Vuex, 计划泡汤! 好在, 最后还是折腾出来了点结果. 基本上算比较完美了. 接下来我就对这几天的研究做个总结. 先上图两张图过过瘾.

继续阅读“Clevo W350ETQ(神舟K590S)安装黑苹果10.13总结”

用Gatsby和Strapi创建一个静态博客

本文以简单通俗的方式讲解了结合Gatsby和Strapi创建一个静态博客的方法和具体步骤, 也额外插入了许多创建过程中遇到的各种问题和解决办法.

原文参阅: Building a static blog using Gatsby and Strapihttps://blog.strapi.io/buildi…. 本篇首发在SegmentFault上, 用Markdown语法, 所以美观性相比更强. 本篇主要是对原文精华内容进行翻译, 以及实操过程中遇到的问题解决和探索. 一些具体的操作步骤和细节, 我将忽略, 结合原文一起阅读效果更佳!

注: 本文操作环境是Linux VPS, CentOS 6 64bit

介绍

这是一个包含很多静态内容页面的站点, 从技术上来说就如同一系列HTML文件, 展示给访问者. 与动态网站不同的是, 他不需要后端开发或者数据库支撑. 发布静态站点之所以容易, 是因为文件只需要上传到服务器或者存储器. 没有额外的渲染页面的请求, 也没有数据库被黑的风险, 所以它既安全也快速.

为了快速建站, 其实很多开源的静态页面生成框架可用, 比如前阵子我搞的Jekyll, Hugo, 好似国人偏爱的Hexo等等, 他们的工作原理相似, 内容都是通过静态文件(比如Markdown)或者带有内容的API, 通过获取这些内容, 注入到开发者做好的模板, 最后生成一大堆HTML文件.

Progressive Web Apps (PWA)实际上是网页应用, 几乎基于Javascript, 并且可靠, 快速, 有吸引力的. 这几年比较火的Angular, Vue, React都是类似的前端框架.

静态站点遇见了PWA就产生了Gatsby

将这两点组合起来的最佳选择看起来就是Gatsby了, 但是同样需要一个内容接口, 这就是我将要展示的, 通过Strapi创建一个内容API提供给Gatsby, 然后打包发布出一个静态站点.


Gatsby是什么

这个并不是型男熟知的杰士派, 虽然我也用过这个发泥, 好像不是很好用. Gatsby是基于React的快速静态网站框架, 有了它, 你就可以感觉飘飘然的开发React网站了.

Strapi是什么

Strapi是一个基于高级的Nodejs API内容管理框架. 听起来有点绕口, 通俗来说就是让你能简单, 安全, 高效的开发出强大API的开源的内容管理框架. 它是免费的, 人们都爱免费的, 可以随意在你的服务器上使用, 也非常具有可个性化, 可扩展性的玩意.

我真想不到国内几乎没有人用Gatsby和Strapi, 百度上查不到任何资料…

创建API

见证奇迹的时刻即将到来, 我们快创建个Strapi API, 添加点内容吧!

创建Strapi项目

Requirements: please make sure Node 8 (or higher) and MongoDB are installed and running on your machine.

此时, 暗喜前阵子已经琢磨出来了并装好了Node 8, 不过装MongoDB就没有了. 因此这里就要插入一段关于MongoDB的内容了. 如果已经有了请自动跳过此内容.

MongoDB安装及相关问题

果断找到文档Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux, 这个redhat和centOS应该是通用的吧- -! 看到Configure the package management system (yum)., 发现原来还有这种操作, 创建repo文件, 来安装对应版本的软件. 闲话少说, 直接上代码:

# cd /etc/yum.repos.d/
# touch mongodb-org-3.6.repo
# vi mongodb-org-3.6.repo

将以下内容copy进去保存

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

再进行安装

# sudo yum install -y mongodb-org

如果有特殊需求, 请参阅上文提到的官方文档, 我这里装的是MongoDB Community Edition

按以上步骤很快就装好了. 接下来启动mongod(如果没有启动的话), 如下命令:

# service mongod start

完成后, 我们接着创建Strapi项目的主题, 推荐安装strapi@alpha版本:

# npm i strapi@alpha -g

完成后, 去到你要创建本文项目的目录, 比如我这里的路径是/home/web/, 我在这里创建一个gatsby-strapi-tutorial目录:

# mkdir gatsby-strapi-tutorial

在这里面搭一个API脚手架

# cd gatsby-strapi-tutorial
# strapi new api

进入项目目录, 并运行Node.js服务器

# cd api
# strapi start

遇到了一些小问题

这里突然时不时卡住了, 如果你很顺利, 那么可以跳过此内容, 频繁报错如下

[root@whidy api]# strapi start
DEBUG (24910 on whidy): Server wasn't able to start properly.
ERROR (24910 on whidy): (hook:mongoose) takes too long to load

大概是网络原因, 我联通网络出问题, 换了电信几番尝试就好了.

操作过程中频繁出现刚才的问题, 我觉得不是网络问题那么简单, 我打算从数据库方面着手完善一下试试, 当然后来证明, 一切问题都与MongoDB无关, 所以下面缩进内容可以选择性阅读大多数情况下我是不愿意理睬WARNING信息的, 只要不是ERROR就好, 但是这次我有点不爽, 后来折腾了半天发现有的很难处理, 好吧我错了, 我想我还是不死磕了吧😱.

  • soft rlimits too low
    WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.

    参阅:

  • versions of RHEL older than RHEL6
    WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

    服务器硬件限制? 可以安全忽略.

    参阅: WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

  • Access Control
    以为要搞账户什么的, 然后运行mongo命令, 创建了一个admin账户:

    # mango
    > use admin
    > db.createUser(
        {
          user: "username",
          pwd: "userpassword",
          roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
      )
    # mongo --port 27017 -u "username" -p "userpassword" --authenticationDatabase "admin"

    其实我自己当时也不知道是搞啥, 其实完全没关系的操作. 很多人甚至官方文档Start MongoDB without access control.也提到:

    mongod --port 27017 --dbpath /data/db1

    可是我一直报错, 要么说不存在, 搞半天才明白, 要手动创建, 创建好了, 又说服务被占用, service mongod stop停了服务, 连上去了, show dbs发现跟之前的又不一样, 没有找到我之前看到的strapi库, 才恍然大悟, 原来其实我创建了一个跟之前无关的库…

    事实上, 启动mongod服务的时候, 它连接了一个默认配置库, 这个库的路径时早就创建好的, 通过查看/etc/mongod.conf这个文件就知道了. 因此删了那个没用的db目录. 接着操作.

    后来第二天早上, 再次执行strapi start很顺利. 我也没办法再研究昨天究竟是为什么总是连不上了. 反正就是渣渣网络经常会带来各种坑!😡, 这段没什么作用的内容就过去了.

回到刚才strapi start, 成功之后, 我们如果是本地操作的, 带有界面的操作系统的话就可以直接访问http://localhost:1337/admin了, 如果也是远程操作, 就改成IP就好了.

接下来的操作是创建用户, 原文已经图文并茂, 傻子都能看懂的步骤了, 由于篇幅过大, 我就简单翻译一下, 不详细复述了嘿嘿~

按照原文操作:

  1. 创建管理员账号(Create your first User)
  2. 创建内容类型(Create a Content Type)
    名为article的内容类型有三个字段: title(字符串), content(文本), author(关系, 多文章对应一个用户).
  3. 添加几项内容到数据库
    1. 访问文章列表页
    2. 点击Add New Article
    3. 插入值, 连接对应的作者并保存
    4. 重复以上操作, 创建额外两篇文章
  4. 允许API权限, 依原文对应勾选保存

完成后, 就可以访问http://localhost:1337/article了.

创建静态站

到目前, 你的API搞定了, 我们要搞静态网站啦

安装Gatsby

首先, 全局安装Gatsby CLI:

# npm install --global gatsby-cli

生成Gatsby项目

回到之前提到的gatsby-strapi-tutorial目录, 创建一个新博客:

# gatsby new blog

事情总是不是那么顺利.

报错, 需要git. 然而我的这台崭新的服务器还没装, 那就装一个吧.

如果你的git已经部署OK, 并且上面这个操作没有问题, 以下内容可忽略:

参考Download for Linux and Unix执行:

# yum install git

再次执行后依旧报错(当前git版本1.7.1)

error Command failed: git clone git://github.com/gatsbyjs/gatsby-starter-default.git blog --single-branch

推测是版本问题. 只好手动安装了. 于是又找到这个安装 Git

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# wget https://www.kernel.org/pub/software/scm/git/git-2.16.1.tar.gz
# tar -zxf git-2.16.1.tar.gz
# cd git-2.16.1
# make prefix=/usr/local all
# sudo make prefix=/usr/local install

漫长的make prefix=/usr/local all之后, 提示:

    SUBDIR perl
/usr/bin/perl Makefile.PL PREFIX=\'/usr/local\' INSTALL_BASE=\'\' --localedir=\'/usr/local/share/locale\'
Can\'t locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.
BEGIN failed--compilation aborted at Makefile.PL line 3.
make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2

蛋疼, 等了半天, 又要解决这个问题, 好在看起来比较容易处理, 参考git fails to build in Fedora 14, 然后继续执行最后两条make命令, 虽然最后出来很多看起来很奇怪的内容, 不过似乎是成功了. 执行:

# git --version
git version 2.16.1

接下来我们再一次执行gatsby new blog, 我擦还提示刚才的...single-branch的error, 这就坑爹了- -. 经过简短的排查. 原来似乎他还是跑的旧版git, 需要删掉之前yum自动安装的git 1.7.1, 我单纯的以为直接自动升级了. 于是:

# yum remove git

按照提示删除成功后, 再次检测git还是ok的, 这次我第三次执行gatsby new blog, 终于成功了!

我这小白也不知道linux软件管理是咋整的. 反正能继续执行卡了我半天的gatsby就好了吧…每次创建速度很慢, 执行gatsby new blog完成的时候提示added 1398 packages in 137.652s, 大概就是2分钟多, 可能是安装依赖包费时吧

启动开发模式

创建成功后, 接着操作, 进入博客目录

# cd blog

启动服务器

# gatsby develop

理论上你就可以通过http://localhost:8000访问到默认的效果博客站点了.

然而又一次出现小插曲, 如果你是和我一样远程访问, 也许以下内容对你有用

每次执行gatsby develop的时间甚至更长, 完成时提示如下:

info bootstrap finished - 334.876 s

DONE  Compiled successfully in 90373ms 21:15:06


You can now view gatsby-starter-default in the browser.

http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema

http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use gatsby build

大概用了6分钟左右, 糟糕的是并不能通过远程IP来访问! 查看了目录下的配置文件和官方文档, 也没查到. 绝望之时, 突然在大量资料中看到webpack也有这样的问题, 想起来之前webpack的server默认配置也是无法通过ip访问, 但是webpack的devServer配置host: "0.0.0.0"即可, 试了下:

# gatsby develop --host 0.0.0.0

又经过4分钟左右漫长等待, 这次成功了! 不过我尝试搜索Gatsby究竟用的什么服务器启动, 为何不能像webpack那样加一段配置呢, 却没有找到. 后来凑巧找到了一篇webpack下的issue, Server can’t be accessed via IP, 有人提到过这条命令.

因此, 从小插曲中来看, 远程访问控制的开发者, 需要加个参数, 具体命令:

# gatsby develop --host 0.0.0.0

这样, 至此开发模式服务器搞定.

安装Strapi插件(Install the Strapi source plugin)

Gatsby understands this pretty well. So its creators decided to build a specific and independent layer: the data layer. This entire system is strongly powered by GraphQL.

前面有一些插件介绍不多说了, 执行安装:

# npm install --save gatsby-source-strapi

完成后, 需要做些配置, 修改gatsby-config.js文件, 替换成以下内容:

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-strapi`,
      options: {
        apiURL: `http://localhost:1337`,
        contentTypes: [ // List of the Content Types you want to be able to request from Gatsby.
          `article`,
          `user`
        ]
      },
    },
  ],
}

保存后, 重启Gatsby服务器

文章列表

为了在首页显示文章列表, 我们需要修改首页代码如下:

路径: src/pages/index.js

import React from 'react'
import Link from 'gatsby-link'
const IndexPage = ({ data }) => (
  <div>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <ul>
      {data.allStrapiArticle.edges.map(document => (
        <li key={document.node.id}>
          <h2>
            <Link to={`/${document.node.id}`}>{document.node.title}</Link>
          </h2>
          <p>{document.node.content}</p>
        </li>
      ))}
    </ul>
    <Link to="/page-2/">Go to page 2</Link>
  </div>
)
export default IndexPage
export const pageQuery = graphql`
  query IndexQuery {
    allStrapiArticle {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`

这里就应用到了GraphQL啦, 好激动呢. 我们导出pageQuery, 一个GraphQL查询会请求文章列表, 我们只需要将需要查询的字段添加进去就好了~

然后我们传递{ data }这个结构对象作为IndexPage参数, 遍历它的allStrapiArticles对象, 来展示数据.

GraphQL查询可以快速生成, 你可以尝试在http://localhost:8000/___graphql修改, 并测试.

文章页

首页有了列表之后, 我们还要访问文章页面呢, 接下来写一个模板:

路径: src/templates/article.js

import React from 'react'
import Link from 'gatsby-link'
const ArticleTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiArticle.title}</h1>
    <p>by <Link to={`/authors/${data.strapiArticle.author.id}`}>{data.strapiArticle.author.username}</Link></p>
    <p>{data.strapiArticle.content}</p>
  </div>
)
export default ArticleTemplate
export const query = graphql`
  query ArticleTemplate($id: String!) {
    strapiArticle(id: {eq: $id}) {
      title
      content
      author {
        id
        username
      }
    }
  }
`

你需要手动创建这个目录和文件, 当然Gatsby并不知道模板何时展示. 每篇文章都需要一个特别的URL, 感谢Gatsby提供的createPage函数.

首先, 我们写个makeRequest函数来处理GraphQL请求. 然后通过createPage函数使我们在获取的文章列表后为它们创建一个页面, 路径为文章id的URL, 回到blog目录, 修改gatsby-node.js文件

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Query for articles nodes to use in creating pages.
  return getArticles;
};

再次重启Gatsby服务器.

现在你就能通过点击首页的文章进入到文章内容页面了.

作者页

虽然这个似乎并不重要, 不过还是加上学习一下吧😁

添加作者页和创建文章页很相似, 我们还是先创建个模板:

路径: src/templates/user.js

import React from 'react'
import Link from 'gatsby-link'
const UserTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiUser.username}</h1>
    <ul>
      {data.strapiUser.articles.map(article => (
        <li key={article.id}>
          <h2>
            <Link to={`/${article.id}`}>{article.title}</Link>
          </h2>
          <p>{article.content}</p>
        </li>
      ))}
    </ul>
  </div>
)
export default UserTemplate
export const query = graphql`
  query UserTemplate($id: String!) {
    strapiUser(id: { eq: $id }) {
      id
      username
      articles {
        id
        title
        content
      }
    }
  }
`

然后再次修改gatsby-node.js来创建作者URLs:

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for article nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});

// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  const getAuthors = makeRequest(graphql, `
    {
      allStrapiUser {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each user.
    result.data.allStrapiUser.edges.forEach(({ node }) => {
      createPage({
        path: `/authors/${node.id}`,
        component: path.resolve(`src/templates/user.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Queries for articles and authors nodes to use in creating pages.
  return Promise.all([
    getArticles,
    getAuthors,
  ])
};

重启服务器, 刷新页面, Wow! 大功告成! 时不时很酷!!!

原文总结

恭喜, 你成功的创建了一个超快的很好维护的博客! 然后各种夸奖Blabla

接下来做什么呢? 你可以去更多的挖掘Gatsby和Strapi的各种优点, 你可以试着增加这些功能:

  • 作者列表
  • 文章分类
  • 用Strapi API创建评论系统, 或者直接用Disqus
  • 当然你也可以试着搞其他站点, 例如电商站, 企业站等等

当然为了进一步方便开发, 你可能需要一个方便的发布在网上的存储载体, Blablabla…

本教程GitHub源码地址, 你可以clone下来, 运行npm run setup, blablabla… 我是个爱研究的人, 我要一步步操作, 才不要clone.

个人总结

这次通过Gatsby和Strapi搭建一个简单的博客站点, 还是挺不容易的, 总共花了将近两天的时间. 不过个人感觉还是值得的! 其中有很多地方是可以更加深入的学习和了解的, 这也算初步接触了react, mongodb, graphQL等相关知识实操, 同时也可以在后期完善更多的功能, 了解并学习一些ES6, 模板的写法技巧等等. 也希望通过此次研究以后能更进一步熟悉其他框架, 数据库, 后端等思想~

相关参阅汇总

最后打个小广告, 我有个GitHub项目, 用于记录我每天学习或者瞎折腾的技术, 范围不限, 有兴趣可以star我的whidy daily

怎样找到当前页面发布日期的几种方法

为什么要搞清楚该网页内容的发布时间呢,有些网站作者的确很不友好,故意隐藏,目的是啥我也不知道。但是我觉得有时候的确很有必要知道正在查阅的内容,尤其是相对重要的内容的时候,他的发布日期对我来说很重要。

为什么要搞清楚该网页内容的发布时间呢,有些网站作者的确很不友好,故意隐藏,目的是啥我也不知道。但是我觉得有时候的确很有必要知道正在查阅的内容,尤其是相对重要的内容的时候,他的发布日期对我来说很重要。比如,遇到以下情况:

  • 有时候我们看到一些不错的文章或者新闻内容,分享给其他人后却被朋友嘲笑这都是老掉牙的内容了;
  • 还有时,查阅一些生活知识,或者时效性强的内容,比如你要补血,发现菠菜补铁促进生血,或者想多吃菠菜变成大力水手那样。其实现代科学证明没啥鸟用;
  • 再或者查找某些技术资料时,按照技术文章对应的方法实践的过程中发现有差异,或者无效的时候很气愤耽误了大量时间。

因此,我接下来要以知乎的某个文章有哪些高级笑话只有具备了一定的专业知识才能听懂?(我这里暂时不想去深究为啥知乎不公开提问日期)作为主要示例介绍一下如何能够找到网上的任何页面的发布日期的几种方法了。

继续阅读“怎样找到当前页面发布日期的几种方法”

Linux下无法正常安装(升级)和删除Nodejs的解决方法

Linux(CentOS6)下安装Nodejs,删除Nodejs,升级Nodejs遇到的一些问题,以及相关解决方案的介绍

接着上次说,自从买了VPS后就没闲着,总想要充分利用起来倒腾点东西。于是决定安装nodejs搭建web服务器等,如今nodejs稳定版本已经更新到8.x了,因此我就试着装一下8.x吧,没想到又遇到了坑,一搞搞了好几天。

我的操作系统是CentOS 6 64 Bit的,我查阅了Nodejs官方升级文档(包含各种可支持的系统),针对我的系统需要分别执行以下几条命令:

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo yum -y install nodejs

当然你也许需要通过以下命令额外安装构建工具:

sudo yum install gcc-c++ make
# or: sudo yum groupinstall 'Development Tools'

如果其他系统则可以参考文档中其他内容。

在这里我就遇到坑了(可能存在该情况较少,所以稍后具体解决放在文章最后来说)。上面第一条应该是静默指定使用8.x的资源,便于安装时采用这个而不是yum自己原来的远程仓,不知道这个解释对不对。

我反复试过了,命令明明提示请执行 sudo yum -y install nodejs 来安装nodejs8.x,却一直安装的是6.x,难道是依赖问题?找不出原因的我,没有办法只能找其他安装途径,于是发现了第二种安装办法,手动获取最新的安装包,并进行解压缩安装,可能依赖Python2.7以上版本,我一步步来说。

如果是仅手动安装Nodejs8.x,执行以下命令:

yum install gcc-c++ openssl-devel
cd /usr/local/src
wget http://nodejs.org/dist/v8.9.4/node-v8.9.4.tar.gz
tar zxvf node-v8.9.4.tar.gz
(cd into extracted folder: ex "cd node-v8.9.4.tar.gz")
./configure
make
make install

顺利的话应该不会有什么问题,大概会过一段时间,稍微有点长,就提示安装好了,可以执行

node -v

来查看是否是8.x,如果好了,基本上关于安装部分就大功告成了。如果没好,太惨了,跟Python有关系的话,请查看Linux下Python安装升级心得

接着我们来看看删除,因为你已经安装了一个低版本,需要升级,那就是要先删除旧版本了,nodejs应该是向下兼容的,所以我就没有去研究可能闲着蛋疼才会去研究如果保存多个版本nodejs,当然在新版中可能会存在部分旧的功能废除而造成异常,虽然一般来说升级利大于弊,不过还是要考虑老项目环境是否要升级!如果你是闲着蛋疼的人,必有理由说服我,请在下方留言。差点跑题,删除命令简直是太简单了。

sudo yum remove nodejs

然后按提示输入y,回车后很快就删了。一切删除操作都是令人兴奋的。。。

其实,我在安装过程中远没有那么轻松,否则也不会折腾几天了,一个是版本错误,一个是Python升级。版本问题,后来差了很多资料才发现,原来是yum缓存问题导致。如果遇到和我类似的问题,请尝试以下命令:

rm -f /etc/yum.repos.d/nodesource-el.repo
yum clean all
yum -y remove nodejs
yum -y install nodejs

汇总下本文参阅的相关文章:

  1. Nodejs官方文档,通过包管理安装Nodejs
  2. Centos下手动安装Nodejs的方法
  3. 无法在Yum仓下安装正确的Nodejs版本(和刚才示例的代码类似,都是清除缓存,不过对我无效)
  4. CentOS下使用nodejs7.x的包进行安装却安装成了6.9.5(针对我的有效方案)
  5. 如何通过Linux命令删除Nodejs

所以我呢,其实就是应该遇到版本不对的情况就尝试清除缓存,再用官方命令进行安装就好了~

我想既然是Yum仓库缓存的问题,除了Nodejs,别的包也许也会有类似情况吧,如果也发现了选择了需要的版本后依然装的是旧版的,又和依赖没什么关系,就试试清除缓存吧 🙂