Albumy示例程序个人资料弹窗无法及时更新关注状态


#1

在照片详情页的评论列表,悬停用户头像或昵称会发送ajax请求,并弹出包含返回的用户资料的弹窗,弹窗中包含关注按钮,通过ajax执行关注操作。在用户资料弹窗模板中设置了根据用户当前的关注状态显示对应的操作按钮,涉及的代码较多就不放上来了源码及Demo,页面如下图:

发现存在一个问题:通过用户资料弹窗执行关注或取消关注操作后,重新触发该弹窗,发现关注按钮没有更新(预期行为是根据用户当前关注状态显示关注或取消关注按钮),依然会显示初次请求时的按钮。F5重载页面后正常显示。

个人猜测可能是在用户弹窗中执行关注操作后,重新触发弹窗时浏览器使用了弹窗页面的缓存,没有重新发起请求,因此弹窗页面的内容没有更新,尝试在ajax请求的url附加随机查询参数,页面请求正常但问题依然没有解决。尝试方法部分代码:

function show_profile_popover(e) {
    var $el = $(e.target);
    var url = $el.data('href') +  '&t=' + Math.random(1000);

    hover_timer = setTimeout(function () {
        hover_timer = null;
        $.ajax({
            type: 'GET',
            url: url,
            success: function (data) {

不知道是否有朋友了解导致上述问题的成因,以及可行的解决方案?


#2

返回的响应是正确的,初步判断是 Bootstrap / 浏览器缓存了弹窗内容。


#3

不知道是否有比较好的解决方案呢,Google和SO上找了很久都没解决:joy:


#4

这两天会抽空看看。


#5

简单试了下,bug能复现。

步骤,进入该页面后,随便选一个人从「Follow」状态鼠标单击取消为「Unfollow」状态,然后鼠标从名字移开使弹窗自动关闭,再把鼠标移回去显示弹窗。本来应该是「Unfollow」状态的结果还是「Follow」状态。之后继续测试,鼠标单击该「Follow」,后端报400错误,错误提示「Already followed.」。

一开始怀疑是浏览器问题,分别使用谷歌浏览器和火狐浏览器,结果又发现一个新bug:

谷歌浏览器能正常显示「Follow」,而火狐浏览器根本不显示「Follow」。火狐浏览器的「Unfollow」显示正常,「Unfollow」能单击发出请求,然后就不显示「Follow」了。

%E4%B8%8D%E8%A7%81%E4%BA%86

火狐浏览器版本:64.0.2,图片中箭头位置本来应该有一个「Follow」按钮的。


还是谷歌浏览器兼容性好啊~


#7

感谢测试,我用火狐浏览器也测试了一下,不过结果和谷歌浏览器是一致的:joy:,我用的是开发者版本,版本号66.0b3。


#8

尝试解决下这个bug,有点麻烦啊。

最后这个bug追踪到是 Popper.js 库的问题(albumy\static\js\popper.min.js)。

简单的测试代码如下:

   function show_profile_popover(e) {
        var $el = $(e.target);

        hover_timer = setTimeout(function () {
            hover_timer = null;
            $.ajax({
                type: 'GET',
                url: $el.data('href'),
                success: function (data) {
                    console.log(data)  // Follow变动后这里打印没问题的
                    $el.popover({
                        html: true,
                        //content: data,

                        // test1
                        // 数值不会随机
                        // content: Math.random(1000),

                        // test2,把一个function传递给content
                        // 数值会随机,达到预期效果
                        // content: ()=>{return Math.random(1000)},

                        // test3
                        // 不成功,Follow变动后这里的data没变化,没达到预期效果
                        content: ()=>{return data},

                        trigger: 'manual',
                        animation: false
                    });
                //...

原代码content: data情况下,第一次渲染data没问题,不隐藏popover弹窗情况下,反复点击「Follow」和「Unfollow」,显示都没问题。但是,只要鼠标移开使popover隐藏后再显示,还是显示不正确。

查看content的文档:

Name Type Default Description
content string | element | function ''

Default content value if data-content attribute isn't present.

If a function is given, it will be called with its this reference set to the element that the popover is attached to.

说是可以传递function,就试着测试了一下,在回调function中返回随机值能达到预期效果,但是返回请求后的data还是没达到预期效果。


#9

加个history.go(0)就能解决问题,但仍不知道原因

    function show_profile_popover(e) {
        var $el = $(e.target);

        hover_timer = setTimeout(function () {
            hover_timer = null;
            $.ajax({
                type: 'GET',
                url: $el.data('href'),
                success: function (data) {
                    $el.popover({
                        html: true,                //支持HTML字符串
                        //title: "提示窗",           //弹窗标题
                        content: data,             //弹窗内容
                        trigger: 'manual',         //手动
                        placement: 'top',          //弹出框位置
                        animation: false           //动画效果
                    });
                    $el.popover('show');
                    $('.popover').on('mouseleave', function () {
                        setTimeout(function () {
                            $el.popover('hide');
                        }, 200);
                        history.go(0);
                    });
                }
            });
        }, 500);
    }