在过去的几周里,我一直(试图)使用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()
}目前,我主要关注的是展示“创造”的一面。简单地显示tweet数据是非常简单的。具体来说,我想知道我对组件的输入/输出应该如何工作。
问题
1) 如果我从我的父母视图模型到我的组件传递一些JSON/JS对象/数据集,为什么我需要重新定义在我的组件中可观察到的?
我是说这个:
self.tweet = params.tweet;为什么有这个必要?如果我不这样做,并试图引用我的模板上的tweet.tweet_user_name (或params.tweet.tweet_user_name),我会得到以下错误:
ReferenceError: tweet is not defined为什么我的模板不知道传递到组件构造函数中的变量?回想一下,构造函数的定义如下:
function TweetViewModel(params) { //SNIP如果我必须在组件上重新定义我的对象,那么对它所做的更改会被映射回父视图模型上的tweetData吗?
2) 当我有多个输入和多个输出源时,我如何保持它们都与敲除映射保持一致,而又不对未定义的属性产生兴趣而不观察变化?
如果你看一下我的组件,你会发现我有两个推特信息的输入源。一个是来自params的数据,另一个是我向服务器发出的从Twitter获取数据的AJAX请求。
这些数据源看起来完全不同。理想情况下,我希望我的“模型”看起来好像我已经在上面定义了它,一个'tweet‘对象,有7个可观察到的属性,从images到tweet_id。来自我父母视图模型上的tweetData的数据应该是这样的,但是当我期望创建一条tweet时,它可能是空的。来自AJAX请求的数据将是我需要格式化的twitter的原始响应。
具体来说,我有以下情况和问题:
tweetData 总是包含我喜欢的模型的信息或大纲。这种情况通常发生在tweet是直接创建的时候,除了我的父母视图模型上的可观察对象之外,它并不存在。我传递给组件的变量是我希望通过组件上的Knockout映射来填充的东西--我不需要传入一个空对象,所有属性都已经格式化了。
params.tweet self.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选项设置黑名单-考虑到多少数据推特返回,这是很多属性需要手动忽略!此外,Twitter返回的属性名与我试图使用的属性名称不匹配(见上面),因此我甚至不确定剔除映射是否适合这里。
3) 我是如何不正确地使用Knockout.js +映射+组件的,对于我试图创建的组件来说,什么是好的启动结构?
我在这里束手无策,我很乐意尝试任何对我提出的建议。理想情况下,我希望尽可能多地回答我的问题。
发布于 2015-07-27 11:20:14
self.tweet.tweet_id(newValue))来设置它们的值,但是如果使用等号,则通常会丢弃绑定变量。ko.mapping什么也救不了你。https://stackoverflow.com/questions/31650473
复制相似问题