使用Nodejs写一个英雄联盟英雄故事网站

12-01
评论
字数统计:7257(字)
本文介绍用nodejs写一个英雄联盟故事合集的简单网站, 后台服务使用express、模板引擎使用nunjucks,接口来源均为英雄联盟官网,只供学习使用。

前言

  • 纯属无聊,写一个英雄联盟故事网站小demo,设计方案:展示英雄列表,点击英雄跳转至英雄故事。在线展示
  • 英雄联盟官网的一些接口可以直接调用,本文主要用到以下两个

https://yz.lol.qq.com/v1/zh_cn/search/index.json

https://yz.lol.qq.com/v1/zh_cn/champions/:sign/index.json

  • 使用express做后台服务,nunjucks做模板引擎,简单明了。
  • 推荐一个库request-promise,此库可以直接await request结果,无需自己封装。
  • 源码至github

英雄联盟api

拳头并没有直接开放api,用到的两个api是国服官网的api,可以直接调用。不保证长期有效。

网站用到的图片图标全部来自官方,纯玩。

开始

yarn add express nunjucks request request-promise
# or
npm install express nunjucks request request-promise

目录结构

|-- lol
    |-- node_modules
    |-- public
    |   |-- favicon.ico
    |   |-- style.css
    |-- router
    |   |-- home.js
    |   |-- hero.js
    |-- views
    |   |-- home.njk
    |   |-- hero.njk
    |-- app.js
    |-- package.json
    |-- yarn.lock or package-lock.json

搭服务

先起服务

express起服务是非常简单、快的,几行代码一个服务。

// ./app.js
var express = require("express");
var app = express();

app.get("/", (req, res) => {
  res.send("lol");
});

app.listen(8012);

""

添加模板引擎

ejs、nunjucks、jede大同小异,都可以用。

// ./app.js
var express = require("express");
var app = express();
var nunjucks = require("nunjucks");

/** 启用nunjucks 并设置views文件夹为页面文件 */
/** mkdir ./views */
nunjucks.configure(path.join(__dirname, "views"), {
  autoescape: true,
  express: app,
});

/** 设置静态资源目录 */
app.use(express.static(path.join(__dirname, "public")));

app.get("/", (req, res) => {
  res.send("lol");
});

app.listen(8012, () => {
  console.log(`lol serve start ok! port:${8012}`);
});

路由

路由文件夹

因为设计方案是首页展示英雄列表,点击英雄图片进入展示英雄故事,那么至少需要两个路由 //:hero

创建/router目录,创建/router/home.js/router/hero.js文件

express配置路由

// ./app.js
// app.get("/", (req, res) => {
//   res.send("lol");
// });

app.get("/", require("./router/home"));
app.get("/:hero", require("./router/hero"));

页面

/views下创建/views/base.njk/views/home.njk/views/hero.njk

这里使用njk作为后缀,也可以用html,具体配置见nunjucks

njk模板语法比较简单,详情见nunjucks语法

模板页

base.njk为模板页,引用一些资源。

使用bootstrap来排版吧

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>英雄联盟 - 英雄故事</title>
    <link rel="icon" href="/favicon.ico" type="image/x-icon" />
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css"/>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/style.css"/>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

首页(英雄列表页)

// ./router/home.js
const rq = require("request-promise");

module.exports = async function (req, res) {
  /** 接口直接返回了英雄列表,还有版本信息、更新日期等,此处直接返回列表给前端即可 */
  const result = await rq(
    "https://yz.lol.qq.com/v1/zh_cn/search/index.json"
  ).then((res) => JSON.parse(res));
  res.render("home.njk", { list: result.champions });
};

// ./views/home.njk
{% extends "base.njk" %}
{% block content %}
    <div class="list-block">
        <div class="container">
            <div class="header">
                <h2>英雄联盟人物故事</h2>
                <div class="search">
                    <input type="email" class="form-control" id="searchInput" aria-describedby="emailHelp" value="{{queryVal}}"/>
                    <button type="button" class="btn btn-primary" onclick="javascript: window.location.href = '/'+$(`#searchInput`).val()+''">
                        搜索
                    </button>
                </div>
            </div>
            <div class="row row-cols-1 row-cols-sm-2 row-cols-md-4">
                {% for item in list %}
                    <div class="col">
                        <div class="card" onclick="window.open('/{{item.slug}}')">
                            <img src="{{item.image.uri}}" class="card-img-top" alt="..."/>
                            <div class="card-body">
                                <h5 class="card-title">{{ item.name }}</h5>
                                <p class="card-text">
                                    {{ item.slug }}
                                </p>
                                <p class="card-text">
                                    {{ item["release-date"] }}
                                </p>
                            </div>
                        </div>
                    </div>
                {% else %}
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}

故事页

// ./router/hero.js
const rq = require("request-promise");

module.exports = async function (req, res) {
  const hero = req.params.hero;
  /** 该接口传入英雄名,注意:这个英雄名是通过英雄列表获取的字段为'sign',并不是name */
  /** 接口会将该英雄所有信息全部返回,此demo只取英雄故事,所以其他功能自行扩展 */
  const result = await rq(
    `https://yz.lol.qq.com/v1/zh_cn/champions/${hero}/index.json`
  ).then((res) => JSON.parse(res));

  const champion = result.champion;
  res.render("hero.njk", {
    info: {
      name: champion.name,
      nickname: champion.title,
      img: champion.image.uri,
      fullDesc: champion.biography.full,
      gameUri: champion["game-info-url"],
    },
  });
};

// ./views/hero.njk
{% extends "base.njk" %}
{% block content %}
    <div class="info-block">
        <div class="info-header">
            <img class="background" src="https://game.gtimg.cn/images/lol/universe/v1/assets/images/vastaya-journal-long.jpg" alt=""/>
            <span class="info-name">{{info.nickname}}
                :
                {{info.name}}</span>
            <img src="https://game.gtimg.cn/images/lol/universe/images/t1HeaderDivider.png" alt="" srcset=""/>
            <a href="{{info.gameUri}}">游戏信息</a>
        </div>
        <div class="info-body">
            <div class="desc">
                {{info.fullDesc | replace("<p>", "") | replace("</p>", "")}}
            </div>
        </div>
    </div>
{% endblock %}

效果

""

""

完成

功能比较简单,适合初学者学习,如有问题可以留言。

页面做了简单的展示,如需扩展可自行加功能,英雄联盟官网可以继续再挖掘一些接口。

代码存放在github,有兴趣的同学可以玩一玩。

本文链接:https://blog.crazylei.com/art/1b81ffd0
版权声明: 本博客所有文章除特别声明外,均采用CC BY 4.0 CN协议 许可协议。转载请注明出处!

评论

正在加载评论...

©2022 Crazylei Bolg沪ICP备20001821号