【问题标题】:jQuery Mobile: Markup Enhancement of dynamically added contentjQuery Mobile:动态添加内容的标记增强
【发布时间】:2013-01-11 02:30:27
【问题描述】:

我想知道如何动态增强 jQuery Mobile 页面?

我尝试过使用这些方法:

  1. $('[data-role="page"]').trigger('create');

  2. $('[data-role="page"]').page();

另外,我如何才能防止仅对复选框进行增强标记?

【问题讨论】:

  • 当您对包含您想要增强的元素的元素执行 .trigger('create') 时发生了什么?

标签: javascript jquery html cordova jquery-mobile


【解决方案1】:

免责声明:

这篇文章也可以在我的博客 HERE 中找到。

简介:

有几种方法可以增强动态创建的内容标记。仅仅动态地向 jQuery Mobile 页面添加新内容是不够的,新内容必须通过经典的 jQuery Mobile 样式来增强。因为这是一个相当繁重的任务,所以需要一些优先级,如果可能,jQuery Mobile 需要尽可能少地进行增强。如果只需要设置一个组件的样式,则不要增强整个页面。

这一切意味着什么?当页面插件调度 pageInit 事件时,大多数小部件使用该事件来自动初始化自己。它会自动增强它在页面上找到的任何小部件实例。

但是,如果您生成新的标记客户端或通过 Ajax 加载内容并将其注入页面,您可以触发 create 事件来处理新标记中包含的所有插件的自动初始化。这可以在任何元素(甚至是页面 div 本身)上触发,从而为您节省手动初始化每个插件(listview 按钮、选择等)的任务。

考虑到这一点,让我们讨论增强级别。一共有三个,它们从资源需求低到高排序:

  1. 增强单个组件/小部件
  2. 增强页面内容
  3. 增强整页内容(页眉、内容、页脚)

增强单个组件/小部件:

重要提示:以下增强方法只能用于当前/活动页面。对于动态插入的页面,这些页面及其内容在插入 DOM 后将得到增强。在动态创建的页面/活动页面之外调用任何方法都会导致错误。

每个 jQuery Mobile 小部件都可以动态增强:

  1. Listview

    标记增强:

    $('#mylist').listview('refresh');
    

    删除列表视图元素:

    $('#mylist li').eq(0).addClass('ui-screen-hidden'); 
    

    增强示例:http://jsfiddle.net/Gajotres/LrAyE/

    请注意,refresh() 方法仅影响附加到列表的新节点。这样做是出于性能原因。

    列表视图的一大亮点是过滤功能。不幸的是,由于某种原因,jQuery Mobile 无法动态地将过滤器选项添加到现有的列表视图中。幸运的是,有一个解决方法。如果可能,请删除当前列表视图并添加另一个并打开文件管理器选项。

    这是一个工作示例:https://stackoverflow.com/a/15163984/1848600

    $(document).on('pagebeforeshow', '#index', function(){       
        $('<ul>').attr({'id':'test-listview','data-role':'listview', 'data-filter':'true','data-filter-placeholder':'Search...'}).appendTo('#index [data-role="content"]');
        $('<li>').append('<a href="#">Audi</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Mercedes</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Opel</a>').appendTo('#test-listview');
        $('#test-listview').listview().listview('refresh');
    });
    
  2. Button

    标记增强:

    $('[type="button"]').button();
    

    增强示例:http://jsfiddle.net/Gajotres/m4rjZ/

    还有一点,你不需要使用输入元素来创建一个按钮,甚至可以用一个基本的div来完成,这里有一个例子:http://jsfiddle.net/Gajotres/L9xcN/

  3. Navbar

    标记增强:

    $('[data-role="navbar"]').navbar();
    

    增强示例:http://jsfiddle.net/Gajotres/w4m2B/

    这是一个如何添加动态导航栏标签的演示:http://jsfiddle.net/Gajotres/V6nHp/

    还有一个 pagebeforecreate 事件:http://jsfiddle.net/Gajotres/SJG8W/

  4. Text inputs, Search inputs & Textareas

    标记增强:

    $('[type="text"]').textinput();   
    

    增强示例:http://jsfiddle.net/Gajotres/9UQ9k/

  5. Sliders & Flip toggle switch

    标记增强:

    $('[type="range"]').slider();  
    

    增强示例:http://jsfiddle.net/Gajotres/caCsf/

    pagebeforecreate 事件期间的增强示例:http://jsfiddle.net/Gajotres/NwMLP/

    动态创建滑块有点麻烦,请在此处阅读更多信息:https://stackoverflow.com/a/15708562/1848600

  6. Checkbox & Radiobox

    标记增强:

    $('[type="radio"]').checkboxradio();
    

    或者如果您想选择/取消选择另一个 Radiobox/Checkbox 元素:

    $("input[type='radio']").eq(0).attr("checked",false).checkboxradio("refresh");
    

    $("input[type='radio']").eq(0).attr("checked",true).checkboxradio("refresh");
    

    增强示例:http://jsfiddle.net/Gajotres/VAG6F/

  7. Select menu

    标记增强:

    $('select').selectmenu();  
    

    增强示例:http://jsfiddle.net/Gajotres/dEXac/

  8. Collapsible

    不幸的是,可折叠元素无法通过某些特定方法进行增强,因此必须使用 trigger('create') 代替。

    增强示例:http://jsfiddle.net/Gajotres/ck6uK/

  9. Table

    标记增强:

    $(".selector").table("refresh");
    

    虽然这是一种标准的表格增强方式,但目前我无法让它发挥作用。所以改为使用 trigger('create')。

    增强示例:http://jsfiddle.net/Gajotres/Zqy4n/

  10. Panels -

    面板标记增强:

    $('.selector').trigger('pagecreate');
    

    内容动态添加到面板的标记增强:

    $('.selector').trigger('pagecreate');
    

    示例:http://jsfiddle.net/Palestinian/PRC8W/

