- 实现四种消息类型
分享消息,单图片消息的模板
/**
* 分享消息模板
* @param {object} 分享消息的内容,包含图片和文字
* @return {string} 返回html字符串
*/
function shareTpl(share) {
var htmlText = [];
htmlText.push('');
htmlText.push('');
htmlText.push('' + share['text'] + '
');
htmlText.push('');
return htmlText.join('');
}
/**
* 单图片消息模板
* @param {object} 单图片消息的图片
* @return {string} 返回html字符串
*/
function onlyImgTpl(pics) {
var htmlText = [];
htmlText.push('');
return htmlText.join('');
}
通过每一条消息的type
值进行匹配
switch (content.type) {
// 多图片消息
case 0:
contentHtml = multiplePicTpl(content.pics);
break;
case 1:
// TODO: 实现分享消息
contentHtml = shareTpl(content.share);
break;
case 2:
// TODO: 实现单张图片消息
contentHtml = onlyImgTpl(content.pics);
break;
case 3:
// TODO: 实现无图片消息
contentHtml = '';
break;
}
在页面渲染函数里,遍历data
即可
/**
* 页面渲染函数:render
*/
function render() {
// TODO: 目前只渲染了一个消息(多图片信息),需要展示data数组中的所有消息数据。
var messageHtml = [];
for (var i = 0; i < data.length; i++) {
messageHtml.push(messageTpl(data[i], i));
}
messageHtml = messageHtml.join('');
$momentsList.html(messageHtml);
}
- 每一条消息都会带有一个回复操作面板,
/*
*点击回复按钮弹出回复模板
*@param {Boolean} hasLiked 是否点过赞
*@return {String} 返回html字符串
*/
function replyPanelTpl(hasLiked) {
var likeText = hasLiked ? '取消' : '点赞';
var htmlText = [];
htmlText.push('
');
return htmlText.join('');
}
默认状态均为隐藏,点击时,通过筛选className
,通过改变面板的width
使其显示,并有一个出现动画
// 弹出回复操作面板
case 'item-reply':
//隐藏掉所有的回复操作面板和评论框
hidePanel();
// 显示当前消息的回复操作面板
$this.siblings('.reply-panel').css('width', '160px');
break;
总结:开始想,只用一个回复操作面板,可以减少html代码量和搜索,用一个全局变量curMomentItem
来记录当前想要点赞和评论的是哪一条消息。
后来,考虑到之前老师说要尽量少使用全局变量,于是,采用了每一条消息都有一个回复面板,用增加html代码量的方法取代了。
最终虽然实现了功能,但总感觉有点冗余,不够精简
想请问老师,有没有更好的实现方法?或者在实际开发中,那个会更好?
- 实现点赞功能
当点击了回复面板中的
// 点赞或取消赞
case 'like':
case 'icon-like':
case 'text-like':
changeLike($this.parents('.moments-item'));
hidePanel();
break;
点赞或取消函数
/**
* 点赞函数
* @param {object} 点赞目标
*/
function changeLike($target) {
// 点赞的消息索引
var index = $target.attr('data-index');
// 修改data中的点赞状态
var like = data[index].reply.hasLiked;
// 若原来没有点赞,则点赞,
if (!like) {
// 修改本人的点赞状态
data[index].reply.hasLiked = !like;
// 修改点赞人列表
data[index].reply.likes.push(userName);
}
// 如果原来点赞,则取消点赞
else {
// 修改本人的点赞状态
data[index].reply.hasLiked = !like;
// 在点赞人列表中删除本人
var likeIndex = data[index].reply.likes.indexOf(userName); //找到本人在点赞列表中的索引
data[index].reply.likes.splice(likeIndex, 1); // 删除
}
// 删除原来的点赞列表
$target.find('.reply-like').remove();
// 重新渲染点赞列表
$target.find('.reply-zone').prepend(likesHtmlTpl(data[index].reply.likes));
// 修改点赞面板中的文字
var text = data[index].reply.hasLiked ? '取消' : '点赞';
$target.find('.text-like').html(text);
}
效果
总结:
如上图,当点击左边区域时,都要触发点赞或取消
由于之前的点击事件是通过事件委托的形式实现的,于是,在这里,将点击目标细分为三种,整个
div
,
图标
以及
点赞
文字
疑问:如果把这种需要对整个容器都反应的点击是否不使用事件委托会更好?
4.实现增加评论功能
当点击评论时
// 评论
case 'comment':
case 'icon-comment':
case 'text-comment':
hidePanel();
// 展现当前消息的评论框
$this.parents('.item-right').children('.comment-form').css('display', 'flex');
// 让当前消息的评论框获得焦点
$this.parents('.item-right').children('.comment-form').children('.comment-text')[0].focus();
实时检测输入框是否为空
// 评论输入框实时绑定
$('.comment-text').on('input', function() {
var $this = $(this);
if ($this.val()) {
// 如果内容不为空,则发送按钮背景为绿色,并且可用
$('.comment-submit').css('background', '#44b00e');
$('.comment-submit').attr('disabled', false);
} else {
// 如果内容为空,则发送按钮背景为灰色,不可用
$('.comment-submit').css('background', '#808080cc');
$('.comment-submit').attr('disabled', true);
}
});
点击发送按钮
// 发送评论
case 'comment-submit':
commentSubmit($this);
break;
在输入框按下enter键,同样可以发送消息
// 按下enter鍵自動提交評論
$('.comment-text').on('keydown', function(event) {
// 判斷按下的是否為enter鍵
if (event.keyCode === 13) {
commentSubmit($(this).siblings('.comment-submit'));
}
});
发送评论函数
/**
* 評論函数
* @param {object} 提交按鈕
*/
function commentSubmit(target) {
var $this = target;
// 生成新的评论html代码
var commentHtml = '' +
'';
// 找到当前消息的回复评论
var $replyComment = $this.parents('.item-right').find('.reply-comment');
// 如果没有评论列表,需要新建一个评论列表框
if (!$replyComment.length) {
var replyCommentHtml = '';
var $replyZone = $this.parents('.item-right').find('.reply-zone');
// 新建一个评论列表框
$replyZone.append(replyCommentHtml);
$replyComment = $replyZone.children('.reply-comment');
}
// 添加新评论
$replyComment.append(commentHtml);
// 删除掉输入框里的文字
$this.siblings('.comment-text').val('');
// 隐藏评论框
$('.comment-form').css('display', 'none');
// 修改消息体,增加当前消息的一条评论
var index = $this.parents('.moments-item').attr('data-index');
data[index].reply.comments.push({
author: userName,
text: $this.siblings('.comment-text').val()
});
console.log(data[index].reply.comments);
}
:' +
$this.siblings('.comment-text').val() +
'
演示
总结:评论与点赞相同,也是每一条消息有一个评论框,初始都是隐藏的,直到被点击
4.实现点击放大图片
html
代码
对应的css
代码
.page-moments .layer{
position: absolute;
display: block;
margin: 0 auto;
top: 0;
width: 100%;
max-width: 640px;
height: 0;
background: #000;
z-index: 999;
}
.layer .pic-enlarge{
width: 100%;
max-width: 500px;
max-height: 500px;
position: fixed;
top: 50vh;
left: 50%;
transform: translate(-50%, -50%);
}
点击处理
// 放大图片
case 'pic-item':
case 'item-only-img':
hidePanel();
// 获取页面
var height = $page.height() + 'px';
// 设置笼罩层的高度和显示
$('.layer').css({
'height': height,
'display': 'block'
});
// 设置放大图片的地址
$('.pic-enlarge').attr('src', $this.attr('src'));
break;
// 隐藏放大图片区域
case 'layer':
case 'pic-enlarge':
hidePanel();
$('.layer').css('display', 'none');
break;
总结:主要是并没有设置背景层的高度,想着把高度设成与想个朋友圈页面高度一致,但好像在实际手机中并不需要只要是手机屏幕的高度就可以了,但如果这样子在网页中就没有罩住整个页面,当滚动的时候就会看到下面的消息,所以,在js
中,用获取page
的高度,设置成一样的。
另外,放大后的图片设置最大高宽为500px,有尝试设置成640px,那样照片放大后有点模糊,所以,改成500px了,于是,就想着上下左右各留一点空隙
不知道这种想法是否正确,还请老师指点。
收获与不足:
不足:自己对于jqery的一些方法和属性还不太熟悉
比如children()
和find()
,一开始以为`children()'是找到所有的后代元素,花了好久测试以及搜索才知道原来只是找到直接子元素。
收获:相对地,通过发现自己的不足,把不熟悉的属性通过查资料更加熟悉了,更了解了。