【问题标题】:Knockout: Removing Specific Item from Observable Array淘汰赛:从可观察数组中删除特定项目
【发布时间】:2019-05-16 03:26:04
【问题描述】:

我正在尝试通过列出可以添加和删除的游戏的简单列表来自学 Knockout.js。目前我一直坚持从可观察数组中删除特定项目。我有一系列游戏,我将它 foreach 绑定到一个 div,其中列出了每个游戏的标题、类型、平台等。每个游戏我也有一个删除按钮,但它们不起作用。我的设置与此处 Knockout 文档中的完全一样:

https://knockoutjs.com/documentation/click-binding.html

我在这里也发现了其他人有完全相同的问题:

Remove items from Knockout observable array

但是,列出的拼接解决方案对我不起作用。这次该函数确实触发了,但它没有从数组中删除正确的项,而是删除了数组中的最后一项,而不管单击了哪个删除按钮。我不知道为什么 Knockout 文档中的代码不起作用,以及为什么拼接解决方案不能正常工作。这是我的代码。请原谅所有硬编码的值。我现在只是想了解它的基本原理。

@{
    ViewBag.Title = "My Game List";
}

<head>
    <script type="text/javascript">
        $(function () {
            var game1 = ko.observable({
                title: 'Bioshock',
                genre: 'Shooter',
                platform: 'XBox 360',
                releaseDate: '8/21/2007',
                developer: 'Irrational Games',
                publisher: '2K Games',
                imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/6/6d/BioShock_cover.jpg/220px-BioShock_cover.jpg'
            });
            var game2 = ko.observable({
                title: 'The Legend of Zelda: Ocarina of Time',
                genre: 'RPG',
                platform: 'N64',
                releaseDate: '11/21/1998',
                developer: 'Nintendo',
                publisher: 'Nintendo',
                imageURL: 'https://cdn-images-1.medium.com/max/1600/1*n2iccNMASW983gg-ZmMdTw.jpeg'
            });
            var game3 = ko.observable({
                title: 'Devil May Cry',
                genre: 'Hack-n-Slash',
                platform: 'PS2',
                releaseDate: '8/23/2001',
                developer: 'Capcom',
                publisher: 'Capcom',
                imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/1/1e/DMC1FrontCover.jpg/220px-DMC1FrontCover.jpg'
            });
            var game4 = ko.observable({
                title: 'Comix Zone',
                genre: 'Beat-em-Up',
                platform: 'Sega Genesis',
                releaseDate: '8/2/1995',
                developer: 'Sega',
                publisher: 'Sega',
                imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/0/0e/Comix_Zone_Coverart.png/220px-Comix_Zone_Coverart.png'
            });
            var game5 = ko.observable({
                title: 'To the Moon',
                genre: 'Visual Novel',
                platform: 'PC',
                releaseDate: '9/1/2011',
                developer: 'Freebird Games',
                publisher: 'Freebird Games',
                imageURL: 'https://steamcdn-a.akamaihd.net/steam/apps/206440/capsule_616x353.jpg?t=1519836062'
            });
            function gamesViewModel() {
                var self = this;
                self.gamesList = ko.observableArray([game1, game2, game3, game4, game5]);
                self.gameToAdd = ko.observable({
                    title: 'Mass Effect',
                    genre: 'RPG',
                    platform: 'PC',
                    releaseDate: '11/20/2007',
                    developer: 'BioWare',
                    publisher: 'EA',
                    imageURL: 'https://steamcdn-a.akamaihd.net/steam/apps/17460/header.jpg?t=1447351599'
                });
                self.addGame = function () {
                    self.gamesList.push(self.gameToAdd);
                };
                self.removeGame = function (gameToRemove) {
                    self.gamesList.remove(gameToRemove);
                    //var gameIndex = self.gamesList.indexOf(gameToRemove);
                    //self.gamesList.splice(gameIndex, 1);
                };
            }
            ko.applyBindings(new gamesViewModel);
        });

    </script>
</head>
<div class="jumbotron">
    <h1>TOP 5 GAMES</h1>
</div>

<div class="row">
    <h4>Games</h4>
    <div class="card-columns" data-bind="foreach: gamesList">
        <div class="card">
            <a data-bind="attr: {href: imageURL}" target="_blank">
                <img class="card-img-top" data-bind="attr: {src: imageURL}" />
            </a>
            <div class="card-body">
                <h5 class="card-title" data-bind="text: title"></h5>
                <div class="card-text">
                    <div>
                        <span>Genre: </span>
                        <span data-bind="text: genre" />
                    </div>
                    <div>
                        <span>Platform: </span>
                        <span data-bind="text: platform" />
                    </div>
                    <div>
                        <span>Release Date: </span>
                        <span data-bind="text: releaseDate" />
                    </div>
                    <div>
                        <span>Developer: </span>
                        <span data-bind="text: developer" />
                    </div>
                    <div>
                        <span>Publisher: </span>
                        <span data-bind="text: publisher" />
                    </div>
                </div>
                <button class="btn btn-danger" data-bind="click: $parent.removeGame">-Remove</button>
            </div>
        </div>
    </div>
    <button data-bind="click: addGame">+Add</button>
