如何使用JSON供电Backbone.js的互动应用 [英] How to use JSON to power interactive Backbone.js app
问题描述
我的工作从Flash转换成一系列互动教育应用为Javascript,和我的团队正计划使用Backbone.js的为框架。每个这些应用的基本上是场景的集合present信息给用户和/或促使一些相互作用,无论是在问题或交互式窗口小部件的形式。我们正在考虑为应用程序的基本结构如下:
I'm working on converting a series of interactive educational apps from Flash to Javascript, and my team is planning on using Backbone.js as the framework. Each of these apps is basically a collection of scenes that present information to the user and/or prompt some interaction, either in the form of questions or interactive widgets. The basic structure we're considering for the app is as follows:
- 一组包含每个应用程序,特定信息的JSON文件,如多少种不同的场景或对象的应用程序有,不同的消息及/或部件显示给用户,等等。
- 一套骨干网(大概下划线)的模板管理如何显示导航,邮件,等等。
- 主干意见/路由器/模型集合,以方便在应用场景之间导航和处理用户交互
- 内建原生的JavaScript一些互动的小部件
问题是,当然,我是一个新手,当涉及到骨干。我做了我的方式,通过一些基本的教程,但我有麻烦的静态JSON文件整合骨干。
Trouble is, of course, is that I'm a novice when it comes to Backbone. I've made my way through some of the basic tutorials but am having trouble integrating Backbone with static JSON files.
比方说,我已经将要显示勾画出三个场景下非常基本的JSON文件:
Let's say I have the following very basic JSON file that lays out three scenes to be displayed:
var scenes = [
{
"name": "Introduction",
"label": "Introduction",
"message": "Welcome to this app"
},
{
"name": "Exercise",
"label": "Exercise",
"message": "If this were a real app, there'd be some sort of exercise here"
},
{
"name": "Conclusion",
"label": "Conclusion",
"order": "Thank you for completing this app"
}
]
我需要什么,以及我想要做的,是有骨气生成一个导航的小工具,让用户这些场景之间的导航并显示每个场景的消息。 (这显然是现实世界的应用程序的一个令人难以置信的简化版本。)
What I need, and what I'm trying to do, is to have Backbone generate a navigation widget that lets users navigate between these scenes and to display the message for each scene. (This is obviously an incredibly simplified version of the real-world app.)
下面是我已经试过:
// simplified object containing stage information
var stages = [
{
"name": "Introduction",
"label": "Introduction",
"message": "Welcome to this app"
},
{
"name": "Exercise",
"label": "Exercise",
"message": "If this were a real app, there'd be some sort of exercise here"
},
{
"name": "Conclusion",
"label": "Conclusion",
"order": "Thank you for completing this app"
}
];
$(function(){
// create model for each stage
StageModel = Backbone.Model.extend({});
// create collection for StageModel
StageModelList = Backbone.Collection.extend({
model: StageModel
});
var stageModelList = new StageModelList();
// create view for list of stages
StageListView = Backbone.View.extend({
el: $("#stageNav"),
initialize: function() {
// if stages are added later
stagemodellist.bind('add',this.createStageList, this);
},
events: {
'click .stageListItem' : 'selectStage'
},
createStageList: function(model) {
$("#stageList").append("<li class='stageListItem'>"+model.label+"</li>");
},
selectStage: function() {
this.router.navigate("stage/"+this.stage.name,true);
}
});
// create view for each stages
StageView = Backbone.View.extend({
el: $("#stage"),
initialize: function(options) {
// get stage variable from options
this.stage = this.options.stage;
// display stage
createOnEnter(this.stage);
},
createOnEnter: function(stage) {
$("#stageLabel").html(stage.label);
$("#stageMsg").html(stage.message);
}
});
// create router
AppRouter = Backbone.Router.extend({
initialize: function() {
Backbone.history.start();
// create collection
new StageModelList();
// create view when router is initialized
new StageListView();
// loop through stages and add each to StageModelList
for (var s in stages) {
StageModelList.add(stages[s]);
}
},
routes: {
"stage/:stage" : "renderStage"
},
renderStage: function(stage) {
// display StageView for this stage
new StageView({stage:stage});
}
});
var App = new AppRouter();
});
和HTML:
<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script class="jsbin" src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script class="jsbin" src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="js/ilo4.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<p>My pathetic attempt at a Backbone.js app</p>
<div id="stageNav">
<ul id="stageList">
</ul>
</div>
<div id="stage">
<div id="stageLabel">
</div>
<div id="stageMsg">
</div>
</div>
</body>
</html>
(你还可以看到一个jsbin版本在这里: http://jsbin.com/ iwerek /编辑#的JavaScript,HTML,现场)。
现在这并不做任何事情,很遗憾。
Right now this doesn't do anything, unfortunately.
我知道,我做这么多事情错在这里,有的认为我踢周围的问题:
I know that I'm doing so many things wrong here, and some questions that I'm kicking around:
- 请我甚至需要一个路由器?
- 我是否需要初始化集合作为一个变量?
- 有没有到模型阶段的列表? 绑定一个更好的办法
- Do I even need a router?
- Do I need to initialize the collection as a variable?
- Is there a better way to bind the model to the list of stages?
A
推荐答案
您实际上不太远了。
我克隆你的jsbin和固定它,所以它的工作原理:链接
I've cloned your jsbin and fixed it up so it works: link
我认为我的回答你的问题。我评论它彻底pretty解释发生了什么事情。
I submit that as my answer to your question. I've commented it pretty thoroughly to explain what's going on.
看看,希望它可以帮助。
Take a look, hopefully it helps.
编辑:什么是地狱,我把code在这里也:
what the hell, I'll put the code here as well:
// simplified object containing stage information
window.stages = [
{
"name": "Introduction",
"label": "Introduction",
"message": "Welcome to this app"
},
{
"name": "Exercise",
"label": "Exercise",
"message": "If this were a real app, there'd be some sort of exercise here"
},
{
"name": "Conclusion",
"label": "Conclusion",
"message": "Thank you for completing this app"
}
];
$(function(){
// StageModel: no need to extend if you're not adding anything.
StageModel = Backbone.Model;
// StageCollection
StageCollection = Backbone.Collection.extend({
model: StageModel
});
// create view for list of stages
StageCollectionView = Backbone.View.extend({
el: $("#stageNav"),
initialize: function() {
// if stages are added later
this.collection.bind('add', this.createStageListItem, this);
},
events: {
'click .stageListItem' : 'selectStage'
},
// I'm adding the model's cid (generated by backbone) as the
// id of the 'li' here. Very non-ideal, as one of the points
// of backbone et al. is to keep from embedding and retrieving
// data from the DOM like this.
//
// Perhaps better would be to create a StageListItemView and
// render one for each model in the collection, perhaps like:
//
// createStageListItem: function(model) {
// this.$('#stageList').append(new StageListItemView({model: model});
// }
//
// where you have a StageListItemView that knows how to render
// itself and can handle click events and communicate with the
// collectionview via events.
//
// At any rate, this string-munging will suffice for now.
createStageListItem: function(model) {
this.$("#stageList").append("<li id=\"" + model.cid + "\" class='stageListItem'>" + model.get('label') + "</li>");
},
// Use backbone's event system, it's pretty awesome. Not to mention
// that it helps to decouple the parts of your app.
//
// And note that you can pass arguments when you trigger an event.
// So any event handler for the 'new-stage' event would receive
// this model as its first argument.
selectStage: function(event) {
var cid = $(event.target).attr('id');
this.trigger('new-stage', this.collection.getByCid(cid));
},
// This was a missing puzzle piece. Your StageCollectionView wasn't
// being rendered at all.
//
// Backbone convention is to call this function render, but you could
// call it whatever you want, as long as you, well, end up _calling_ it.
render: function() {
var self = this;
this.collection.each(function(model) {
self.createStageListItem(model);
});
return this;
}
});
// StageView,
StageView = Backbone.View.extend({
el: $("#stage"),
// We're going to assume here that we get passed a
// newStageEventSource property in the options and
// that it will fire a 'new-stage' event when we need
// to load a new stage.
initialize: function(options) {
this.eventSource = options.newStageEventSource;
this.eventSource.bind('new-stage', this.loadAndRenderStage, this);
},
// A load function to set the StageView's model.
load: function(model) {
this.model = model;
return this;
},
render: function() {
$("#stageLabel").html(this.model.get('label'));
$("#stageMsg").html(this.model.get('message'));
},
loadAndRenderStage: function(stage) {
this.load(stage);
this.render();
}
});
// Instatiate a StageCollection from the JSON list of stages.
// See Backbone docs for more, but you can pass in a list of
// hashes, and the Collection will use its model attribute to
// make the models for you
var stageCollection = new StageCollection(stages);
// View constructors take an options argument. Certain properties
// will automatically get attached to the view instance directly,
// like 'el', 'id', 'tagName', 'className', 'model', 'collection'.
var stageCollectionView = new StageCollectionView({
collection: stageCollection
});
// Instantiate the StageView, passing it the stageCollectionView in
// the options for it to listen to.
var stageView = new StageView({
newStageEventSource: stageCollectionView
});
// Last step, we need to call 'render' on the stageCollectionView
// to tell it to show itself.
stageCollectionView.render();
});
这篇关于如何使用JSON供电Backbone.js的互动应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!