1. 摘要
这次添加的功能是 实现首页和 个人信息页面的异步加载功能
传送门:
基于 flask 框架的模拟instagram 图片分享网站的开发 2
基于 flask 框架的模拟instagram 图片分享网站的开发 1
2. 流程
2.1 profile.js 分析
- 这里需要编写相应的js 代码, 主要由前端提供, 虽然是前端提供的代码, 我们还是需要读懂它, 在必要的时候做相应的修改
- 代码中, oExports 相当于是一个字典, 记录了关键字 与相应处理函数之间的映射关系, ie, 使用initialize 调用的时候, 本质就是在执行 fInitialize 函数调用
- 在 fInitialize 中, 我们首先找到 需要加载 图片 的区域 ‘div.js-image-list’, 初始化相应数据, 并为元素 ‘.js-load-more’ 添加点击事件
- fTpl 中, oData 对应着 传入的 json 数据, 当然也可以是自己构建的字典数据 ( 在 index 中 加载评论的时候, 我们就需要自行加载自己的 comments 字典数据)
- fRequestData 用来请求数据, 这里面将 需要异步加载的 html 代码写入进来
$(function () {
var oExports = {
initialize: fInitialize,
// 渲染更多数据
renderMore: fRenderMore,
// 请求数据
requestData: fRequestData,
// 简单的模板替换
tpl: fTpl
};
// 初始化页面脚本
oExports.initialize();
function fInitialize() {
var that = this;
// 常用元素
that.listEl = $('div.js-image-list');
// 初始化数据
that.uid = window.uid;
that.page = 1;
that.pageSize = 6;
that.listHasNext = true;
// 绑定事件
$('.js-load-more').on('click', function (oEvent) {
var oEl = $(oEvent.currentTarget);
var sAttName = 'data-load';
// 正在请求数据中,忽略点击事件
if (oEl.attr(sAttName) === '1') {
return;
}
// 增加标记,避免请求过程中的频繁点击
oEl.attr(sAttName, '1');
that.renderMore(function () {
// 取消点击标记位,可以进行下一次加载
oEl.removeAttr(sAttName);
// 没有数据隐藏加载更多按钮
!that.listHasNext && oEl.hide();
});
});
}
function fRenderMore(fCb) {
var that = this;
// 没有更多数据,不处理
if (!that.listHasNext) {
return;
}
that.requestData({
uid: that.uid,
page: that.page + 1,
pageSize: that.pageSize,
call: function (oResult) {
// 是否有更多数据
that.listHasNext = !!oResult.has_next && (oResult.images || []).length > 0;
// 更新当前页面
that.page++;
// 渲染数据
var sHtml = '';
$.each(oResult.images, function (nIndex, oImage) {
sHtml += that.tpl([
'<a class="item" href="/image/#{id}">',
'<div class="img-box">',
'<img src="/#{url}">',
'</div>',
//'<div class="img-mask"></div>',
//'<div class="interaction-wrap">',
// '<div class="interaction-item"><i class="icon-comment"></i>#{comment_count}</div>',
//'</div>',
'</a>'].join(''), oImage);
});
sHtml && that.listEl.append(sHtml);
},
error: function () {
alert('出现错误,请稍后重试');
},
always: fCb
});
}
function fRequestData(oConf) {
var that = this;
var sUrl = '/profile/images/' + oConf.uid + '/' + oConf.page + '/' + oConf.pageSize + '/';
$.ajax({url: sUrl, dataType: 'json'}).done(oConf.call).fail(oConf.error).always(oConf.always);
}
function fTpl(sTpl, oData) {
var that = this;
sTpl = $.trim(sTpl);
return sTpl.replace(/#{(.*?)}/g, function (sStr, sName) {
return oData[sName] === undefined || oData[sName] === null ? '' : oData[sName];
});
}
});
2.2 建立请求的路由
- 这部分需要和 相应的js 文件中 的 fRequestData 定义的路由保持一致, 并输出json 数据
@app.route('/profile/images/<int:id>/<int:page_num>/<int:per_page>/')
@login_required
def profile_paginate(id, page_num, per_page):
user = User.query.get(id)
paginate = user.images.paginate(page=page_num, per_page=per_page, error_out=False)
map = {'has_next' : paginate.has_next}
images = []
for image in paginate.items:
imgvo = {'id':image.id, 'url':image.url}
images.append(imgvo)
map['images'] = images
return json.dumps(map)
2.3 index 页面
同理可以编写index 页面的异步加载功能
3. 处理效果
4. 遇到的问题
- 由于jquery 代码不熟悉, 加载的时候, 评论部分无法加载, 后来才想到, 应该修改 需要传递的 json 信息, 将评论作为一个列表传送
相应的 renderMore 部分代码:
function fRenderMore(fCb) {
var that = this;
// 没有更多数据,不处理
if (!that.listHasNext) {
return;
}
that.requestData({
uid: that.uid,
page: that.page + 1,
pageSize: that.pageSize,
call: function (oResult) {
// 是否有更多数据
that.listHasNext = !!oResult.has_next && (oResult.images || []).length > 0;
// 更新当前页面
that.page++;
// 渲染数据
var sHtml = '';
$.each(oResult.images, function (nIndex, oImage) {
sHtml_part1 = that.tpl([
'<article class="mod">',
'<header class="mod-hd">',
'<time class="time">#{ images.create_date }</time>',
'<a href="/profile/#{image_user_id}" class="avatar">',
' <img src="/#{image_user_head_url}">',
'</a>',
'<div class="profile-info">',
'<a title="#{image_user_username}" href="/profile/#{image_user_id}">#{image_user_username}</a>',
'</div>',
'</header>',
'<div class="mod-bd">',
'<div class="img-box">',
'<a href = "/image/#{image_id}">',
'<img src="/#{image_url}">',
' </div>',
' </div>',
' <div class="mod-ft">',
' <ul class="discuss-list">',
' <li class="more-discuss">',
' <a>',
' <span>全部 </span><span class="">#{image_comments_length}</span>',
'<span> 条评论</span></a>',
'</li>'].join(''), oImage);
sHtml_part2 = ' ';
// 解析评论列表中的数据
for (var ni = 0; ni < oImage.image_comments_length; ni++){
dict = {'comment_user_username':oImage.comment_user_username[ni], 'comment_user_id':oImage.comment_user_id[ni],
'comment_content':oImage.comment_content[ni] };
sHtml_part2 += that.tpl([
' <li>',
' <a class="_4zhc5 _iqaka" title="#{comment_user_username}" href="/profile/#{comment_user_id}" data-reactid=".0.1.0.0.0.2.1.2:$comment-17856951190001917.1">#{comment_user_username}</a>',
' <span>',
' <span>#{comment_content}</span>',
' </span>',
' </li>',
].join(''), dict);
}
sHtml_part3 = that.tpl([
' </ul>',
' <section class="discuss-edit">',
' <a class="icon-heart"></a>',
' <form>',
' <input placeholder="添加评论..." type="text">',
' </form>',
' <button class="more-info">更多选项</button>',
' </section>',
' </div>',
' </article> '
].join(''), oImage);
sHtml += sHtml_part1 + sHtml_part2 + sHtml_part3;
});
sHtml && that.listEl.append(sHtml);
},
error: function () {
alert('出现错误,请稍后重试');
},
always: fCb
});
}
- 修改js 代码之后, 直接输入网址, 不会立即生效, 需要 刷新浏览器(ps, 被这个坑了好久)
5. 工程地址
https://code.csdn.net/zhyh1435589631/instagram_simulation/tree/master