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

发布于 2024-12-10 09:36:45 字数 215 浏览 0 评论 0原文

我想创建可重用的控件,用于淘汰赛/ jquery / asp.net mvc 页面

例如,各种项目可以进行讨论(评论列表)。我想要一个讨论控件来处理显示和添加注释等。

最初的想法是使用部分视图来注入 html,然后使用带有一些 javascript 的 .js 文件来设置淘汰视图模型。虽然看起来有点笨拙。我只是想知道是否有人有一种非常好的方法来完成这一切并将其包装为一个很好的控件?

I'm wanting to create reusable controls which get used on a knockout / jquery / asp.net mvc page

For instance, various items can have a discussion ( a list of comments). I want a discussion control which handles showing and adding comments, etc.

initial thoughts are to use a partial view to inject the html, and then have .js file with some javascript that sets up the knockout viewmodel. It seems a bit clunky though. I'm just wondering if someone has a really nice way of doing all this and packaging it up as a nice control?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

焚却相思 2024-12-17 09:36:45

这是一种方法。


您有一个单独的 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);
}

您的部分视图通过淘汰绑定渲染出您的标记。我们为 HTML 创建一个唯一的 ID,这样我们就可以将剔除视图模型绑定到页面的这个特定部分(避免与页面上的其他剔除组件发生冲突)。
我们需要的 JavaScript(淘汰视图模型等)被包含在内,创建了一个新的 ViewModel 并应用了淘汰绑定。

@{
    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 中,我们定义了淘汰视图模型等。

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 })

Here is one approach.


You have a separate WebAPI controller for handling the data access from the clientside.

//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;
}

Your MVC controllers have actions which return PartialViewResults. It is a simple action which returns a partial view.

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

Your partial view renders out your markup, with knockout bindings. We make a unique ID for our HTML so we can bind our knockout viewmodel to this specific section of the page (avoid conflicting with other knockout components on the page).
The JavaScript we require (knockout viewmodels etc) gets included, a new ViewModel created and knockout bindings applied.

@{
    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>

Inside our JavaScript, we define our knockout viewmodels etc.

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);
        });
    })();
};

And we're done! To use this new component, we can use 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 })
青芜 2024-12-17 09:36:45

如果“控件”指的是我们在 ASP.NET WebForms 中习惯的控件类型,那么 ASP.NET MVC 中最接近的控件就是 HTML 助手。因为它们基本上只是返回 HtmlString< 的常规 .NET 方法/code>,您可以轻松地将任何您想要的内容打包到包含这些方法的程序集中以及 嵌入资源(适用于 JavaScript、CSS 和图像文件)。

If, with "control", you mean the type of control we're used to from ASP.NET WebForms, the closest thing you have in ASP.NET MVC, is HTML Helpers. Since they are basically just regular .NET methods returning HtmlString, you can easily package anything you want inside an assembly containing these methods along with embedded resources (for JavaScript, CSS and image files).

漫雪独思 2024-12-17 09:36:45

如果您希望自动将 html 连接到淘汰赛,请查看我的插件 https:// github.com/phototom/ko-autobind

这仍然是一项正在进行的工作。要使用它,请查看演示小提琴 http://jsfiddle.net/rxXyC/11/

您还可以在 https://github.com/SteveSanderson/knockout 查看一些可用插件的列表/wiki/插件

If you are looking to automatically hookup your html to knockout, take a look at my plug-in at https://github.com/phototom/ko-autobind.

This is still a work-in progress. To use it, take a look a demo fiddle a http://jsfiddle.net/rxXyC/11/.

You can also see list of some available plug-in's at https://github.com/SteveSanderson/knockout/wiki/Plugins

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文