繁体   English   中英

我完全不了解淘汰表.js映射或组件如何工作?

[英]I don't understand how knockout.js mapping or components work at all?

在过去的几周里,我一直在(尝试)使用Knockout.js映射和组件,但坦率地说,这很糟糕。 我发誓我会丢失一些使一切正常工作的魔术作品,因为此刻我试图用它生产的一切都感觉非常混乱和混乱,因此,大多数东西都无法正常工作。

我已经通读了文档,但几乎没有满意或没有帮助。

用例

我有一个主要的视图模型,但这不是故事的主角。 这是我要构建的可重用组件。 我们称之为TweetViewModel 该组件取决于params.action是设置为“ create”还是“ show”,将允许用户输入有关tweet的信息,或将其显示给他们:

组件视图模型

define(['knockout','ko.mapping', 'jquery', 'text!components/tweet/tweet.html'], function(ko, koMapping, $, htmlString) {
    function TweetViewModel(params) {

        var self = this;

        self.tweet = params.tweet;
        self.action = params.action;

        self.tweetUrl = ko.observable();
        self.tweetUrl.subscribe(function(value) {
            var valueOfTwitterUrlField = value;

            // Check that the entered URL contains 'twitter' before sending a request (perform more thorough validation serverside)
            if (valueOfTwitterUrlField.indexOf('twitter.com') !== -1) {

                var explodedVals = valueOfTwitterUrlField.split('/');
                var id = explodedVals[explodedVals.length - 1];

                $.ajax('/myproj/create/retrievetweet/' + id, {
                    dataType: 'json',
                    type: 'GET',
                    success: function (response) {
                    }
                });
            }
            // Allow default action
            return true;
        });
    }

    return { viewModel: TweetViewModel, template: htmlString };
});

模板

<!-- ko if: action == 'show' -->
<div class="card twitter-card">

</div>
<!-- /ko -->
<!-- ko if: action == 'create' -->
<div class="card twitter-card create">
    <label>Tweet URL</label>
    <input type="url" name="tweet_url" id="tweet_url" data-bind="textInput: tweetUrl" />
    <hr/>
    <p>Alternatively, if the tweet is no longer available, enter the tweet information below</p>
    <div class="tweeter-details">
        <img src="" />
        <span class="tweeter-screen-name" data-bind="text: tweet.tweet_user_screen_name"></span>
        <label>Username</label>
        <input type="text" class="tweeter-name" data-bind="value: tweet.tweet_user_name" />
    </div>
    <textarea class="tweet-text" data-bind="text: tweet.tweet_text"></textarea>
    <div class="date-input">
        <datetime params="value: tweet.tweet_created_at, type: 'datetime'"></datetime>
    </div>
</div>
<ul class="tweet-images-list" data-bind="template: { name: 'tweet-images-template', foreach: tweet.images }">
</ul>
<div class="tweet-images-details"></div>
<!-- /ko -->
<script type="text/html" id="tweet-images-template">

</script>

通过以下HTML调用此模板:

<tweet params="action: 'create', tweet: tweetData"></tweet>

action是模板中我感兴趣的一部分,它会显示和tweet: tweetData是我希望父视图模型与组件进行通信的方式。 tweetData可能是具有以下属性的对象:

self.tweet = {
    tweet_id: ko.observable(),
    tweet_text: ko.observable(),
    tweet_user_name: ko.observable(),
    tweet_user_screen_name: ko.observable(),
    tweet_created_at: ko.observable(),
    tweet_parent_id: ko.observable(),
    images: ko.observableArray()
}

目前,我主要关心的是展示事物的“创造”方面。 仅显示推文数据非常简单。 具体来说,我想知道组件上的输入/输出应该如何工作。

问题

1) 如果我要从父视图模型传递一些JSON / JS对象/数据集到我的组件,为什么还要在我的组件中重新定义可观察对象呢?

我的意思是:

