【问题标题】:backbone Inverse view骨干逆视图
【发布时间】:2013-01-14 06:11:50
【问题描述】:

骨干新手在这里。我想开始在 Web 应用程序(后端是 Ruby on Rails)上使用骨干网,到目前为止,它的客户端功能非常少(一些用于执行 slideToggles 的 jquery 和几个 ajax 调用)。

我面临的一个问题是,Backbone 似乎是这样构建的,以便您加载 javascript,然后使其向服务器请求数据(通常是 JSON),然后呈现视图。在我的情况下这是不可接受的。我想获取源自服务器的 html,将其呈现给用户,然后使用该 html 填充我的模型(之后,我对从服务器请求 JSON 内容的模型很好)。

我猜我需要的是某种“逆视图”。给出这个 html 的东西:

<ul class="people">
  <li><span class="name">Peter</span></li>
  <li><span class="name">John</span></li>
</ul>

还有一个 People Collection 和一个带有 name 属性的 Person 模型,可以从中解析出 Peter 和 John(可能使用 View)。

这是存在的吗?我是否以错误的方式处理整个事情?

【问题讨论】:

标签: javascript backbone.js backbone-views


【解决方案1】:

可以将Backbone.View 附加到服务器上预呈现的 HTML 页面。我在this SO answer 中对此进行了更详细的描述。这是page needs to be crawlable by search engines 时很常见的情况。

但是,我建议不要通过解析服务器呈现的 HTML 来初始化模型状态的设计。我建议您改为bootstrap 将初始模型数据作为 JSON 提供给服务页面。比如:

<body>
      <!-- your server-side template code here -->
      <script>
        window.bootstrap = {
          people: <%= @people.to_json %>
        };
      </script>
</body>

当您初始化集合时,您可以简单地从引导数据初始化它们并丢弃引导集合:

var bootstrap = window.bootstrap || {};
var peopleCollection = new PeopleCollection(bootstrap.people);
delete window.bootstrap;

只需确保您的服务器端渲染引擎使用与引导程序相同的数据,这样您就可以保证渲染页面和初始模型数据是同步的。

或者,重新考虑像 Backbone 这样的框架是否适合您的需求。您说您的应用程序几乎没有(javascript)功能。你需要Backbone吗?这是一个很棒的框架,但您想要的是The Right Tool For The Job™

【讨论】:

    【解决方案2】:

    我最终只是在每个视图的元素上添加了我需要的每个模型的 json。

    换句话说:

    <ul class="people" data-collection="people">
      <li data-model="person" data-attributes='{"name":"Peter"}'>Peter</li>
      <li data-model="person" data-attributes='{"name":"John"}'>John</li>
    </ul>
    

    在我的例子中,每个属性上的 JSON 片段在服务器上生成是微不足道的。

    我更喜欢将 json 嵌入到 html 中而不是在开始时将它返回到一个大数组中的原因是,这样我可以很容易地将模型附加到他们的视图中。

    其余的从那里流出。

    我使用 jquery 来检测 data-collections 并创建与 DOM 元素关联的相应视图。然后我解析模型,最后我开始在集合视图上监听事件。

    $(function(){
      $('[data-collection="people"]').each(function() {
        var view = new PeopleView({el: this});
        view.parse();
        view.listen();
      });
    });
    

    parselisten 方法如下所示:

    MyApp.PeopleView = Backbone.View.extend({
      collection: MyApp.Collections.People,
      ...
      parse: function() {
        var people = this.$("[data-model='person']").map(function(i,el){
          return new MyApp.Models.Person($(el).data('attributes'));
        };
        this.collection.reset(comments, {silent: true});
      },
      listen: function() {
        this.listenTo(this.collection, 'add',   this.showNewPerson, this);
        this.listenTo(this.collection, 'reset', this.renderEveryone, this);
        this.delegateEvents();
      }
      ...
    });
    

    在这种特殊情况下,我不需要为列表中的每个人创建特定的 Backbone 视图。但如果需要,我可以在 parse 方法中这样做。

    【讨论】:

      【解决方案3】:

      您可以使用服务器或客户端代码预渲染 HTML。尽管我不确定为什么在您的情况下必须通过 AJAX 加载 HTML。无论如何,Backbone ModelCollection 并不真正知道它的定义,直到您对其进行提取。

      底线是,您可以预加载预定义的View 并使用 Backbone 进行更改。在您的情况下,如果您希望 Backbone 对您的 $('.people') 进行操作,您可以在加载新记录之前简单地追加新行或清空元素。

      至于从渲染的View 解析您的实际Models,不太确定为什么要这样做,但您可以使用jQuery 遍历它并选择html()text()

      如果您可以执行AJAX 请求,我不明白为什么发送实际的Model 会是一个问题。

      var json = { people: [{name: 'Peter' },{name: 'John' }]};
      

      Backbone 在使用和主要结构基础方面没有任何限制。希望这可以解决您的问题。

      【讨论】:

      • 我不认为你明白我的意思。一旦页面以通常的方式工作,我就可以通过向服务器请求 json 来确定(或者不。无论做什么更容易,我现在并不关心)。但是,在初始页面加载中,我想从服务器已经提供的渲染 html 创建模型。
      • 您可以预渲染您的服务器端 JSON 对象并让 Backbone 对该对象进行操作。基本上输出并将其视为 JavaScript 对象。 { "name" : "" }
      • 我必须非常糟糕地传达我的需求。请忘记 json 或 ajax。我想解析html。这就是我的问题所在。
      【解决方案4】:

      我正在使用Backbone LayoutManager 来执行此操作。您可以定义一个 fetch() 函数,其中可以远程获取视图(即您的服务器)。例如,它们然后被缓存在 Javascript 模板对象中。

      部分代码取自Backbone BoilerPlate

      var app = { root: "/" };
      var JST = window.JST = window.JST || {};
      
      // Configure LayoutManager
      Backbone.LayoutManager.configure({
      
        ....
      
      
        fetch: function(path) {
          var done;
          path = path + ".html";
      
          if (!JST[path]) {
            done = this.async();
            $.ajax({ url: app.root + path }).then(function(contents) {
              JST[path] = _.template(contents);
              done(JST[path]);
            });
          }
          return JST[path];
      
        }
      });
      

      【讨论】:

      • 对不起,我不明白这如何回答我的问题。澄清一下:我不是试图通过 ajax 从服务器获取模型数据。我正在尝试解析已经存在的 html,并使用该 html 正确初始化相关集合。就这样。 稍后,我可能想做 ajax 并从服务器获取东西,但这不是我在这个问题上要问的。我只对现有 html 的解析感兴趣。谢谢。
      • @kikito - 是的,我明白了。 fetch() 函数是 LayoutManager 的 View 的一个属性——您可以通过这种方式从您的服务器获取 html 模板。然后,缓存它们并使用 JST 重新使用它们
      • 重新读取其他 cmets -- 所以,您希望将 HTML 发送为“如果它是 JSON”?也就是说,把它当成数据,然后以某种方式解析它?
      • 正确。我想我可以在 Jquery 中做到这一点,但我想知道是否有更好的方法来做到这一点,或者人们是否会这样做。
      • 啊,我明白了。有一个parse 方法可以用来处理来自服务器的数据......但你必须编写自己的方法——jQuery 或任何处理它的方法。但是,由于您的模型在此之后请求 JSON,因此最好在引导程序上仅在“html 数据”上运行一次您的方法。也就是说,我很确定 Backbone 中没有任何东西可以为你做这种解析。
      猜你喜欢
      • 2015-08-22
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多