淘汰赛:从可观察阵列中删除特定项目

时间:2018-12-14 21:00:02

标签: arrays knockout.js foreach

我试图通过列出一个可以添加和删除的游戏的简单列表来自学Knockout.js。目前,我仍坚持从可观察的数组中删除特定项目。我有一系列游戏,并且将foreach绑定到div,该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>

1 个答案:

答案 0 :(得分:0)

  

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

要么声明不可观察的游戏对象,要么在列表中为其分配“()”。

 $(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>