原文鏈接:http://www.reibang.com/p/2a9367afe9e7
1510997059(1).jpg
1. 將原項(xiàng)目遷移進(jìn)入KOA2篮绰,并順利通過(guò)index/index路由進(jìn)行訪問(wèn)
1.1 新建項(xiàng)目,配置項(xiàng)目結(jié)構(gòu)所需的一系列的文件缓升,使 index/index 可以打開
將原項(xiàng)目 Praisethumb 拖拽到 sublime 編輯器中,新建一個(gè)koatest 文件夾
打開小黑窗進(jìn)入koatest 文件夾中
cd Desktop
cd koatest
初始化項(xiàng)目
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);
此時(shí)在小黑窗中輸入 node app.js 會(huì)報(bào)如下的錯(cuò)誤,原因是為將ES6 代碼編譯為 可解析的 ES5
4Y4V)NM0S7MLXBOBDM9NH2G.png
開始安裝編譯依賴包 babel 橙弱,在此闡述一下 -dev 的問(wèn)題歧寺,安裝包時(shí)加 -dev 說(shuō)明其只在開發(fā)環(huán)境下使用而上線時(shí)有命令可以直接將其去掉, babel 便是此類的安裝包
npm install babel-preset-es2015 --save-dev
http://www.ruanyifeng.com/blog/2016/01/babel.html?20170213113809阮一峰先生的 babel 教程
在項(xiàng)目中新建 .babelrc 棘脐,babel 的配置文件 輸入如下代碼
{
"presets":[
"es2015",
"stage-0"
],
"plugins":[]
}
安裝babel 編譯所需的其他包斜筐,stage-0 是 ES7 的一個(gè)階段,是為了使 babel 可以識(shí)別后面寫的 async 和 await
cnpm install babel-preset-stage-0 --save-dev
http://www.reibang.com/p/c84d52828e45async 和 await 詳解
編譯 app.js 文件蛀缝,并啟動(dòng)服務(wù)
babel app.js -o app_o.js
node app_o.js
啟動(dòng)時(shí)報(bào)了如下錯(cuò)誤顷链,猜測(cè)是由于哪個(gè)包裝的時(shí)候未裝完整便退出了,所以將文件夾中的 node_modules 文件刪除? 再重新安裝一遍項(xiàng)目所需的包 cnpm install? 再次啟動(dòng) node app_o.js 時(shí)便成功了
1511065654(1).jpg
啟動(dòng)成功后屈梁,在瀏覽器中輸入http://localhost:3000/顯示為 Hello Koa證明一切都沒問(wèn)題了
14.此時(shí)需要配置路由 為 /index/index 蕴潦,使用 koa-simple-router 包
https://www.npmjs.com/package/koa-simple-router包的網(wǎng)址
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);
為了使項(xiàng)目變得更加的分化明了
新建一個(gè) midddleware 文件夾放項(xiàng)目的容錯(cuò)文件
新建一個(gè) config 文件夾放項(xiàng)目的配置文件
新建一個(gè) controller 文件夾放項(xiàng)目的路由配置文件
新建一個(gè)向后端請(qǐng)求數(shù)據(jù)的文件夾 models
新建一個(gè)放 html 頁(yè)面的文件夾 views
再加一個(gè)放靜態(tài)文件 .css .js 的文件夾 public
文件創(chuàng)建解構(gòu)如下
public -> css -> index.css
public -> scripts -> index.js
controller -> initController.js
controller -> indexController.js
編輯 initController.js 文件,將 app.js 文件中的路由配置方法代碼拿到 該文件中略加修改俘闯,最后講方法導(dǎo)出
import index from './indexController';//引入 indexController 文件導(dǎo)出的方法
const controllerInit = {
//配置初始化函數(shù)
init(app, router) {
app.use(router(_ => {
_.get('/index/index', index.index())
}))
}
}
//導(dǎo)出初始化方法潭苞,使其全局可用
export default controllerInit;
編輯 indexController.js 文件,并導(dǎo)出該方法給 initController.js 文件使用
const indexController ={
index(){
return async(ctx,next)=>{
ctx.body = await ctx.render('index.html',function(){
title:'大拇指點(diǎn)贊'
})
}
}
}
// 導(dǎo)出該方法給 initController.js 文件使用
export default indexController;
在 app.js 文件中引用 initController 并執(zhí)行
import initController from './controller/initController';
initController.init(app,router);
由于在controller js 文件中都使用了 koa-swig 框架中的 rander 函數(shù)真朗,而且需要這個(gè)框架在靜態(tài)文件中引用文件此疹,所以要引用 koa-swig
https://www.npmjs.com/package/koa-swig包的網(wǎng)址
npm install koa-swig --save
https://www.cnblogs.com/elementstorm/p/3142644.htmlswig 使用指南
在 swig 使用指南中找到 模板繼承模塊,在項(xiàng)目中的 views 文件夾中新建 layout.html 和 index.html 將如下代碼 copy 進(jìn)去
layout.html
{% block title %}My Site{% endblock %}
{% block head %}
{% endblock %}
{% block content %}{% endblock %}
index.html
{% extends 'layout.html' %}
{% block title %}My Page{% endblock %}
{% block head %}
{% parent %}
{% endblock %}
{% block content %}
This is just an awesome page.
{% endblock %}
以為用的是 koa2 所以用 swig 時(shí)還要引用 co 模塊遮婶,該模塊無(wú)需安裝蝗碎,在 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 文件中相互引用路徑時(shí)需要安裝 koa-static 來(lái)配置
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-mapES
6-Map 方法詳述
安裝 path
npm? install path --save-dev
編輯 config.js 文件,將方法導(dǎo)出 app.js 會(huì)使用
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? //期間莫名其妙報(bào)了錯(cuò)旗扑,然后檢查了下需要引用的包蹦骑,看看 package.json 文件中是否存在沒有的安裝一遍,之后還是報(bào)錯(cuò)臀防,便將 node_modules 文件夾刪掉 在將所有的包重裝了一遍 npm install 可以了
進(jìn)入 config 和 controller 文件夾中眠菇,將里面的 .js 文件后綴名改為 .es边败,再在命令行中進(jìn)行編譯
cd config
babel config.es -o config.js
cd ..
cd controller
babel initController.es -o initController.js
babel indexController.es -o indexController.js
啟動(dòng)服務(wù)
cd..
node app_o.js
此時(shí)報(bào)了如下的錯(cuò)誤,
1511073380(1).jpg
原因是在 indexController 中用到了 async 和 await 但是并沒有編譯的很好捎废,因?yàn)?babel 默認(rèn)是不會(huì)編譯較高級(jí)的函數(shù)的笑窜,所以需要裝兩個(gè)包使其支持
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
運(yùn)行服務(wù) 報(bào)錯(cuò)為如下圖
image.png
在 app.js 文件中引入 CONFIG
import CONFIG from './config/config';
編譯修改過(guò)的文件
babel app.js -o app_o.js
cd config
babel config.es -o config.js
切記每次修改了 .es 都需要在重新編譯一遍
運(yùn)行服務(wù)
node app_o.js
在瀏覽器打開頁(yè)面http://localhost:3000/index/index展示如下圖所示? 便表示成功了接下來(lái)就是第二步將原項(xiàng)目遷移過(guò)來(lái)
1511076432(1).jpg
1.2 將之前所做的 項(xiàng)目 Praisethumb 中的文件配置到新項(xiàng)目中
1.將之前的 css 樣式 放到 koatest 項(xiàng)目中的 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 內(nèi)容也拿過(guò)來(lái)
index.html
{% extends 'layout.html' %}
{% block title %}My Page{% endblock %}
{% block head %}
{% parent %}
{% endblock %}
{% block content %}
+1
SystemJS.config({
//使用的 js 文件的文件夾路徑
baseURL: '/scripts'
});
//使用的 js 文件名稱
SystemJS.import('index-es.js').then(function(m) {
$.extend({
//將自己寫的函數(shù)掛載到 jq 上稱為一個(gè)插件
thumb:m.default.Thumb
})
//回調(diào)函數(shù)
callBack();
});
//定義回調(diào)函數(shù)
function callBack() {
//為頁(yè)面元素添加方法
var f = new $.thumb(0,$('#thumb'));
f.clickAction();
}
{% endblock %}
拿 js
window.add = function (num) {
return num + 1;
}
將編譯過(guò)的 點(diǎn)擊小手子類繼承父類的 js文件(index.es.js)復(fù)制到 項(xiàng)目的 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();
};
重啟服務(wù)
node app_o.js
刷新http://localhost:3000/index/index頁(yè)面,發(fā)現(xiàn)項(xiàng)目已經(jīng)移植成功
2. 使用 PHP + MySQL 完成點(diǎn)贊借口登疗,實(shí)現(xiàn)用戶點(diǎn)擊一次更新數(shù)據(jù)庫(kù)點(diǎn)贊次數(shù)
在項(xiàng)目中新建一個(gè) praise.php 文件
編輯文件
//用php的面向?qū)ο髞?lái)寫
/**
* 新建一個(gè)類
*/
class Conmysql
{
//定義所需的變量
//public關(guān)鍵字表示屬性或方法是公開可見的
public $servername;
public $username;
public $password;
public $dbname;
}
?>
用 XAMPP 啟動(dòng) Apache 和 MySQL
1511081397(1).jpg
在瀏覽器中打開http://localhost/phpmyadmin/頁(yè)面
在左側(cè)操作欄中點(diǎn)擊【新建】
輸入新數(shù)據(jù)庫(kù)的名字 praise 點(diǎn)擊【創(chuàng)建】
新建數(shù)據(jù)表 text 2
字段分別為? id 和 num
id 需要設(shè)置為主鍵
點(diǎn)擊保存
具體設(shè)計(jì)如下圖所示
image.png
在 text 數(shù)據(jù)表中手動(dòng)添加一條數(shù)據(jù)
點(diǎn)擊數(shù)據(jù)表【text】
點(diǎn)擊 【SQL】
點(diǎn)擊【INSERT】
將輸入域的值修改為如下所示排截,點(diǎn)擊【執(zhí)行】
INSERT INTO `text`(`id`, `num`) VALUES (1,0)
在 php 文件中編輯
//用php的面向?qū)ο髞?lái)寫
/**
* 新建一個(gè)類
*/
class Conmysql
{
//定義所需的變量
//public關(guān)鍵字表示屬性或方法是公開可見的
public $servername;
public $username;
public $password;
public $dbname;
public $con = null;
//添加構(gòu)造方法
public function __construct($servername,$username,$password,$dbname){
$this->servername = $servername;
$this->username = $username;
$this->password = $password;
$this->dbname = $dbname;
}
//創(chuàng)建數(shù)據(jù)庫(kù)鏈接方法
//參考網(wǎng)址:http://www.runoob.com/php/php-mysql-connect.html -> 實(shí)例 (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();
}
}
//更新數(shù)據(jù)的方法
public function updateDate($sql){
//如果未連接的話就鏈接到數(shù)據(jù)庫(kù)
if($this->con == null){
$this->getConnection();
}
//執(zhí)行sql
//參考鏈接:http://www.runoob.com/php/php-mysql-insert.html -> 實(shí)例 (PDO)
$res=$this->con->exec($sql);
//關(guān)閉鏈接
$this->closeCon();
}
//關(guān)閉鏈接的方法
public function closeCon(){
$this->con = null;
}
}
/**
* 創(chuàng)建子類
*/
class realConn extends Conmysql
{
//繼承父類的構(gòu)造方法
public function __construct($servername,$username,$password,$dbname){
parent::__construct($servername,$username,$password,$dbname);
}
//真正執(zhí)行 sql 的方法
public function updateRealDate(){
$sql = "UPDATE text SET num=num+1 WHERE id=1";
$this->updateDate($sql);
}
}
//將子類實(shí)例化執(zhí)行方法
$praiseCon = new realConn('localhost','root','','praise');
$praiseCon->updateRealDate();
?>
將 praise.php 文件復(fù)制到 C:\xampp\htdocs 文件夾下,在瀏覽器中打開http://localhost/praise.php辐益,再查看 text 數(shù)據(jù)表中會(huì)發(fā)現(xiàn) num 的值為 1 断傲,刷 php 頁(yè)面一次值便會(huì)加 1,至此點(diǎn)贊接口便完成了
3. 使用KOA2+ES6封裝PHP點(diǎn)贊接口智政,并建立路由
1.在 koatest 項(xiàng)目文件夾的 models 文件夾中新建一個(gè) indexmodel.js 文件
編輯 indexmodel.js 文件
import rpA from 'request-promise';
class indexModel {
constructor(ctx) {
this.ctx = ctx;
}
//為了實(shí)現(xiàn)數(shù)據(jù)庫(kù)更新建立方法 傳數(shù)據(jù)的接口
updateNum() {
//在這里 return 一個(gè) promise 模塊傳入 initController.js 再在indexController.js 中調(diào)用需要用到一個(gè)模塊 request-promise? 參考網(wǎng)址: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({});
}
})
})
}
}
//將該方法導(dǎo)出认罩,? indexController.js 文件要用到
export default indexModel;
由于 updateNum 方法中需要用到 request-promise 模塊 所以需要安裝兩個(gè)包
參考鏈接:https://www.npmjs.com/package/request-promise
npm install --save request
npm install --save request-promise
編輯 indexController.js 文件
indexController 對(duì)象中增加一個(gè) 提交數(shù)據(jù)的方法
//引入所需方法的文件
import indexModel from '../models/indexModel';
update(){
return async(ctx,next)=>{
const indexM = new indexModel(ctx);
ctx.body = await indexM.updateNum();
}
}
編輯 initController.js 文件
將 indexController 提交數(shù)據(jù)的方法注冊(cè)到 一個(gè)新的路由上
_.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
此時(shí)運(yùn)行服務(wù)會(huì)發(fā)現(xiàn)小手點(diǎn)擊并沒有與服務(wù)器關(guān)聯(lián)起來(lái),此時(shí)需要用 axios 模塊來(lái)使其連接到 koa2 點(diǎn)贊接口上
4. 將用戶點(diǎn)擊事件通過(guò) axios 鏈接到 KOA2 點(diǎn)贊接口
在 koatest 項(xiàng)目中的 scripts 文件夾中新建 index.es 文件女仰,并將 praisethumb 項(xiàng)目中的 scripts -> index.js 文件代碼復(fù)制過(guò)來(lái)
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 模塊來(lái)使其連接到 koa2 點(diǎn)贊接口上
參考鏈接:https://www.npmjs.com/package/axios
這里有三種引用的方法:npm 裝包抡锈,瀏覽器裝包疾忍,cdn,這里我們用的是 cdn 方法床三,將如下代碼 copy 至 index.html 文件中
將如下代碼 copy 至 index.es -> this.element.click 點(diǎn)擊事件中
axios.get('/index/update')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
編修改過(guò)的文件 index.es
cd public\scripts\
babel index.es -o index-es.js
運(yùn)行服務(wù)
cd ../..
node app_o.js
點(diǎn)擊時(shí)頁(yè)面http://localhost:3000/index/index報(bào)如下圖所示的錯(cuò)誤
image.png
編輯 praise.php 文件中的 updateDate 方法
//更新數(shù)據(jù)的方法
public function updateDate($sql){
//如果未連接的話就鏈接到數(shù)據(jù)庫(kù)
if($this->con == null){
$this->getConnection();
}
//向前臺(tái)輸出 json 格式的數(shù)據(jù)
header('content-type:application/json;charset=utf8');
//執(zhí)行sql
//參考鏈接:http://www.runoob.com/php/php-mysql-insert.html -> 實(shí)例 (PDO)
$res=$this->con->exec($sql);
//執(zhí)行之后 輸出返回的數(shù)據(jù)
$arr = array('result'=>$res);
echo json_encode($arr);
//關(guān)閉鏈接
$this->closeCon();
}
運(yùn)行服務(wù)一罩,發(fā)現(xiàn)又報(bào)了 404 ,排查之后發(fā)現(xiàn)是 index.es 文件中的 uodate 寫成了 uodete 撇簿,誒聂渊,修改后 編譯 ,再運(yùn)行點(diǎn)擊一下小手四瘫,數(shù)據(jù)庫(kù)里面的 num 的值 +1 證明成功了
需要注意的是 php返回的數(shù)據(jù)必須嚴(yán)格是 json 格式的 不然前臺(tái) .js 文件 (未編譯:indexmodel.es 已編譯 indexmodel.js)中用到的 JSON.parse(result); 會(huì)一直報(bào)錯(cuò)導(dǎo)致頁(yè)面崩潰
cd public\scripts\
babel index.es -o index-es.js
cd../..
node app_o.js
5. 對(duì)用戶連續(xù)點(diǎn)擊事件進(jìn)行稀釋
稀釋所用的方法就是 setTimeout
編輯 index.es 文件
let f = '';
class PraiseButton{
constructor(num,element){
this.num = num;
this.element = element;
}
clickAction(){
this.element.click(()=>{
//判斷事件是否已經(jīng)存在汉嗽,如果存在便會(huì)將其清除掉,所以點(diǎn)擊只會(huì)執(zhí)行最后一次點(diǎn)擊的那次事件
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
運(yùn)行服務(wù)找蜜,稀釋成功
node app_o.js
6. 完成點(diǎn)贊接口的自動(dòng)化測(cè)試饼暑、點(diǎn)贊+1功能的自動(dòng)化測(cè)試、真實(shí)頁(yè)面點(diǎn)擊自動(dòng)化測(cè)試
1. 點(diǎn)贊+1功能的自動(dòng)化測(cè)試
安裝 karma
cnpm install karma --save-dev
安裝斷言庫(kù)洗做、核心弓叛、chrome 啟動(dòng)器
cnpm install karma-jasmine jasmine-core karma-chrome-launcher --save-dev
安裝無(wú)界面瀏覽器、無(wú)界面瀏覽器啟動(dòng)器
cnpm install phantomjs --save-dev
cnpm install karma-phantomjs-launcher --save-dev
karma 初始化生成配置文件 karma.conf.js
karma init
jasmine
no
PhantomJS
yes
5.在項(xiàng)目中新建一個(gè) test 文件夾诚纸,在該文件夾下做三大測(cè)試
將 praisethumb 項(xiàng)目文件夾的中 index.spce.js 文件復(fù)制到 test 文件夾下
編輯 karma.conf.js 文件
files: [
'test/index.spec.js',
'public/scripts/index.js'
],
singleRun: true,
啟動(dòng)測(cè)試撰筷,運(yùn)行成功
karma start
2. 點(diǎn)贊接口的自動(dòng)化測(cè)試
1.先安裝 mocha
cnpm install mocha --save-dev
安裝 supertest
cnpm install supertest --save-dev
在 test 文件夾下新建一個(gè) server.js 文件
編輯 sever.js 文件,這里我們需要用到 supertest 模塊
參考鏈接:https://www.npmjs.com/package/supertest
import requestsuper from 'supertest';
//這里引用的是 app_o.js 文件拿到 app畦徘,所以需要在 app.js 文件中將其導(dǎo)出毕籽,然后再將 app.js 文件編譯為 app_o.js 文件
import app from '../app_o.js';
//先定義一個(gè)拿到端口的方法
function request(){
return requestsuper(app.listen());
}
describe('測(cè)試路由', function() {
it('點(diǎn)贊', 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
執(zhí)行 server-es.js 文件
cd ..
mocha test\server-es.js
此時(shí)報(bào)如下圖所示的錯(cuò)誤
image.png
將 mocha 安裝至全局
cnpm install mocha -g
執(zhí)行測(cè)試
mocha test\server-es.js
執(zhí)行成功
image.png
3. 真實(shí)頁(yè)面點(diǎn)擊自動(dòng)化測(cè)試
1.安裝 selenium-webdriver
參考鏈接:https://www.npmjs.com/package/selenium-webdriver
cnpm install selenium-webdriver
2.下面火狐瀏覽器所需的相應(yīng)組件
參考鏈接:https://github.com/mozilla/geckodriver/releases/找到與當(dāng)前設(shè)備匹配的一款點(diǎn)擊下載 我的是 win64
將下載好的壓縮包解壓至 koatest 項(xiàng)目文件夾中抬闯,刪除壓縮包
再安裝兩個(gè)包
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();
//設(shè)置地址
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(); //為了看到效果將關(guān)閉瀏覽器的行為暫時(shí)注釋掉
執(zhí)行測(cè)試腳本 e2e.js 文件
node test\e2e.js
此時(shí)會(huì)發(fā)現(xiàn)瀏覽器打開頁(yè)面后,頁(yè)面并不能加載出來(lái)原因是這個(gè) koatest 項(xiàng)目此時(shí)并沒有處于運(yùn)行狀態(tài)影钉,所以需要新建一個(gè)命令行窗口中執(zhí)行項(xiàng)目運(yùn)行操作
image.png
在新窗口中輸入命令
cd Desktop
cd koatest
node app_o.js
此時(shí)再在之前的命令行窗口中執(zhí)行測(cè)試腳本 e2e.js 文件
node test\e2e.js
整個(gè)實(shí)戰(zhàn)到此結(jié)束画髓。
作者:sunxiaochuan
鏈接:http://www.reibang.com/p/2a9367afe9e7
來(lái)源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)平委,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處奈虾。