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'] = imagesreturn 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