增强页面内容:

如果我们正在生成/重建整个页面内容,最好一次性完成,并且可以这样做:

$('#index').trigger('create');

增强示例:http://jsfiddle.net/Gajotres/426NU/

增强整页内容(页眉、内容、页脚):

不幸的是,trigger('create') 不能增强页眉和页脚标记。在这种情况下,我们需要大炮:

$('#index').trigger('pagecreate');

增强示例:http://jsfiddle.net/Gajotres/DGZcr/

这几乎是一种神秘的方法,因为我在官方 jQuery Mobile 文档中找不到它。仍然很容易在 jQuery Mobile 错误跟踪器中找到它,并警告不要使用它,除非确实有必要。

注意,.trigger('pagecreate'); 可以假设每次页面刷新只能使用一次,我发现它是不真实的:

http://jsfiddle.net/Gajotres/5rzxJ/

第三方增强插件

有几个 3rd 方增强插件。有些是对现有方法的更新,有些是为了修复损坏的 jQM 功能。

  • 按钮文字变化

    很遗憾找不到这个插件的开发者。原SO来源:Change button text jquery mobile

    (function($) {
        /*
         * Changes the displayed text for a jquery mobile button.
         * Encapsulates the idiosyncracies of how jquery re-arranges the DOM
         * to display a button for either an <a> link or <input type="button">
         */
        $.fn.changeButtonText = function(newText) {
            return this.each(function() {
                $this = $(this);
                if( $this.is('a') ) {
                    $('span.ui-btn-text',$this).text(newText);
                    return;
                }
                if( $this.is('input') ) {
                    $this.val(newText);
                    // go up the tree
                    var ctx = $this.closest('.ui-btn');
                    $('span.ui-btn-text',ctx).text(newText);
                    return;
                }
            });
        };
    })(jQuery);
    

    工作示例:http://jsfiddle.net/Gajotres/mwB22/

获取正确的最大内容高度

如果页眉和页脚有一个恒定的高度,内容 div 可以通过一点 css 技巧轻松设置为覆盖全部可用空间:

#content {
    padding: 0;
    position : absolute !important; 
    top : 40px !important;  
    right : 0; 
    bottom : 40px !important;  
    left : 0 !important;     
}

这是一个带有 Google maps api3 演示的工作示例:http://jsfiddle.net/Gajotres/7kGdE/

此方法可用于获取正确的最大内容高度,并且必须与 pageshow 事件一起使用。

function getRealContentHeight() {
    var header = $.mobile.activePage.find("div[data-role='header']:visible");
    var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
    var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
    var viewport_height = $(window).height();

    var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
    if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
        content_height -= (content.outerHeight() - content.height());
    } 
    return content_height;
}

这是一个现场 jsFiddle 示例:http://jsfiddle.net/Gajotres/nVs9J/

要记住一件事。此功能将正确地为您提供最大可用内容高度,同时它可用于拉伸相同的内容。不幸的是,它不能用于将 img 拉伸到完整的内容高度,img 标签的开销为 3px。

标记增强预防方法:

