【问题标题】:jquerymobile not rendering nested listview with knockoutJSjquerymobile 不使用 knockoutJS 渲染嵌套列表视图
【发布时间】:2014-02-14 03:18:36
【问题描述】:

我正在用 knockoutjs 绑定一个嵌套列表视图,并像这样使用 JQuery mobile 对其进行样式化

        <ul id="machine-list" data-bind="foreach: machineList" data-role="listview">
            <li><span data-bind="text:location"></span>
                <ul  data-bind="foreach: machines" data-role="listview">
                    <li><span data-bind="text:machine"></span></li>
                </ul>
            </li>
        </ul>  

当它进入嵌套列表时,那里什么都没有。我知道绑定正在工作,因为如果我删除数据角色,我会得到嵌套列表。任何人都可以帮忙吗?干杯。

【问题讨论】:

  • 你用的是什么版本的jQM?
  • 最新我认为它来自 jqm 网站上的 CDN。我现在不在电脑旁。

标签: jquery-mobile knockout.js


【解决方案1】:

如果您使用的是最新版本的 jQuery Mobile,您必须知道嵌套列表仅提供部分支持。 Here's the source link.。如前所述,我们必须自己使用页面 -> 页面导航系统,所以就这样吧。

设置

我曾经为此建立了一个示例。你可以调整你的代码。 我有一个像这样的 json 对象数组

[
      {
        "name": "DC Comics",
        "characters": [
            "All-Star Squadron",
            "Birds of Prey",
             ...
        ]
      }, 
      {
        "name": "Marvel Studios",
        "characters": [
            "Alpha Flight",
            "Avengers",
            "Champions",
            "Defenders",
            ...
         ]
       }
       ....
]

所以,如果您有 两页 可能会更好,其中一个用于显示主列表(即组),当单击时,另一个页面用于显示子项,即字符。

在页面加载时,我想显示如下内容:

当点击其中一个链接时,我想显示 字符数组 中存在的内容。例如,如果我选择“DC Comics”,当前上下文将是:

{
   "name": "DC Comics",
   "characters": [
       "All-Star Squadron",
       "Birds of Prey",
             ...
    ]
}

从这里,我将取出characters 属性并将其显示在 页面的列表中。 (无论如何,这就是嵌套列表曾经做的事情)。所以,需要这样的东西:

两个页面,两个视图模型

现在要实现这一点,可能有办法。但最好的方法是使用多个 ViewModels,每个页面一个,因此将其设为 2,并在初始化特定页面时绑定它。所以对于一个特定的页面,

标记:

<div data-role="page" id="groups-page"></div>

查看模型:

我们会有一个单独的ViewModel

//view model for the parent page.
var groupModel = {
    //data array
    groupInfo: [
          {
            "name": "DC Comics",
            "characters": [
                "All-Star Squadron",
                "Birds of Prey",
                 ...
            ]
          }, 
          {
            "name": "Marvel Studios",
            "characters": [
                "Alpha Flight",
                "Avengers",
                "Champions",
                "Defenders",
                ...
             ]
           }
           ....
    ]
}

pageinit 事件: 并将其绑定在#group-pagepageinit 事件中:

//events pertaining to Page 1 - the groups
$(document).on({
    "pageinit": function () {
        //apply partial binding to groups-page alone. Reason we're doing this is because only this page will be available onload
        ko.applyBindings(groupModel, this);

    }
}, "#groups-page");

请注意,applyBindings (this) 中的第二个对象表示将 id 设置为 groups-page 的 DOM 元素。

同样地,你会为第二页做同样的事情,#character-page

标记:

<div data-role="page" id="character-page"></div> 

视图模型:

 //view model for the character page - basically an empty view model to be filled with data when a link is clicked.
var characterModel = {
    name: ko.observable(),
    characterInfo: ko.observableArray()
}

pageinit 事件:

//events pertaining to Page 1 - the groups
$(document).on({
    "pageinit": function () {
        //apply partial binding to character-page alone. 
        ko.applyBindings(groupModel, this);

    }
}, "#character-page");

我们在这里使用 observables 的原因是因为每次点击某些东西时,我们都会更新 observables,这将自动更改第二页列表视图的内容。

填充第一页

这就是我的 HTML 结构的样子:

<ul data-bind="foreach: groupInfo">
     <li> 
       <a href="#">
         <span data-bind="text: name"></span>
         <span data-bind="text: characters.length" class="ui-li-count"></span>
       </a>
    </li>
</ul>

applyBindings() 仅绑定到第一页之后,我会在页面中的这些列表视图上调用刷新:

 //apply partial binding to groups-page alone. Reason we're doing this is because only this page will be available onload
ko.applyBindings(groupModel, this);

//refresh the listview
$("ul", this).attr("data-role", "listview").listview().listview("refresh");

这将位于#group-pagepageinit 事件中。

群组的点击事件,将页面更改为字符

为此,我会在第一页列表视图的a 标记上使用KO 的click 绑定:

<a href="#" data-bind="click: $root.getInfo">
  <span data-bind="text: name"></span>
  <span data-bind="text: characters.length" class="ui-li-count"></span>
</a>

其中 $root 是 ViewModel 级别的上下文(请参阅docs)。

哦等等!必须将getInfo 添加到第一页的模型groupModel。所以viewmodel变成了这样:

//view model for the parent page.
var groupModel = {
    //data array
    groupInfo: [
    //groups
    ],
    //click event to be fired when an anchor tag is clicked 
    getInfo: function (data, e) {
        //here "data" variable gives the clicked elements' corresponding array and "e" gives the event object

        //prevents defaultbehaviour of anchor tag
        e.preventDefault();

        //setting up the character array in View model of page 2
        characterModel.characterInfo(data.characters);
        //setting up name variable of ViewModel in page 2
        characterModel.name(data.name);

        //change the page
        $.mobile.changePage("#character-page", {
            transition: "slide"
        });
    }
}

请注意,我现在才填充 characterModel。由于这个模型内部的属性是observables,所以每次更新这些变量时,DOM也会更新。第二页的 HTML 是:

<ul data-bind="foreach: characterInfo">
    <li data-bind="text: $data"></li>
 </ul>

$data 用于获取characterInfo 中的内容,如果您不知道的话。完成后,您将拥有如下内容:

下一步是刷新列表视图,但不在pageinit 中。原因是,pageinit 只被触发一次,并且由于每次点击发生时character-page 都会更新,因此您必须使用pageshowpagebeforshow 方法。更多信息here。现在绑定到character-pageevents 是:

//events pertaining to Page 2 - the characters
$(document).on({
    "pageinit": function () {
        ko.applyBindings(characterModel, this);
    },
    "pagebeforeshow": function () {
        //refresh listview before page is shown
        $("ul", this).attr("data-role", "listview").listview().listview("refresh");
    }
}, "#character-page");  

上面的片段会在每次触发"#character-page"pagebeforeshow 事件时刷新你的样式(这是我们想要的),最后给你这个:

原来如此!希望这会有所帮助:)

而且,在我们忘记之前,

here's a demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 2019-06-16
    • 2015-01-25
    • 1970-01-01
    相关资源
    最近更新 更多