</div>

【问题讨论】:

    标签: arrays knockout.js foreach


    【解决方案1】:

    在 knockoutjs 中使用“()”非常棘手。您的代码很完美,但问题就在这里。游戏对象(game1、game2、...)被声明为可观察(我会将它们保留为普通变量),并且您在 gamesList 中推送可观察引用而不是实际值。这就是为什么 remove 方法无法识别它的原因。

    要么声明没有 observable 的游戏对象,要么在列表中用“()”分配它们。

     $(function () {
                var game1 = ko.observable({
                    title: 'Bioshock',
                    genre: 'Shooter',
                    platform: 'XBox 360',
                    releaseDate: '8/21/2007',
                    developer: 'Irrational Games',
                    publisher: '2K Games',
                    imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/6/6d/BioShock_cover.jpg/220px-BioShock_cover.jpg'
                });
                var game2 = ko.observable({
                    title: 'The Legend of Zelda: Ocarina of Time',
                    genre: 'RPG',
                    platform: 'N64',
                    releaseDate: '11/21/1998',
                    developer: 'Nintendo',
                    publisher: 'Nintendo',
                    imageURL: 'https://cdn-images-1.medium.com/max/1600/1*n2iccNMASW983gg-ZmMdTw.jpeg'
                });
                var game3 = ko.observable({
                    title: 'Devil May Cry',
                    genre: 'Hack-n-Slash',
                    platform: 'PS2',
                    releaseDate: '8/23/2001',
                    developer: 'Capcom',
                    publisher: 'Capcom',
                    imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/1/1e/DMC1FrontCover.jpg/220px-DMC1FrontCover.jpg'
                });
                var game4 = ko.observable({
                    title: 'Comix Zone',
                    genre: 'Beat-em-Up',
                    platform: 'Sega Genesis',
                    releaseDate: '8/2/1995',
                    developer: 'Sega',
                    publisher: 'Sega',
                    imageURL: 'https://upload.wikimedia.org/wikipedia/en/thumb/0/0e/Comix_Zone_Coverart.png/220px-Comix_Zone_Coverart.png'
                });
                var game5 = ko.observable({
                    title: 'To the Moon',
                    genre: 'Visual Novel',
                    platform: 'PC',
                    releaseDate: '9/1/2011',
                    developer: 'Freebird Games',
                    publisher: 'Freebird Games',
                    imageURL: 'https://steamcdn-a.akamaihd.net/steam/apps/206440/capsule_616x353.jpg?t=1519836062'
                });
                function gamesViewModel() {
                    var self = this;
                    self.gamesList = ko.observableArray([game1(), game2(), game3(), game4(), game5()]);
                    self.gameToAdd = ko.observable({
                        title: 'Mass Effect',
                        genre: 'RPG',
                        platform: 'PC',
                        releaseDate: '11/20/2007',
                        developer: 'BioWare',
                        publisher: 'EA',
                        imageURL: 'https://steamcdn-a.akamaihd.net/steam/apps/17460/header.jpg?t=1447351599'
                    });
                    self.addGame = function () {
                        self.gamesList.push(self.gameToAdd);
                    };
                    self.removeGame = function (gameToRemove) {
                        self.gamesList.remove(gameToRemove);
                        //var gameIndex = self.gamesList.indexOf(gameToRemove);
                        //self.gamesList.splice(gameIndex, 1);
                    };
                }
                ko.applyBindings(new gamesViewModel);
            });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="jumbotron">
        <h1>TOP 5 GAMES</h1>
    </div>
    
    <div class="row">
        <h4>Games</h4>
        <div class="card-columns" data-bind="foreach: gamesList">
            <div class="card">
                <a data-bind="attr: {href: imageURL}" target="_blank">
                    <img class="card-img-top" data-bind="attr: {src: imageURL}" />
                </a>
                <div class="card-body">
                    <h5 class="card-title" data-bind="text: title"></h5>
                    <div class="card-text">
                        <div>
                            <span>Genre: </span>
                            <span data-bind="text: genre" />
                        </div>
                        <div>
                            <span>Platform: </span>
                            <span data-bind="text: platform" />
                        </div>
                        <div>
                            <span>Release Date: </span>
                            <span data-bind="text: releaseDate" />
                        </div>
                        <div>
                            <span>Developer: </span>
                            <span data-bind="text: developer" />
                        </div>
                        <div>
                            <span>Publisher: </span>
                            <span data-bind="text: publisher" />
                        </div>
                    </div>
                    <button class="btn btn-danger" data-bind="click: $parent.removeGame">-Remove</button>
                </div>
            </div>
        </div>
        <button data-bind="click: addGame">+Add</button>
    </div>

    【讨论】:

    • 谢谢!做到了!知道何时何地放置或不放置括号在 Knockout 中确实相当棘手。希望我最终能掌握它。
    猜你喜欢
    • 2013-06-02
    • 2012-09-08
    • 2014-05-18
    • 2015-03-20
    • 2015-10-05
    • 2016-10-14
    • 1970-01-01
    • 2015-07-14
    相关资源
    最近更新 更多