self.tweet = params.tweet;

为什么这是必要的? 如果我不这样做,并尝试在模板(或params.tweet.tweet_user_name )上引用tweet.tweet_user_nametweet.tweet_user_name出现以下错误:

ReferenceError: tweet is not defined

为什么我的模板不知道传递给组件构造函数的变量? 回想一下我的构造函数是这样定义的:

function TweetViewModel(params) {  //SNIP

如果必须在组件上重新定义对象,是否将对它所做的更改映射回tweetData上的tweetData?

2) 当我有多个输入源和多个输出源时,如何使它们都与剔除映射保持一致,而又不对未定义的属性造成影响并且不观察更改?

如果看一下我的组件,您会看到我有两个输入源,用于发布tweet信息。 一个是来自params的数据,另一个是我向服务器发出的AJAX请求,以从Twitter API提取数据。

这些数据源看起来完全不同。 理想情况下,我希望我的“模型”看起来就像我在上面定义的一样,是一个具有7个可观察属性的“ tweet”对象,范围从imagestweet_id 来自我的tweetData上tweetData的数据应该看起来像这样,但是当我期望创建一条tweet时,它可能为空。 来自我的AJAX请求的数据将是我需要格式化的twitter API的原始响应。

具体来说,我有以下情况和问题:

  • 我不能保证tweetData将始终包含信息或我的首选模型的轮廓。

通常在完全创建推文且除我的parentviewmodel上的可观察对象之外不存在某条推文时,会发生这种情况。 希望传递给组件的变量是我希望通过组件上的Knockout映射来填充的-我不需要传递具有已格式化所有属性的空对象。

  • 当我用从AJAX请求中收到的数据覆盖我的params.tweet值时,它实际上不会覆盖self.tweet的值,并且不会更新我的数据绑定

考虑以下代码:

self.tweet.tweet_text = ko.observable("foo")

$.ajax('/myproj/create/retrievetweet/' + id, {
dataType: 'json',
type: 'GET',
success: function (response) {
    self.tweet = {
        tweet_id: ko.observable(response.id),
        tweet_text: ko.observable(response.text),
        tweet_user_name: ko.observable(response.user.name),
        tweet_user_screen_name: ko.observable(response.user.screen_name),
        tweet_created_at: ko.observable(response.created_at),
        tweet_parent_id: ko.observable(response.in_reply_to_status_id),
        images: ko.observableArray(response.entities.media)
    }
}
});

由于某些原因,此成功回调实际上不会在我的模板上设置任何内容。 我绑定到tweet.tweet_text文本绑定仍将显示“ foo”,即使在我收到有效的响应并应按照上面的定义重设它之后也是如此。

将敲除映射与服务器的响应一起使用更令人恶心。 没有办法将我要观察的属性列入白名单,我只能通过ignore options设置将其列入黑名单-考虑到Twitter返回的数据量,有很多属性需要手动忽略! 另外,Twitter返回的属性名称与我要使用的属性名称不匹配(请参见上文),因此我什至不确定敲除映射是否适合此处。

3) 我怎么一直没有正确使用Knockout.js +映射+组件,对于我要创建的组件来说,什么是一个很好的起始结构?

我的智慧到此为止,我会很乐意尝试所有提出的建议。 理想情况下,我希望尽可能多地回答我的问题。

  1. 组件具有自己的视图模型,因为根据设计,它们是可重用的,并且可以在具有不同视图模型的不同应用程序中使用。 如果要引用主视图模型,请将其作为参数传递。

  2. 不要重新分配绑定的可观察变量或包含绑定的可观察变量的变量。 您可以使用正常的函数调用(例如self.tweet.tweet_id(newValue) )来设置它们的值,但是如果使用等号,则通常会丢弃绑定变量。

  3. 我想,如果您希望将值列入白名单,则最好创建并分配变量。 ko.mapping不会为您节省任何费用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM