2021SC@SDUSC
从这一篇开始,我们将要和对应的html文件一起分析,通过调用JavaScript文件的方式来推测更多使用的细节。
view/home/ceshi_hooks.html
这里是钩子。钩子是什么?https://www.jianshu.com/p/3382cc765b39介绍了钩子函数的使用方式。Hook技术又叫做钩子函数,在系统没有调用该函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,还可以强制结束消息的传递。简单来说,就是把系统的程序拉出来变成我们自己执行代码片段。当然,这篇文章说的是Java程序里的Hook技术,但在JavaScript中也可以如此看待。
在这个Html文档中,让我们看看测试的钩子是如何运转的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{HOOK@adminArticleEdit@1|safe}} <hr>
{{HOOKS@adminArticleEdit['aaaa']|safe}}<hr>
{{HOOKS@adminArticleEdit['bbbb']|safe}}<hr>
{{HOOKS@adminArticleEdit@2['bbbb']|safe}}<br>
{{HOOK@adminArticleEdit|safe}}
</body>
</html>
前面是Html文档惯有的写作模式,不必多说。body 一块让我们重点看一看。这里是写了一些示例的钩子调用,包括带$hook_type 参数的视图钩子调用,带$hook_type 和$hook.key 参数视图钩子调用,带$hook_type 和$hook.key 参数视图钩子调用,默认调用。
src/controller/home/detail.js
下面再让我们回头去看src/controller/home/detail.js 。这里存放了一些钩子相关的函数。
this.assign('info', info);
await this.hook('documentDetailAfter', info);
await this.hook('videoPlayer', info);
const editor = !think.isEmpty(info.editor) ? info.editor : await this.model('cmswing/model').get_model(info.model_id, 'editor');
const field_group = await this.model('cmswing/model').get_model(info.model_id, 'field_group');
const fields = await this.model('cmswing/attribute').get_model_attribute(info.model_id, true);
const fg = parse_config_attr(field_group);
const farr = [];
for (const key in fg) {
for (const f of fields[key]) {
if (f.type === 'editor') {
farr.push(f);
if (editor === '0') {
await this.hook('pageHeader', f.name, f.value, {$hook_key: f.name});
await this.hook('pageFooter', f.name, f.value, {$hook_key: f.name});
await this.hook('pageContent', f.name, info[f.name], {$hook_key: f.name});
} else {
await this.hook('pageHeader', f.name, f.value, {$hook_key: f.name, $hook_type: editor});
await this.hook('pageFooter', f.name, f.value, {$hook_key: f.name, $hook_type: editor});
await this.hook('pageContent', f.name, info[f.name], {$hook_key: f.name, $hook_type: editor});
}
};
};
};
文档内容底部钩子,视频播放器钩子和加载页面头部底部钩子,总之全是钩子。
接下来又是我们熟悉的浏览器差分:
if (this.isMobile) {
if (!think.isEmpty(info.template) && info.template != 0) {
temp = info.template;
} else if (!think.isEmpty(cate.template_m_detail)) {
temp = cate.template_m_detail;
} else {
temp = model;
}
return this.display(this.mtpl(temp));
} else {
if (!think.isEmpty(info.template) && info.template != 0) {
temp = info.template;
} else if (!think.isEmpty(cate.template_detail)) {
temp = cate.template_detail;
} else {
temp = model;
}
return this.display(`home/detail_${temp}`);
}
}
最后是关于下载的一段代码,很长但是并没有很复杂。
async downloadgetidAction() {
const id = decodeURIComponent(this.get('id')).split('||');
const db = this.model('document_download');
const info = await db.find(id[0]);
const file_id = info.file_id;
let dlink;
if (Number(id[1]) === 1) {
const d = await get_file(file_id);
if (Number(d.type) === 2) {
const qiniu = this.extService('qiniu', 'attachment');
dlink = await qiniu.download(d.savename);
} else {
dlink = `/home/detail/download?id=${d.id}#${d.name}`;
}
await db.where({id: info.id}).increment('download');
this.assign('durl', dlink);
if (this.isMobile) {
return this.display(`home/mobile/detail_downloadgetid`);
} else {
return this.display();
}
} else if (id[1] == 2) {
dlink = id[2];
await db.where({id: info.id}).increment('download');
return this.redirect(dlink);
} else if (id[1] == 3) {
const pan = info.panurl.split('\r\n');
for (const v of pan) {
const varr = v.split('|');
console.log(varr[1]);
if (!think.isEmpty(varr[2]) && think._.trim(id[2]) == think._.trim(varr[1])) {
this.assign({
title: varr[0],
durl: varr[1],
sn: varr[2]
});
}
}
await db.where({id: info.id}).increment('download');
if (this.isMobile) {
return this.display(`home/mobile/detail_downloadgetid`);
} else {
return this.display();
}
}
}
其中包含一些判定和分流工作,不再赘述。最后依旧是和下载相关的代码——
async downloadAction() {
const file = await get_file(this.get('id'));
const filePath = `${think.ROOT_PATH}/www${file.savename}`;
const userAgent = this.userAgent.toLowerCase();
let hfilename = '';
if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
hfilename = `=${encodeURIComponent(file.name)}`;
} else if (userAgent.indexOf('firefox') >= 0) {
hfilename = `*="utf8''${encodeURIComponent(file.name)}"`;
} else {
hfilename = `=${Buffer.from(file.name).toString('binary')}`;
}
this.ctx.set('Content-Disposition', `attachment; filename${hfilename}`);
return this.download(filePath);
}
};
总结
src/controller/home/detail.js为我们展现了首页的详情需要的各种函数,从功能上来讲可能并不复杂,却要做到面面俱到。从这当中也可以看到,从一个框架到真正实现一个页面的展示中间需要多少距离。
|