主干绑定 AMD 项目中 json 文件中的数据

Backbone bind data from json file in AMD project

本文关键字:json 文件 数据 项目 绑定 AMD      更新时间:2023-09-26

我是Backbone的新手,所以我正在尝试一下。我基于这个例子建立了一个模块化项目。我还以与本教程类似的方式实现了页面之间的转换。现在,我被困在 json 文件的一个视图中的数据绑定中。我尝试了很多方法,但没有运气。

这是我的代码:

我有一个"页面管理器",它根据用户的页面处理视图结构以及过渡输入和转换输出功能:

define([
    "backbone",
    "config-all"
], function(Backbone, Config) {
    var pagesManagerView = Backbone.View.extend({
        el: $("#page"),
        initialize: function(options) {
            var $this = this;

            this.currentPage = null;
            this.backDetected = false;
            this.transitionType = "";
            this.isFirstPageLoad = false;
            this.previousPageMapItem = null;
            this.currentPageMapItem = null;

            this.pagesMap = {
                "home": {
                    index: 0,
                    fragment: "",
                    regex: /^home$/,
                    pageId: "home"
                }, 
                "projects": {
                    index: 1,
                    fragment: "projects",
                    regex: /^projects$/,
                    pageId: "projects"
                },
                "users": {
                    index: 2,
                    fragment: "users",
                    regex: /^users$/,
                    pageId: "users"
                }
            };
            $(document).ready(function(evt) {
            });
        },
        getPageFromMapByFragment: function(fragment) {
            if (fragment === "") 
                fragment = "home";
            for (var i in this.pagesMap) {
                if (fragment.match(this.pagesMap[i].regex))
                    return this.pagesMap[i];
            }
            return this.pagesMap[fragment];
        },
        updatePageHistoryState: function() {
            var currentFragment = Backbone.history.getFragment();
            this.currentPageMapItem = this.getPageFromMapByFragment(currentFragment);
            this.backDetected = 
                this.currentPageMapItem && 
                this.previousPageMapItem && 
                this.currentPageMapItem.index < this.previousPageMapItem.index;

            this.transitionType = Config.transitions.PageTransitionType.VERTICAL;

            this.isFirstPageLoad = this.previousPageMapItem === null;
            this.previousPageMapItem = this.currentPageMapItem;
        },
        renderPage: function(pageView) {
            var $this = this;

            this.transitionType = Config.transitions.PageTransitionType.VERTICAL;
            if (this.$el.find("#page-out").length === 0)
                this.$el.append('<div id="page-out" class="page-out"></div>');
            var elIn = this.$el.find("#page-in");
            var elOut = this.$el.find("#page-out");

            if (this.currentPage) {
                var currentPageHtml = elIn.html();
                elOut.html(currentPageHtml);
                elOut.show();
                this.currentPage.$el = elOut;
                this.currentPage.transitionOut(this.transitionType, this.backDetected);
            }
            pageView.$el = elIn;
            pageView.render();
            pageView.transitionIn(this.isFirstPageLoad, this.transitionType, this.backDetected, function() {
            });
            this.currentPage = pageView;
            return true;
        }
    });
    return pagesManagerView;
});

然后我有一个抽象页面,其中有所有视图共享的函数,包括实际的转换函数:

define(['backbone', 'config-all'],
    function(Backbone, Config) {
    var abstractPageView = Backbone.View.extend({
        render: function() {
        },
        transitionIn: function(isFirstPageLoad, transitionType, transitionBack, callback) {
            switch (transitionType) {
                case Config.transitions.PageTransitionType.VERTICAL:
                    this.transitionInVertical(isFirstPageLoad, transitionBack, callback);
                    break;
            }
        },
        transitionOut: function(transitionType, transitionBack, callback) {
            switch (transitionType) {
                case Config.transitions.PageTransitionType.VERTICAL:
                    this.transitionOutVertical(transitionBack, callback);
                    break;
            }
        },

        transitionInVertical: function(isFirstPageLoad, transitionBack, callback) {
            var $this = this;
            var startPosTop = transitionBack
                ? 0 - $("#page").height()
                : 0 + $("#page").height();
            if (isFirstPageLoad)
                startPosTop = 0;
            this.$el.css({
                top: startPosTop
            });
            this.$el.animate({
                top: 0
            }, {
                duration: 500,
                easing: "easeOutQuad",
                done: function() {
                    if (callback && typeof callback === "function")
                        callback();
                }
            });
        },
        transitionOutVertical: function(transitionBack, callback) {
            var $this = this;
            var endPosTop = transitionBack
                ? $("#page").height()
                : -$("#page").height();
            this.$el.animate({
                top: endPosTop
            }, {
                duration: 500,
                easing: "easeOutQuad",
                done: function() {
                    if (callback && typeof callback === "function")
                        callback();
                    // @important remove(); 
                    // this must be called upon transition out complete
                    $this.remove();
                }
            });
        }
    });
    return abstractPageView;
});