这可以通过几种方式完成,有时您需要将它们结合起来才能达到预期的效果。

  • 方法一:

    添加这个属性就可以做到:

    data-enhance="false"
    

    到页眉、内容、页脚容器。

    这也需要在应用加载阶段开启:

    $(document).one("mobileinit", function () {
        $.mobile.ignoreContentEnabled=true;
    });
    

    在 jquery-mobile.js 初始化之前初始化它(看下面的例子)。

    更多信息可以在这里找到:

    http://jquerymobile.com/test/docs/pages/page-scripting.html

    示例:http://jsfiddle.net/Gajotres/UZwpj/

    要重新创建页面,请使用:

    $('#index').live('pagebeforeshow', function (event) {
        $.mobile.ignoreContentEnabled = false;
        $(this).attr('data-enhance','true');
        $(this).trigger("pagecreate")
    });
    
  • 方法二:

    第二个选项是使用这一行手动完成:

    data-role="none"
    

    示例:http://jsfiddle.net/Gajotres/LqDke/

  • 方法三:

    可以防止某些 HTML 元素进行标记增强:

     $(document).bind('mobileinit',function(){
          $.mobile.page.prototype.options.keepNative = "select, input";
     });    
    

    示例:http://jsfiddle.net/Gajotres/gAGtS/

    在 jquery-mobile.js 初始化之前再次初始化它(看下面的例子)。

标记增强问题:

有时从头开始创建组件(如列表视图)时会出现此错误:

无法在初始化之前调用列表视图上的方法

可以在标记增强之前通过组件初始化来防止它,这是您可以解决的方法:

$('#mylist').listview().listview('refresh');

标记覆盖问题:

如果由于某种原因需要更改默认的 jQuery Mobile CSS,则必须使用 !important 覆盖来完成。没有它,默认的 CSS 样式将无法更改。

例子:

#navbar li {
    background: red !important;
}

jsFiddle 示例:http://jsfiddle.net/Gajotres/vTBGa/

变化:

  • 01.02.2013 - 添加了动态导航栏演示
  • 01.03.2013 - 添加了有关如何向列表视图动态添加过滤的评论
  • 07.03.2013 - 添加了新章节:获取正确的最大内容高度
  • 17.03.2013 - 在章节中添加了几句话:获取正确的最大内容高度
  • 29.03.2013 - 添加了有关动态创建的滑块的新内容并修复了一个示例错误
  • 03.04.2013 - 添加了有关动态创建的可折叠元素的新内容
  • 04.04.2013 - 添加了第 3 方插件章节
  • 20.05.2013 - 添加了动态添加的面板和内容
  • 21.05.2013 - 添加了另一种设置完整内容高度的方法
  • 20.06.2013 - 添加了新章节:标记覆盖问题
  • 29.06.2013 - 添加了关于何时使用增强方法的重要说明

【讨论】:

  • @Gajotres 出色的解释
  • 希望我可以添加+6,这是我很长时间以来看到的最佳答案。非常感谢你,现在只要 jQuery mobile 的文档是这样直截了当的。谢谢!不过,有一个问题,我有一个正在更改的标题......标题是否有类似的方法? $(":jqmData(role='header')").header()?
  • 如果要增强header需要使用trigger('pagecreate'),可以在我的回答中找到。
  • 我想使用 type="password" 增强输入字段如果我尝试 $("#acntNewPW").textinput();我得到了经典风格和新的 jquery 移动风格。
  • 这通常发生在 jQuery Mobile js 与 jQuery Mobile css 不匹配时。转到他们的官方页面并下载最新版本,然后重试。
【解决方案2】:

从 JQMobile 1.4 开始,您可以对所有孩子 http://api.jquerymobile.com/enhanceWithin/ 执行 .enhanceWithin()

var content = '<p>Hi</p>';
$('#somediv').html(content);
$('#somediv').enhanceWithin();

【讨论】:

  • 这是否比$('#somediv').trigger('create') 更可取,如果是,为什么?
  • .trigger( "create" ) 已被弃用。您可以改用新方法 .enhanceWithin()。例如,如果你动态添加一个带有 data-role="listview" 的 ul 的可折叠文件,你可以使用 .enhanceWithin() 来初始化 listview 插件。
  • 在子元素已经增强的元素上调用这个方法有问题吗?
  • 我不知道这样的问题。然而,这种方法会遍历选择器的所有子节点,并尝试增强它可以找到的任何内容。在某些情况下,遍历大块 DOM 并不是最快的事情......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 2012-01-27
  • 2012-09-20
相关资源
最近更新 更多