如何使用knockout、jquery和ASP.NET MVC创建可重复使用的控件?

8
我希望创建可重复使用的控件,用于knockout / jquery / asp.net mvc页面。例如,各种项目可以进行讨论(也就是一系列的评论)。我需要一个讨论控件,可以处理显示和添加评论等操作。 最初的想法是使用部分视图来注入HTML,然后有一个带有一些JavaScript代码的.js文件来设置knockout viewmodel。但这个方法似乎有些笨重。我在想是否有更好的方法来做到这一点,并将其打包成一个漂亮的控件?

作为不建设性的内容而投票关闭?我特别询问有关如何使用asp.net mvc/knocout和jquery创建可重复使用控件的专业知识。这符合stackoverflow的格式 :-) - Keith Nicholas
1
这个问题涉及的深度太大了,有很多种方法可以解决。一旦开始添加自定义和选项,复杂性就会急剧上升,你就需要讨论API的可用性以及组合与继承等问题。 - John Farrell
你在这方面有什么好运气吗?我需要做类似的事情 - 我使用编辑器模板来呈现子对象集合。这很好用,可以正确命名每个对象以进行MVC绑定,例如Category.Products [0] .ProductName等。现在我需要弄清楚如何将每个子对象的属性绑定到我的knockout视图模型。 - Ciarán Bruen
3个回答

3
下面是一种方法。
您需要一个独立的WebAPI控制器来处理客户端数据访问。
//Inside your CommentsApiController, for example
public IEnumerable<Comment> Get(int id)
{
    var comments = _commentsService.Get(int id);    //Call lower layers to get the data you need
    return comments;
}

您的MVC控制器具有返回PartialViewResults的操作。这是一个简单的动作,返回部分视图。

//Inside your MVC CommentsController, for example
public PartialViewResult CommentsList(int id)
{
    return PartialView(id);
}

你的部分视图呈现出你的标记,带有knockout绑定。我们为我们的HTML创建一个唯一的ID,以便将我们的knockout viewmodel绑定到页面的这个特定部分(避免与页面上的其他knockout组件冲突)。 所需的JavaScript(knockout viewmodels等)被包含在内,创建一个新的ViewModel并应用knockout绑定。

@{
    var commentsId = Model;    //passed from our MVC action
    var uniqueIid = System.Guid.NewGuid().ToString();
}
<section class="comments" id="@uniqueIid ">
    <ul data-bind="foreach: { data: Comments, as: 'comment' }">
        <li>
            <span data-bind="text: comment.Author"></span>
            <p data-bind="text: comment.Message"></p>
        </li>
    </ul>
</section>


@Scripts.Render("~/js/comments")    //using MVC Bundles to include the required JS
@{
    //generate the URL to our WebAPI endpoint.
    var url = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Comments", id = commentsId });
}
<script type="text/javascript">
    $(function() {
        var commentsRepository = new CommentsRepository('@url');
        var commentsViewModel = new CommentsViewModel(commentsRepository);

        var commentsElement = $('#@uniqueIid')[0];
        ko.applyBindings(commentsViewModel, commentsElement);
    });
</script>

在我们的 JavaScript 中,我们定义了 knockout 视图模型等内容。

var CommentsRepository = function(url) {
    var self = this;
    self.url = url;

    self.Get = function(callback) {
        $.get(url).done(function(comments) {
            callback(comments);
        });
    };
};

var CommentsViewModel = function (commentsRepository) {
    var self = this;
    self.CommentsRepository = commentsRepository;
    self.Comments = ko.observableArray([]);

    //self executing function to Get things started
    self.init = (function() {
        self.CommentsRepository.Get(function(comments) {
            self.Comments(comments);
        });
    })();
};

我们完成了!要使用这个新组件,我们可以使用RenderAction

@* inside our Layout or another View *@
<article>
    <h1>@article.Name</h1>
    <p>main page content here blah blah blah</p>
    <p>this content is so interesting I bet people are gonna wanna comment about it</p>
</article>
@Html.RenderAction("Comments", "CommentsList", new { id = article.id })

0
如果你说的“控件”是指我们从ASP.NET WebForms所熟悉的那种类型的控件,在ASP.NET MVC中最接近的东西就是HTML Helpers。由于它们基本上只是返回HtmlString的常规.NET方法,因此你可以轻松地将任何你想要的内容打包在一个包含这些方法和嵌入资源(用于JavaScript、CSS和图像文件)的程序集中。

不像WebForms那样,虽然目标是相似的... 它只是制作一个可重用的组件,与knockout连接。HTML Helpers很酷,这可能是解决方案的一部分,但是knockout意味着您必须在正确的时间将其注入到客户端创建过程中以注入您的“控件”。 - Keith Nicholas

0

我似乎无法使您的演示fiddle工作。另外,考虑到自动绑定存储库已经有一段时间没有更新了,您是否可以更新readme以包含已知问题等信息? :) - Morten Mertner
你说得对。我回家后几天内会把它修好。 - photo_tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接