然后有一个观点:

define([
    'jquery',
    'underscore',
    'backbone',
    'views/abstract-page',
    'views/sidebar/SidebarView',
    'text!templates/contributors/contributorsTemplate.html'
], function ($, _, Backbone, AbstractPage, SidebarView, contributorsTemplate) {
    var ContributorsView = AbstractPage.extend({
        initialize: function () {
        },
        render: function () {
            $('.menu li').removeClass('active');
            $('.menu li a[href="' + window.location.hash + '"]').parent().addClass('active');
            // render my template
            this.$el.html(contributorsTemplate);
            // add the sidebar 
            var sidebarView = new SidebarView();
            sidebarView.render();
        }
    });
    return ContributorsView;
});

目前,贡献者模板.html只有静态html,但我想从json文件中绑定一些数据。我对如何使用模型、集合以及如何将数据绑定到模板中感到非常困惑,因为模板是使用 Require 调用的.js并且不知道如何将数据注入div。

这是我的收藏:

define([
  'underscore',
  'backbone',
  'models/contributor/ContributorModel'
], function(_, Backbone, ContributorModel){
    var ContributorsCollection = Backbone.Collection.extend({
        model: ContributorModel,
        url: "js/data/data.json",
        initialize: function(models, options) {
        }
    });
  return ContributorsCollection;
});

和模型:

define([
  'underscore',
  'backbone'
], function(_, Backbone) {
  var ContributorModel = Backbone.Model.extend({
    defaults : {
    }
  });
  return ContributorModel;
});

和我的 JSON 文件:

[
    {
        "name": "Google",
        "image": "/images/logo.jpg",
        "link": "http://www.google.co.uk"
    },
    {
        "name": "Yahoo",
        "image": "/images/logo.jpg",
        "link": "http://www.yahoo.co.uk"
    },
    {
        "name": "Apple",
        "image": "/images/logo.jpg",
        "link": "http://www.apple.com"
    },
    {
        "name": "Gizmodo",
        "image": "/images/logo.jpg",
        "link": "http://www.gizmodo.co.uk"
    },
    {
        "name": "Engadget",
        "image": "/images/logo.jpg",
        "link": "http://www.engadget.com"
    },
    {
        "name": "9to5 Mac",
        "image": "/images/logo.jpg",
        "link": "http://www.9to5mac.com"
    }

]

