美文网首页
第二次作业整理

第二次作业整理

作者: joinwang | 来源:发表于2017-11-19 23:32 被阅读0次

    NodeJS实战--使用NodeJS实现前后端的联调

    180 sunxiaochuan 简书作者

    2017.11.19 23:11  打开App

    1510997059(1).jpg

    1. 将原项目迁移进入KOA2,并顺利通过index/index路由进行访问

    1.1 新建项目,配置项目结构所需的一系列的文件,使 index/index 可以打开

    将原项目 Praisethumb 拖拽到 sublime 编辑器中,新建一个koatest 文件夹

    打开小黑窗进入koatest 文件夹中

    cd Desktop

    cd koatest

    初始化项目

    npm init

    找寻 koa2 包教程,www.npmjs.com -> 搜索框输入koa2

    参考链接:https://www.npmjs.com/package/koa2

    开始配置koa2 -> 在小黑窗中安装koa2包

    npm install koa@next

    在koatest文件夹中新建文件 app.js, copy 如下代码

    const Koa = require('koa');

    const app = new Koa();

    // response

    app.use(ctx => {

      ctx.body = 'Hello Koa';

    });

    app.listen(3000);

    由于使用的是 ES6 所以将 require 引用 改为 import name from 'name'

    import Koa from 'koa';

    const app = new Koa();

    // response

    app.use(ctx => {

      ctx.body = 'Hello Koa';

    });

    app.listen(3000);

    此时在小黑窗中输入 node app.js 会报如下的错误,原因是为将ES6 代码编译为 可解析的 ES5

    4Y4V)NM0S7MLXBOBDM9NH2G.png

    开始安装编译依赖包 babel ,在此阐述一下 -dev 的问题,安装包时加 -dev 说明其只在开发环境下使用而上线时有命令可以直接将其去掉, babel 便是此类的安装包

    npm install babel-preset-es2015 --save-dev

    http://www.ruanyifeng.com/blog/2016/01/babel.html?20170213113809 阮一峰先生的 babel 教程

    在项目中新建 .babelrc ,babel 的配置文件 输入如下代码

    {

    "presets":[

        "es2015",

        "stage-0"

    ],

    "plugins":[]

    }

    安装babel 编译所需的其他包,stage-0 是 ES7 的一个阶段,是为了使 babel 可以识别后面写的 async 和 await

    cnpm install babel-preset-stage-0 --save-dev

    http://www.jianshu.com/p/c84d52828e45 async 和 await 详解

    编译 app.js 文件,并启动服务

    babel app.js -o app_o.js

    node app_o.js

    启动时报了如下错误,猜测是由于哪个包装的时候未装完整便退出了,所以将文件夹中的 node_modules 文件删除 再重新安装一遍项目所需的包 cnpm install 再次启动 node app_o.js 时便成功了

    1511065654(1).jpg

    启动成功后,在浏览器中输入 http://localhost:3000/ 显示为 Hello Koa证明一切都没问题了

    14.此时需要配置路由 为 /index/index ,使用 koa-simple-router 包

    https://www.npmjs.com/package/koa-simple-router 包的网址

    npm install koa-simple-router --save

    在 app.js 文件的代码改为如下所示的

    import Koa from 'koa';

    import router from 'koa-simple-router';

    const app = new Koa();

    app.use(router(_ => {

      _.get('/', (ctx, next) => {

        ctx.body = 'hello'

      })

      _.post('/name/:id', (ctx, next) => {

    // ...

      })

    })

    app.listen(3000);

    为了使项目变得更加的分化明了

    新建一个 midddleware 文件夹放项目的容错文件

    新建一个 config 文件夹放项目的配置文件

    新建一个 controller 文件夹放项目的路由配置文件

    新建一个向后端请求数据的文件夹 models

    新建一个放 html 页面的文件夹 views

    再加一个放静态文件 .css .js 的文件夹 public

    文件创建解构如下

    public -> css -> index.css

    public -> scripts -> index.js

    controller -> initController.js

    controller -> indexController.js

    编辑 initController.js 文件,将 app.js 文件中的路由配置方法代码拿到 该文件中略加修改,最后讲方法导出

    import index from './indexController';//引入 indexController 文件导出的方法

    const controllerInit = {

    //配置初始化函数

    init(app, router) {

        app.use(router(_ => {

            _.get('/index/index', index.index())

        }))

    }

    }

    //导出初始化方法,使其全局可用

    export default controllerInit;

    编辑 indexController.js 文件,并导出该方法给 initController.js 文件使用

    const indexController ={

    index(){

        return async(ctx,next)=>{

            ctx.body = await ctx.render('index.html',function(){

                title:'大拇指点赞'

            })

        } 

    }

    }

    // 导出该方法给 initController.js 文件使用

    export default indexController;

    在 app.js 文件中引用 initController 并执行

    import initController from './controller/initController';

    initController.init(app,router);

    由于在controller js 文件中都使用了 koa-swig 框架中的 rander 函数,而且需要这个框架在静态文件中引用文件,所以要引用 koa-swig

    https://www.npmjs.com/package/koa-swig 包的网址

    npm install koa-swig --save

    https://www.cnblogs.com/elementstorm/p/3142644.html swig 使用指南

    在 swig 使用指南中找到 模板继承模块,在项目中的 views 文件夹中新建 layout.html 和 index.html 将如下代码 copy 进去

    layout.html

    <!doctype html>

    <html>

    <head>

    <meta charset="utf-8">

    <title>{% block title %}My Site{% endblock %}</title>

    {% block head %}

    {% endblock %}

    </head>

    <body>

    {% block content %}{% endblock %}

    </body>

    </html>

    index.html

    {% extends 'layout.html' %}

    {% block title %}My Page{% endblock %}

    {% block head %}

    {% parent %}

    <link rel="stylesheet" href="../css/index.css">

    <script src="../scripts/index.js"></script>

    {% endblock %}

    {% block content %}

    <p>This is just an awesome page.</p>

    {% endblock %}

    以为用的是 koa2 所以用 swig 时还要引用 co 模块,该模块无需安装,在 app.js 文件中输入如下代码

    import co from 'co';

    app.context.render = co.wrap(render({

      root: __dirname + 'views',

      autoescape: true,

      cache: 'memory', // disable, set to false

      ext: 'html',

      writeBody: false

    }));

    html 文件中相互引用路径时需要安装 koa-static 来配置

    npm install koa-static --save

    在 app.js 文件中输入如下代码

    import serve from 'koa-static';

    app.use(serve(__dirname + '/test/fixtures'));

    在 config 文件夹中新建 config.js 文件

    http://es6.ruanyifeng.com/?search=map&x=0&y=0#docs/set-map ES

    6-Map 方法详述

    安装 path

    npm  install path --save-dev

    编辑 config.js 文件,将方法导出 app.js 会使用

    import path from 'path';

    const CONFIG = new Map();

    CONFIG.set('port',3000);

    CONFIG.set('staticDir',path.join(__dirname,'..','public'));

    CONFIG.set('viewDir',path.join(__dirname,'..','views'));

    export default CONFIG;

    在 app.js 文件中引入 CONFIG 并修改配置路径

    import CONFIG from './config/config';

    initController.init(app,router);

    app.context.render = co.wrap(render({

    root: CONFIG.get('viewDir'),

    autoescape: true,

    cache: 'memory', // disable, set to false

    ext: 'html',

    writeBody: false

    }));

    app.use(serve(CONFIG.get('staticDir')));

    app.listen(CONFIG.get('port'));

    编译文件

    babel app.js -o app_o.js  //期间莫名其妙报了错,然后检查了下需要引用的包,看看 package.json 文件中是否存在没有的安装一遍,之后还是报错,便将 node_modules 文件夹删掉 在将所有的包重装了一遍 npm install 可以了

    进入 config 和 controller 文件夹中,将里面的 .js 文件后缀名改为 .es,再在命令行中进行编译

    cd config

    babel config.es -o config.js

    cd ..

    cd controller

    babel initController.es -o initController.js

    babel indexController.es -o indexController.js

    启动服务

    cd..

    node app_o.js

    此时报了如下的错误,

    1511073380(1).jpg

    原因是在 indexController 中用到了 async 和 await 但是并没有编译的很好,因为 babel 默认是不会编译较高级的函数的,所以需要装两个包使其支持

    cnpm install babel-register --save-dev

    cnpm install babel-polyfill --save-dev

    装好之后在 app.js 文件中引入

    import babel_co from 'babel-core/register';

    import babel_po from 'babel-pocyfill';

    再编译一遍文件

    babel app.js -o app_o.js

    cd controller

    babel indexcontroller

    babel indexController.es -o indexController.js

    运行服务 报错为如下图

    image.png

    在 app.js 文件中引入 CONFIG

    import CONFIG from './config/config';

    编译修改过的文件

    babel app.js -o app_o.js

    cd config

    babel config.es -o config.js

    切记每次修改了 .es 都需要在重新编译一遍

    运行服务

    node app_o.js

    在浏览器打开页面 http://localhost:3000/index/index 展示如下图所示 便表示成功了接下来就是第二步将原项目迁移过来

    1511076432(1).jpg

    1.2 将之前所做的 项目 Praisethumb 中的文件配置到新项目中

    1.将之前的 css 样式 放到 koatest 项目中的 index.css 文件中

    {

    margin: 0;

    padding: 0;

    }

    body {

    background-color: #b1c8ac;

    padding: 50px;

    position: relative;

    height: 600px;

    }

    .a {

    position: absolute;

    left: 0;

    right: 0;

    top: 0;

    bottom: 0;

    margin: auto;

    background-color: #ffcaaa;

    width: 226px;

    height: 360px;

    border-radius: 38px 0 0 38px;

    border: 1px solid #95755e;

    border-width: 1px 0 1px 1px;

    }

    .a:before {

    content: " ";

    display: block;

    position: absolute;

    width: 246px;

    height: 240px;

    border-top: 1px solid #95755e;

    bottom: 0;

    top: 0;

    right: 0;

    left: 0;

    margin: auto auto auto -224px;

    background-color: #ffcaaa;

    }

    .a:after {

    content: " ";

    display: block;

    position: absolute;

    width: 150px;

    height: 90px;

    border: 1px solid #95755e;

    border-width: 1px 1px 0 0;

    border-radius: 0 45px 45px 0;

    bottom: 0;

    top: 0;

    right: 0;

    left: 0;

    margin: 0 auto auto 30px;

    background-color: #ffcaaa;

    transform: rotate(-65deg);

    transform-origin: left top;

    box-shadow: -4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset, -80px 2px 10px 1px #ffcaaa inset, -100px 2px 20px 0px #efb38f inset;

    transition: all .3s;

    }

    .b {

    width: 180px;

    height: 90px;

    border: 1px solid #95755e;

    position: absolute;

    border-radius: 45px;

    box-shadow: -4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset;

    background-color: #ffcaaa;

    z-index: -1;

    left: 0;

    right: 0;

    top: 0;

    bottom: 0;

    margin: auto -90px -1px auto;

    -webkit-box-reflect: above 178px;

    box-reflect: above 178px;

    }

    .b:before {

    content: " ";

    display: block;

    position: absolute;

    width: 180px;

    height: 90px;

    border: 1px solid #95755e;

    right: 0;

    top: -91px;

    border-radius: 45px;

    border-width: 1px 1px 1px 0;

    box-shadow: -4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset;

    background-color: #ffcaaa;

    }

    .c {

    width: 180px;

    height: 90px;

    border: 1px solid #95755e;

    position: absolute;

    border-radius: 45px;

    box-shadow: -4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset;

    background-color: #ffcaaa;

    z-index: -1;

    left: 0;

    right: 0;

    top: 0;

    bottom: 0;

    margin: 90px -90px -1px auto;

    /-webkit-box-reflect: above 178px;

    box-reflect: above 178px;/

    }

    .c:before {

    content: " ";

    display: block;

    position: absolute;

    width: 180px;

    height: 90px;

    border: 1px solid #95755e;

    right: 0;

    top: -91px;

    border-radius: 45px;

    border-width: 1px 1px 1px 0;

    box-shadow: -4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset;

    background-color: #ffcaaa;

    }

    /.b:after{content: " ";display: block;position: absolute;width: 180px;height:90px;border: 1px solid #95755e;right: 0;top:182px;border-radius: 45px;border-width: 1px 1px 1px 0;box-shadow:-4px -4px 22px 2px #ffcaaa inset, -4px 4px 30px 2px #ffcaaa inset, -25px 2px 10px 3px #fce0d4 inset;background-color: #ffcaaa;}/

    .hide {

    opacity: 0;

    color: red;

    font-size: 60px;

    position: absolute;

    right: 60px;

    top: 150px;

    }

    .num {

    animation: myani .6s ease;

    -moz-animation: myani .6s ease;

    -webkit-animation: myani .6s ease;

    -o-animation: myani .6s ease;

    }

    @keyframes myani() {

    form {

    opacity: 0;

    top: 150px;

    }

    to {

    opacity: 1;

    top: 50px;

    }

    }

    @-moz-keyframes myani {

    form {

    opacity: 0;

    top: 150px;

    }

    to {

    opacity: 1;

    top: 50px;

    }

    }

    @-webkit-keyframes myani {

    form {

    opacity: 0;

    top: 150px;

    }

    to {

    opacity: 1;

    top: 50px;

    }

    }

    @-o-keyframes myani {

    form {

    opacity: 0;

    top: 150px;

    }

    to {

    opacity: 1;

    top: 50px;

    }

    }

    :root {

    --green: #b1c8ac;

    }

    body {

    background-color: var(--green);

    }

    将 html 内容也拿过来

    index.html

    {% extends 'layout.html' %}

    {% block title %}My Page{% endblock %}

    {% block head %}

    {% parent %}

    <link rel="stylesheet" href="../css/index.css">

    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    <script src="https://cdn.bootcss.com/systemjs/0.20.19/system.js"></script>

    <script src="../scripts/index.js"></script>

    {% endblock %}

    {% block content %}

    <div id="thumb">

    <div class="a">

    <div class="b"></div>

    <div class="c"></div>

    </div>

    </div>

    <span class="hide" id="animation">+1</span>

    <script type="text/javascript">

    SystemJS.config({

    //使用的 js 文件的文件夹路径

    baseURL: '/scripts'

    });

    //使用的 js 文件名称

    SystemJS.import('index-es.js').then(function(m) {

    $.extend({

    //将自己写的函数挂载到 jq 上称为一个插件

    thumb:m.default.Thumb

    })

    //回调函数

    callBack();

    });

    //定义回调函数

    function callBack() {

    //为页面元素添加方法

    var f = new $.thumb(0,$('#thumb'));

    f.clickAction();

    }

    </script>

    {% endblock %}

    拿 js

    window.add = function (num) {

    return num + 1;

    }

    将编译过的 点击小手子类继承父类的 js文件(index.es.js)复制到 项目的 scripts 文件夹下

    index-es.js

    'use strict';

    Object.defineProperty(exports, "__esModule", {

    value: true

    });

    var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

    function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

    function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.proto = superClass; }

    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

    var PraiseButton = function () {

    function PraiseButton(num, element) {

    _classCallCheck(this, PraiseButton);

    this.num = num;

    this.element = element;

    _createClass(PraiseButton, [{

    key: 'clickAction',

    value: function clickAction() {

    var _this = this;

    this.element.click(function () {

    if (_this.num < 10) {

    _this.element.css('-webkit-filter', 'grayscale(0)');

    $('#animation').addClass('num');

    _this.num = add(_this.num);

    setTimeout(function () {

    $('#animation').removeClass('num');

    }, 1000);

    } else {

    _this.element.css('-webkit-filter', 'grayscale(1)');

    _this.num = 0;

    }

    console.log(_this.num);

    });

    }

    }]);

    return PraiseButton;

    }();

    var Thumb = function (_PraiseButton) {

    _inherits(Thumb, _PraiseButton);

    function Thumb(num, element) {

    _classCallCheck(this, Thumb);

    return _possibleConstructorReturn(this, (Thumb.proto || Object.getPrototypeOf(Thumb)).call(this, num, element));

    }

    return Thumb;

    }(PraiseButton);

    exports.default = { Thumb: Thumb

    // let f = new Thumb(0,$('#thumb'));

    // f.clickAction();

    };

    重启服务

    node app_o.js

    刷新 http://localhost:3000/index/index 页面,发现项目已经移植成功

    2. 使用 PHP + MySQL 完成点赞借口,实现用户点击一次更新数据库点赞次数

    在项目中新建一个 praise.php 文件

    编辑文件

    <?php

    //用php的面向对象来写

    /**

    * 新建一个类

    */

    class Conmysql

    {

    //定义所需的变量

    //public关键字表示属性或方法是公开可见的

    public $servername;

    public $username;

    public $password;

    public $dbname;

    }

    ?>

    用 XAMPP 启动 Apache 和 MySQL

    1511081397(1).jpg

    在浏览器中打开 http://localhost/phpmyadmin/ 页面

    在左侧操作栏中点击【新建】

    输入新数据库的名字 praise 点击【创建】

    新建数据表 text 2

    字段分别为 id 和 num

    id 需要设置为主键

    点击保存

    具体设计如下图所示

    image.png

    在 text 数据表中手动添加一条数据

    点击数据表【text】

    点击 【SQL】

    点击【INSERT】

    将输入域的值修改为如下所示,点击【执行】

    INSERT INTO `text`(`id`, `num`) VALUES (1,0)

    在 php 文件中编辑

    <?php

    //用php的面向对象来写

    /**

    * 新建一个类

    */

    class Conmysql

    {

    //定义所需的变量

    //public关键字表示属性或方法是公开可见的

    public $servername;

    public $username;

    public $password;

    public $dbname;

    public $con = null;

    //添加构造方法

    public function __construct($servername,$username,$password,$dbname){

        $this->servername = $servername;

        $this->username = $username;

        $this->password = $password;

        $this->dbname = $dbname;

    }

    //创建数据库链接方法

    //参考网址:http://www.runoob.com/php/php-mysql-connect.html -> 实例 (PDO)

    public function getConnection(){

        //这里用的是 PDO 方法

        try {

            $dsn = "mysql:host=$this->servername;dbname=$this->dbname";

                $this->con = new PDO($dsn, $this->username, $this->password);

                //echo "连接成功";

            }

        catch(PDOException $e)

            {

                echo $e->getMessage();

            }

    }

    //更新数据的方法

    public function updateDate($sql){

        //如果未连接的话就链接到数据库

        if($this->con == null){

            $this->getConnection();

        }

        //执行sql

        //参考链接:http://www.runoob.com/php/php-mysql-insert.html -> 实例 (PDO)

        $res=$this->con->exec($sql);

        //关闭链接

        $this->closeCon();

    }

    //关闭链接的方法

    public function closeCon(){

        $this->con = null;

    }

    }

    /**

    * 创建子类

    */

    class realConn extends Conmysql

    {

    //继承父类的构造方法

    public function __construct($servername,$username,$password,$dbname){

        parent::__construct($servername,$username,$password,$dbname);

    }

    //真正执行 sql 的方法

    public function updateRealDate(){

        $sql = "UPDATE text SET num=num+1 WHERE id=1";

        $this->updateDate($sql);

    }

    }

    //将子类实例化执行方法

    $praiseCon = new realConn('localhost','root','','praise');

    $praiseCon->updateRealDate();

    ?>

    将 praise.php 文件复制到 C:\xampp\htdocs 文件夹下,在浏览器中打开 http://localhost/praise.php,再查看 text 数据表中会发现 num 的值为 1 ,刷 php 页面一次值便会加 1,至此点赞接口便完成了

    3. 使用KOA2+ES6封装PHP点赞接口,并建立路由

    1.在 koatest 项目文件夹的 models 文件夹中新建一个 indexmodel.js 文件

    编辑 indexmodel.js 文件

    import rpA from 'request-promise';

    class indexModel {

      constructor(ctx) {

        this.ctx = ctx;

    }

    //为了实现数据库更新建立方法 传数据的接口

    updateNum() {

        //在这里 return 一个 promise 模块传入 initController.js 再在indexController.js 中调用需要用到一个模块 request-promise  参考网址:https://www.npmjs.com/package/request-promise

      // 获取文件

        const options = {

            uri: 'http://localhost/praise.php',

            method:'GET'

        };

        return new Promise((resolve,reject)=>{

            rpA(options).then(function(result){

                const info = JSON.parse(result);

                if(info){

                    resolve({data:info.result});

                }else{

                    reject({});

                    }

                })

            })

        }

    }

    //将该方法导出,  indexController.js 文件要用到

    export default indexModel;

    由于 updateNum 方法中需要用到 request-promise 模块 所以需要安装两个包

    参考链接:https://www.npmjs.com/package/request-promise

    npm install --save request

    npm install --save request-promise

    编辑 indexController.js 文件

    indexController 对象中增加一个 提交数据的方法

    //引入所需方法的文件

    import indexModel from '../models/indexModel';

    update(){

        return async(ctx,next)=>{

            const indexM = new indexModel(ctx);

            ctx.body = await indexM.updateNum();

        }

    }

    编辑 initController.js 文件

    将 indexController 提交数据的方法注册到 一个新的路由上

    _.get('/index/update', index.update());

    babel 编译文件

    将 indexmodel.js 重命名为 indexmodel.es

    cd models

    babel indexmodel.es -o indexmodel.js

    cd ..

    cd controller

    babel  indexController.es -o indexController.js

    babel initController.es -o initController.js

    此时运行服务会发现小手点击并没有与服务器关联起来,此时需要用 axios 模块来使其连接到 koa2 点赞接口上

    4. 将用户点击事件通过 axios 链接到 KOA2 点赞接口

    在 koatest 项目中的 scripts 文件夹中新建 index.es 文件,并将 praisethumb 项目中的 scripts -> index.js 文件代码复制过来

    class PraiseButton{

    constructor(num,element){

        this.num = num;

        this.element = element;

    }

    clickAction(){

        this.element.click(()=>{

            if(this.num < 10){

                this.element.css('-webkit-filter','grayscale(0)');

                $('#animation').addClass('num');

                this.num = add(this.num);

                setTimeout(function () {

                    $('#animation').removeClass('num');

                },1000);

            }else{

                this.element.css('-webkit-filter','grayscale(1)');

                this.num = 0;

            }

            console.log(this.num);

        })

    }

    }

    class Thumb extends PraiseButton{

        constructor(num,element){

            super(num,element)

        }

    }

    export default{Thumb}

    // let  f = new Thumb(0,$('#thumb'));

    // f.clickAction();

    编辑 index.es 文件,这里是要用 axios 模块来使其连接到 koa2 点赞接口上

    参考链接:https://www.npmjs.com/package/axios

    这里有三种引用的方法:npm 装包,浏览器装包,cdn,这里我们用的是 cdn 方法,将如下代码 copy 至 index.html 文件中

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    将如下代码 copy 至 index.es -> this.element.click 点击事件中

    axios.get('/index/update')

      .then(function (response) {

        console.log(response);

      })

      .catch(function (error) {

        console.log(error);

      });

    编修改过的文件 index.es

    cd public\scripts\

    babel index.es -o index-es.js

    运行服务

    cd ../..

    node app_o.js

    点击时页面 http://localhost:3000/index/index 报如下图所示的错误

    image.png

    编辑 praise.php 文件中的 updateDate 方法

    //更新数据的方法

    public function updateDate($sql){

        //如果未连接的话就链接到数据库

        if($this->con == null){

            $this->getConnection();

        }

        //向前台输出 json 格式的数据

        header('content-type:application/json;charset=utf8');

        //执行sql

        //参考链接:http://www.runoob.com/php/php-mysql-insert.html -> 实例 (PDO)

        $res=$this->con->exec($sql);

        //执行之后 输出返回的数据

        $arr = array('result'=>$res);

        echo json_encode($arr);

        //关闭链接

        $this->closeCon();

    }

    运行服务,发现又报了 404 ,排查之后发现是 index.es 文件中的 uodate 写成了 uodete ,诶,修改后 编译 ,再运行点击一下小手,数据库里面的 num 的值 +1 证明成功了

    需要注意的是 php返回的数据必须严格是 json 格式的 不然前台 .js 文件 (未编译:indexmodel.es 已编译 indexmodel.js)中用到的 JSON.parse(result); 会一直报错导致页面崩溃

    cd public\scripts\

    babel index.es -o index-es.js

    cd../..

    node app_o.js

    5. 对用户连续点击事件进行稀释

    稀释所用的方法就是 setTimeout

    编辑 index.es 文件

    let f = '';

    class PraiseButton{

    constructor(num,element){

        this.num = num;

        this.element = element;

    }

    clickAction(){

        this.element.click(()=>{

        //判断事件是否已经存在,如果存在便会将其清除掉,所以点击只会执行最后一次点击的那次事件

        if(f){

        clearTimeout(f);

        }

            f = setTimeout(()=>{

                if(this.num < 10){

                    this.element.css('-webkit-filter','grayscale(0)');

                    $('#animation').addClass('num');

                    this.num = add(this.num);

                    setTimeout(function () {

                        $('#animation').removeClass('num');

                    },1000);

                    axios.get('/index/update')

                      .then(function (response) {

                        console.log(response);

                      })

                      .catch(function (error) {

                        console.log(error);

                      });

                }else{

                    this.element.css('-webkit-filter','grayscale(1)');

                    this.num = 0;

                }

                console.log(this.num);

            },800)

           

        })

    }

    }

    class Thumb extends PraiseButton{

    constructor(num,element){

            super(num,element)

        }

    }

    export default{Thumb}

    // let  f = new Thumb(0,$('#thumb'));

    // f.clickAction();

    编译文件

    cd public\scripts\

    babel index.es -o index-es.js

    运行服务,稀释成功

    node app_o.js

    6. 完成点赞接口的自动化测试、点赞+1功能的自动化测试、真实页面点击自动化测试

    1. 点赞+1功能的自动化测试

    安装 karma

    cnpm install karma --save-dev

    安装断言库、核心、chrome 启动器

    cnpm install karma-jasmine jasmine-core karma-chrome-launcher --save-dev

    安装无界面浏览器、无界面浏览器启动器

    cnpm install phantomjs --save-dev

    cnpm install karma-phantomjs-launcher --save-dev

    karma 初始化生成配置文件 karma.conf.js

    karma init

    jasmine

    no

    PhantomJS

    yes

    5.在项目中新建一个 test 文件夹,在该文件夹下做三大测试

    将 praisethumb 项目文件夹的中 index.spce.js 文件复制到 test 文件夹下

    编辑 karma.conf.js 文件

    files: [

        'test/index.spec.js',

        'public/scripts/index.js'

    ],

    singleRun: true,

    启动测试,运行成功

    karma start

    2. 点赞接口的自动化测试

    1.先安装 mocha

    cnpm install mocha --save-dev

    安装 supertest

    cnpm install supertest --save-dev

    在 test 文件夹下新建一个 server.js 文件

    编辑 sever.js 文件

    参考链接:https://www.npmjs.com/package/supertest

    import requestsuper from 'supertest';

    //这里引用的是 app_0.js 文件拿到 app,所以需要在 app.js 文件中将其导出,然后再将 app.js 文件编译为 app_o.js 文件

    import app from '../app_o.js';

    //先定义一个拿到端口的方法

    function request(){

        return requestsuper(app.listen());

    }

    describe('测试路由', function() {

      it('点赞', function(done) {

        request()

          .get('/index/update')

          .expect(200)

          .end(function(err,res){

            if(res.data==1)return done(err);

            done();

          })

      });

    });

    修改 app.js 文件

    export default app;

    编译文件

    babel app.js -o app_o.js

    cd test\

    babel server.js -o server-es.js

    执行 server-es.js 文件

    cd ..

    mocha test\server-es.js

    此时报如下图所示的错误

    image.png

    将 mocha 安装至全局

    cnpm install mocha -g

    执行测试

    mocha test\server-es.js

    执行成功

    image.png

    3. 真实页面点击自动化测试

    1.安装 selenium-webdriver

    参考链接:https://www.npmjs.com/package/selenium-webdriver

    cnpm install selenium-webdriver

    2.下面火狐浏览器所需的相应组件

    参考链接:https://github.com/mozilla/geckodriver/releases/ 找到与当前设备匹配的一款点击下载 我的是 win64

    将下载好的压缩包解压至 koatest 项目文件夹中,删除压缩包

    再安装两个包

    cnpm install selenium-standalone --save

    cnpm install protractor --save

    test 文件夹下新建 e2e.js 文件

    编辑 e2e.js 文件

    参考链接:https://www.npmjs.com/package/selenium-webdriver -> Usage

    const {Builder, By, Key, until} = require('selenium-webdriver');

    let driver = new Builder()

        .forBrowser('firefox')

        .build();

    //设置地址

    driver.get('http://localhost:3000/index/index');

    driver.findElement(By.id('thumb')).click();

    const _animation = driver.findElement(By.id('animation'))

    driver.wait(_animation.isDisplayed(), 1000);

    // driver.quit(); //为了看到效果将关闭浏览器的行为暂时注释掉

    执行测试脚本 e2e.js 文件

    node test\e2e.js

    此时会发现浏览器打开页面后,页面并不能加载出来原因是这个 koatest 项目此时并没有处于运行状态,所以需要新建一个命令行窗口中执行项目运行操作

    image.png

    在新窗口中输入命令

    cd Desktop

    cd koatest

    node app_o.js

    此时再在之前的命令行窗口中执行测试脚本 e2e.js 文件

    node test\e2e.js

    整个实战到此结束。

    2017.11.19 23.11 我今天生日哟,刚了一天!奋发图强 !

    相关文章

      网友评论

          本文标题:第二次作业整理

          本文链接:https://www.haomeiwen.com/subject/wikmvxtx.html