在我看来,我真的不明白如何做这样的事情(来自模块化骨干示例(:

  // Using Underscore we can compile our template with data
  var data = {};
  var compiledTemplate = _.template( projectListTemplate, data );
  // Append our compiled template to this Views "el"
  this.$el.append( compiledTemplate );

我已经尝试过但没有成功,我不明白如何使用data{}.抱歉,如果问题很长,并且我可能错过了一些Backbone专家可能识别的简单内容。我真的需要一些适合我的代码的示例的帮助,几天来一直在敲打我的头!

提前感谢!

代码更新
试图应用查理布朗的答案但没有运气,我确定我仍然在做一些愚蠢的事情:

收集:

define([
  'underscore',
  'backbone',
  'models/contributor/ContributorModel'
], function(_, Backbone, ContributorModel){
    var ContributorsCollection = Backbone.Collection.extend({
        model: ContributorModel,
        url: "js/data/data.json",
        initialize: function(models, options) {
        }
    });
  return ContributorsCollection;
});

视图:

define([
    'jquery',
    'underscore',
    'backbone',
    'views/abstract-page',
    'views/sidebar/SidebarView',
    'collections/contributors/ContributorsCollection',
    'text!templates/contributors/contributorsTemplate.html'
], function ($, _, Backbone, AbstractPage, SidebarView, ContributorsCollection, contributorsTemplate) {
    var ContributorsView = AbstractPage.extend({
        initialize: function () {
        },
        render: function () {
            $('.menu li').removeClass('active');
            $('.menu li a[href="' + window.location.hash + '"]').parent().addClass('active');
            var contrCollection = new ContributorsCollection();
            //compile the template
            var data = {items: contrCollection.toJSON() };
            var compiledTemplate = _.template(contributorsTemplate, data);
            // render my template
            this.$el.html(compiledTemplate);
            // add the sidebar 
            var sidebarView = new SidebarView();
            sidebarView.render();
        }
    });
    return ContributorsView;
});

模板:

<div class="main" id="contacts">    
    <h2>Contributors</h2>
        <div id="projects-list">
            <% _.each(items, function(item) { %>
                <%= item.name %>
                <%= item.image %>
                <%= item.link %>
            <% } %>
        </div>
</div>

那我做错了什么呢?

再次感谢

答案 2,基于您更新的代码。

您没有显示如何连接事物并使应用程序运行,但我想它在您的主文件中.js(requirejs SCRIPT 标签中的数据主文件(。

很明显,您没有得到任何结果,因为:1. 您要在渲染方法中创建新集合2. 您没有fetch该集合,因此您的数据永远不会加载!

怀疑你没有读过我推荐给你的文章,因为你正在做的事情是哭泣CollectionView,但出于学习目的,没关系。 阅读! ;)

var ContributorsView = AbstractPage.extend({
        initialize: function (options) {
          //Backbone automatically stores options.collection on this.collection
          //whenever the collection is reset, re-render this view!
          this.listenTo(this.collection, "reset", this.render);
        },
    render: function () {
        $('.menu li').removeClass('active');
        $('.menu li a[href="' + window.location.hash + '"]').parent().addClass('active');
        //compile the template
        var data = {items: this.collection.toJSON() };
        var compiledTemplate = _.template(contributorsTemplate, data);
        // render my template
        this.$el.html(compiledTemplate);
        // add the sidebar - WHAT'S THIS?
        var sidebarView = new SidebarView();
        sidebarView.render();
    }
});

现在,无论您在哪里即时显示此视图:

var contrCollection = new ContributorsCollection();
var mainView = new ContributorsView({ collection: contrCollection });
contrCollection.fetch({reset:true}); //we want to trigger the reset event you're waiting for!

明白我的意思吗?从外部为视图提供其集合,或在其initialize方法中创建。我一点也不喜欢侧边栏视图。您应该从此视图外部创建并呈现它,可能是路由器的路由处理程序。否则,每次render父视图时,您都将创建另一个将永远保留在内存中的侧边栏视图。http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

总结:

  1. 创建集合,创建视图
  2. 将该集合提供给视图的选项(如果它是在外部创建的(
  3. 加载数据是异步操作,您应该"等待"数据
  4. 加载数据后,您可能希望重新呈现视图,以便模板数据具有要显示的内容。

Backbone中的所有内容都与事件相关,因为好事需要时间。 ;)

http://backbonejs.org/#Events-catalog

哇看起来

很复杂,虽然很有趣! :)

好消息 - 你错过的是容易的部分。

您正在使用requirejs文本插件从外部源加载HTML。您只需要使用您选择的模板引擎"编译"该 HTML。您提到的示例使用基本的下划线模板。

不要将 HTML 直接添加到视图的 jQuery 元素中,而是使用您喜欢的数据对其进行编译,然后发送结果:

render: function () {
  $('.menu li').removeClass('active');
  $('.menu li a[href="' + window.location.hash + '"]').parent().addClass('active');
  //compile the template
  var data = { text: "Hello world!" };
  var compiledTemplate = _.template(contributorsTemplate, data);
  // render my template
  this.$el.html(compiledTemplate);
}

假设您的模板包含以下内容:

<h1><%= text %></h1>

前面代码的结果是,模板中的text变量将使用提供给_.template的上下文进行插值。因此,它将显示">

你好世界!

使用模型和集合时,模板数据通常包含模型数据(如果是集合,则包含模型列表(。

例如,假设您的视图具有如下模型:

this.model = new Backbone.Model({
  firstName: "Mauro",
  lastName: " Backbone"
});
//compile the template
var data = this.model.toJSON();
var compiledTemplate = _.template(contributorsTemplate, data);
// render my template
this.$el.html(compiledTemplate);

然后,您可以直接将模型属性用作模板文件中的变量:

<h1><%= firstName %> <%= lastName %></h1>

这就是为什么通常你会创建基本的通用View并从中继承,以避免相同的步骤:

  1. 序列化模型/集合
  2. 编译模板
  3. 输出到视图$el

索梅西格喜欢:

var BaseView = Backbone.View.extend({
  render: function(){
    if(!this.template) return this;
    //abstract data serialization to a method, easy to override in child classes
    var data = this.serializeData();
    var compiledTemplate = _.template(this.template, data);
    this.$el.html(compiledTemplate);
    return this;
  },
  serializeData: function(){
    if(this.model){
      return this.model.toJSON();
    }
    else {
      return {};
    }
  }
});

现在定义扩展此视图而不是普通 Backbone.View 的视图,定义模板或模型并渲染。

var ContactView = BaseView.extend({
  template: yourRequiredTemplate
});
//in your router or "main app/view"
var contact = new Backbone.Model({
  firstName: "Mauro",
  age: 20
});
var contactView = new ContactView({
  model: contact
});
//for example, let's append it to the body
$("body").append(contactView.render().$el);

希望它有所帮助,您可能想看看 Marionettejs 以查看它提供的专业视图,或者像此示例中一样滚动自己的视图:http://liquidmedia.org/blog/2011/02/backbone-js-part-3/