จะใช้หลายรุ่นกับเส้นทางเดียวใน EmberJS / Ember Data ได้อย่างไร?


85

จากการอ่านเอกสารดูเหมือนว่าคุณต้อง (หรือควร) กำหนดโมเดลให้กับเส้นทางดังนี้:

App.PostRoute = Ember.Route.extend({
    model: function() {
        return App.Post.find();
    }
});

จะเกิดอะไรขึ้นถ้าฉันต้องการใช้วัตถุหลายชิ้นในเส้นทางหนึ่ง ๆ ? เช่นโพสต์ความคิดเห็นและผู้ใช้? ฉันจะบอกเส้นทางในการโหลดได้อย่างไร

คำตอบ:


117

อัปเดตล่าสุดตลอดไป : ฉันไม่สามารถอัปเดตสิ่งนี้ได้ นี่จึงเลิกใช้งานและน่าจะเป็นแบบนี้ นี่คือเธรดEmberJS ที่ดีขึ้นและเป็นปัจจุบันมากขึ้น: จะโหลดหลายรุ่นในเส้นทางเดียวกันได้อย่างไร

อัปเดต:ในคำตอบเดิมของฉันฉันบอกว่าจะใช้embedded: trueในการกำหนดโมเดล ไม่ถูกต้อง ในการแก้ไขครั้งที่ 12 Ember-Data คาดว่าจะมีการกำหนดคีย์ต่างประเทศด้วยคำต่อท้าย ( ลิงก์ ) _idสำหรับเร็กคอร์ดเดียวหรือ_idsสำหรับการรวบรวม สิ่งที่คล้ายกับสิ่งต่อไปนี้:

{
    id: 1,
    title: 'string',
    body: 'string string string string...',
    author_id: 1,
    comment_ids: [1, 2, 3, 6],
    tag_ids: [3,4]
}

ฉันได้อัปเดตซอและจะดำเนินการอีกครั้งหากมีอะไรเปลี่ยนแปลงหรือพบปัญหาเพิ่มเติมเกี่ยวกับรหัสที่ให้ไว้ในคำตอบนี้


ตอบด้วยโมเดลที่เกี่ยวข้อง:

สำหรับสถานการณ์ที่คุณกำลังอธิบายฉันจะอาศัยการเชื่อมโยงระหว่างโมเดล(การตั้งค่าembedded: true)และโหลดPostโมเดลในเส้นทางนั้นเท่านั้นโดยพิจารณาว่าฉันสามารถกำหนดการDS.hasManyเชื่อมโยงสำหรับCommentโมเดลและการDS.belongsToเชื่อมโยงสำหรับUserทั้งในCommentและPostโมเดล สิ่งนี้:

App.User = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName: DS.attr('string'),
    email: DS.attr('string'),
    posts: DS.hasMany('App.Post'),
    comments: DS.hasMany('App.Comment')
});

App.Post = DS.Model.extend({
    title: DS.attr('string'),
    body: DS.attr('string'),
    author: DS.belongsTo('App.User'),
    comments: DS.hasMany('App.Comment')
});

App.Comment = DS.Model.extend({
    body: DS.attr('string'),
    post: DS.belongsTo('App.Post'),
    author: DS.belongsTo('App.User')
});

คำจำกัดความนี้จะทำให้เกิดสิ่งต่อไปนี้:

ความสัมพันธ์ระหว่างโมเดล

ด้วยคำนิยามนี้ทุกครั้งที่ผมfindโพสต์ผมจะมีการเข้าถึงคอลเลกชันของความคิดเห็นที่เกี่ยวข้องกับการโพสต์ที่เขียนและแสดงความคิดเห็นเช่นกันและผู้ใช้ซึ่งเป็นผู้เขียนของการโพสต์ตั้งแต่พวกเขาจะถูกฝังไว้ทั้งหมด เส้นทางเรียบง่าย:

App.PostsPostRoute = Em.Route.extend({
    model: function(params) {
        return App.Post.find(params.post_id);
    }
});

ดังนั้นในPostRoute(หรือPostsPostRouteถ้าคุณใช้resource) แม่แบบของฉันจะสามารถเข้าถึงคอนโทรลเลอร์contentซึ่งเป็นPostโมเดลได้ดังนั้นฉันจึงสามารถอ้างถึงผู้เขียนได้ง่ายๆว่าauthor

<script type="text/x-handlebars" data-template-name="posts/post">
    <h3>{{title}}</h3>
    <div>by {{author.fullName}}</div><hr />
    <div>
        {{body}}
    </div>
    {{partial comments}}
</script>

<script type="text/x-handlebars" data-template-name="_comments">
    <h5>Comments</h5>
    {{#each content.comments}}
    <hr />
    <span>
        {{this.body}}<br />
        <small>by {{this.author.fullName}}</small>
    </span>
    {{/each}}
</script>

(ดูซอ )


ตอบแบบไม่เกี่ยวข้อง:

แต่ถ้าสถานการณ์ของคุณเป็นเพียงเล็กน้อยที่ซับซ้อนมากขึ้นกว่าสิ่งที่คุณอธิบายและ / หรือมีการใช้งาน (หรือแบบสอบถาม) Route#setupControllerรุ่นที่แตกต่างกันสำหรับเส้นทางโดยเฉพาะอย่างยิ่งผมอยากจะแนะนำให้ทำมันใน ตัวอย่างเช่น:

App.PostsPostRoute = Em.Route.extend({
    model: function(params) {
        return App.Post.find(params.post_id);
    },
    // in this sample, "model" is an instance of "Post"
    // coming from the model hook above
    setupController: function(controller, model) {
        controller.set('content', model);
        // the "user_id" parameter can come from a global variable for example
        // or you can implement in another way. This is generally where you
        // setup your controller properties and models, or even other models
        // that can be used in your route's template
        controller.set('user', App.User.find(window.user_id));
    }
});

และตอนนี้เมื่อฉันอยู่ในเส้นทางการโพสต์แม่แบบของฉันจะสามารถเข้าถึงuserคุณสมบัติในตัวควบคุมได้ตามที่ตั้งค่าไว้ในsetupControllerhook:

<script type="text/x-handlebars" data-template-name="posts/post">
    <h3>{{title}}</h3>
    <div>by {{controller.user.fullName}}</div><hr />
    <div>
        {{body}}
    </div>
    {{partial comments}}
</script>

<script type="text/x-handlebars" data-template-name="_comments">
    <h5>Comments</h5>
    {{#each content.comments}}
    <hr />
    <span>
        {{this.body}}<br />
        <small>by {{this.author.fullName}}</small>
    </span>
    {{/each}}
</script>

(ดูซอ )


15
ขอบคุณมากที่สละเวลาโพสต์ฉันพบว่ามันมีประโยชน์จริงๆ
ไม่ระบุชื่อ

1
@MilkyWayJoe โพสต์เก่งจริงๆ! ตอนนี้แนวทางของฉันดูไร้เดียงสาจริงๆ :)
intuitivepixel

ปัญหาเกี่ยวกับโมเดลที่ไม่เกี่ยวข้องของคุณคือมันไม่ยอมรับสัญญาเช่นเดียวกับโมเดลเบ็ดใช่ไหม? มีวิธีแก้ปัญหาสำหรับสิ่งนั้นหรือไม่?
miguelcobain

1
หากฉันเข้าใจปัญหาของคุณอย่างถูกต้องคุณสามารถปรับเปลี่ยนได้อย่างง่ายดาย เพียงแค่รอให้คำสัญญาเป็นจริงจากนั้นจึงตั้งค่าโมเดลเป็นตัวแปรของคอนโทรลเลอร์
ฟาบิโอ

นอกเหนือจากการแสดงความคิดเห็นซ้ำแล้วซ้ำอีกมันจะน่าดูถ้าคุณสามารถแสดงตัวอย่างว่ามีคนเพิ่มความคิดเห็นใหม่เข้าไปpost.commentsได้อย่างไร
Damon Aw

49

การใช้Em.Objectเพื่อห่อหุ้มหลายรุ่นเป็นวิธีที่ดีในการรับข้อมูลทั้งหมดในmodelเบ็ด แต่ไม่สามารถมั่นใจได้ว่าข้อมูลทั้งหมดจะถูกเตรียมหลังจากการแสดงผล

Em.RSVP.hashอีกทางเลือกหนึ่งคือการใช้งาน เป็นการรวมคำสัญญาต่างๆเข้าด้วยกันและคืนสัญญาใหม่ สัญญาใหม่หากได้รับการแก้ไขหลังจากที่สัญญาทั้งหมดได้รับการแก้ไข และsetupControllerจะไม่เรียกจนกว่าสัญญาจะได้รับการแก้ไขหรือปฏิเสธ.

App.PostRoute = Em.Route.extend({
  model: function(params) {
    return Em.RSVP.hash({
      post:     // promise to get post
      comments: // promise to get comments,
      user:     // promise to get user
    });
  },

  setupController: function(controller, model) {
    // You can use model.post to get post, etc
    // Since the model is a plain object you can just use setProperties
    controller.setProperties(model);
  }
});

ด้วยวิธีนี้คุณจะได้โมเดลทั้งหมดก่อนที่จะดูการเรนเดอร์ และการใช้Em.Objectไม่ได้มีประโยชน์นี้

ข้อดีอีกประการหนึ่งคือคุณสามารถรวมคำสัญญาและคำสัญญาไม่ได้ แบบนี้:

Em.RSVP.hash({
  post: // non-promise object
  user: // promise object
});

ตรวจสอบสิ่งนี้เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับEm.RSVP: https://github.com/tildeio/rsvp.js


แต่อย่าใช้Em.ObjectหรือEm.RSVPวิธีแก้ปัญหาหากเส้นทางของคุณมีกลุ่มแบบไดนามิก

ปัญหาหลักคือlink-to. หากคุณเปลี่ยน url โดยคลิกลิงก์ที่สร้างโดยlink-toโมเดลโมเดลจะถูกส่งต่อไปยังเส้นทางนั้นโดยตรง ในกรณีนี้modelเบ็ดไม่ได้เรียกว่าและsetupControllerคุณจะได้รับรูปแบบlink-toให้คุณ

ตัวอย่างมีดังนี้:

รหัสเส้นทาง:

App.Router.map(function() {
  this.route('/post/:post_id');
});

App.PostRoute = Em.Route.extend({
  model: function(params) {
    return Em.RSVP.hash({
      post: App.Post.find(params.post_id),
      user: // use whatever to get user object
    });
  },

  setupController: function(controller, model) {
    // Guess what the model is in this case?
    console.log(model);
  }
});

และlink-toรหัสโพสต์เป็นแบบจำลอง:

{{#link-to "post" post}}Some post{{/link-to}}

สิ่งที่น่าสนใจกลายเป็นที่นี่ เมื่อคุณใช้ url /post/1เพื่อเยี่ยมชมเพจmodelhook จะถูกเรียกและsetupControllerรับวัตถุธรรมดาเมื่อคำสัญญาได้รับการแก้ไข

แต่ถ้าคุณไปที่หน้าโดยคลิกlink-toลิงก์มันจะส่งผ่านpostโมเดลไปPostRouteและเส้นทางจะไม่สนใจmodelตะขอ ในกรณีนี้setupControllerจะได้รับpostรุ่นแน่นอนคุณไม่สามารถรับผู้ใช้ได้

ดังนั้นอย่าใช้ในเส้นทางที่มีกลุ่มไดนามิก


2
คำตอบของฉันใช้กับ Ember & Ember-Data เวอร์ชันก่อนหน้า นี่เป็นแนวทางที่ดีจริงๆ +1
MilkyWayJoe

11
มีอยู่จริง. หากคุณต้องการส่งรหัสโมเดลแทนที่จะส่งโมเดลตัวเองไปยังตัวช่วยเชื่อมโยงโมเดลเบ็ดจะถูกเรียกใช้
darkbaby123

2
ควรจัดทำเป็นเอกสารไว้ในคู่มือ Ember (แนวทางปฏิบัติที่ดีที่สุดหรือบางอย่าง) เป็นกรณีการใช้งานที่สำคัญที่ฉันแน่ใจว่าหลาย ๆ คนต้องเจอ
โบร

1
หากคุณกำลังใช้controller.setProperties(model);อย่าลืมเพิ่มคุณสมบัติเหล่านี้ด้วยค่าเริ่มต้นให้กับคอนโทรลเลอร์ มิฉะนั้นจะทำให้เกิดข้อยกเว้นCannot delegate set...
Mateusz Nowak

13

ในขณะที่ฉันใช้Em.RSVP.hashงาน แต่ปัญหาที่พบคือฉันไม่ต้องการให้มุมมองของฉันรอจนกว่าทุกรุ่นจะโหลดก่อนที่จะแสดงผล อย่างไรก็ตามฉันพบวิธีแก้ปัญหาที่ยอดเยี่ยม (แต่ค่อนข้างไม่เป็นที่รู้จัก) ขอบคุณคนที่Novelysที่เกี่ยวข้องกับการใช้Ember.PromiseProxyMixin :

สมมติว่าคุณมีมุมมองที่มีส่วนภาพที่แตกต่างกันสามส่วน แต่ละส่วนเหล่านี้ควรได้รับการสนับสนุนโดยโมเดลของตัวเอง โมเดลที่รองรับเนื้อหา "splash" ที่ด้านบนของมุมมองมีขนาดเล็กและจะโหลดได้อย่างรวดเร็วคุณจึงโหลดได้ตามปกติ:

สร้างเส้นทางmain-page.js:

import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.find('main-stuff');
    }
});

จากนั้นคุณสามารถสร้างเทมเพลต Handlebars ที่เกี่ยวข้องmain-page.hbs:

<h1>My awesome page!</h1>
<ul>
{{#each thing in model}}
    <li>{{thing.name}} is really cool.</li>
{{/each}}
</ul>
<section>
    <h1>Reasons I Love Cheese</h1>
</section>
<section>
    <h1>Reasons I Hate Cheese</h1>
</section>

สมมติว่าในเทมเพลตของคุณคุณต้องการให้มีส่วนแยกต่างหากเกี่ยวกับความสัมพันธ์ความรัก / ความเกลียดชังของคุณกับชีสแต่ละส่วน (ด้วยเหตุผลบางประการ) ได้รับการสนับสนุนโดยแบบจำลอง คุณมีบันทึกมากมายในแต่ละรุ่นพร้อมรายละเอียดมากมายเกี่ยวกับเหตุผลแต่ละข้ออย่างไรก็ตามคุณต้องการให้เนื้อหาด้านบนแสดงผลอย่างรวดเร็ว นี่คือที่{{render}}มาของผู้ช่วยคุณสามารถอัปเดตเทมเพลตของคุณได้ดังนี้:

<h1>My awesome page!</h1>
<ul>
{{#each thing in model}}
    <li>{{thing.name}} is really cool.</li>
{{/each}}
</ul>
<section>
    <h1>Reasons I Love Cheese</h1>
    {{render 'love-cheese'}}
</section>
<section>
    <h1>Reasons I Hate Cheese</h1>
    {{render 'hate-cheese'}}
</section>

ตอนนี้คุณจะต้องสร้างคอนโทรลเลอร์และเทมเพลตสำหรับแต่ละตัว เนื่องจากมันเหมือนกันอย่างมีประสิทธิภาพสำหรับตัวอย่างนี้ฉันจะใช้แค่อันเดียว

สร้างตัวควบคุมที่เรียกว่าlove-cheese.js:

import Ember from 'ember';

export default Ember.ObjectController.extend(Ember.PromiseProxyMixin, {
    init: function() {
        this._super();
        var promise = this.store.find('love-cheese');
        if (promise) {
            return this.set('promise', promise);
        }
    }
});

คุณจะสังเกตเห็นว่าเรากำลังใช้ที่PromiseProxyMixinนี่ซึ่งทำให้คอนโทรลเลอร์ตระหนักถึงสัญญา เมื่อเริ่มต้นคอนโทรลเลอร์เราจะระบุว่าสัญญาควรโหลดlove-cheeseโมเดลผ่านข้อมูล Ember คุณจะต้องตั้งค่าคุณสมบัตินี้ในการควบคุมของpromiseสถานที่ให้บริการ

ตอนนี้สร้างเทมเพลตชื่อlove-cheese.hbs:

{{#if isPending}}
  <p>Loading...</p>
{{else}}
  {{#each item in promise._result }}
    <p>{{item.reason}}</p>
  {{/each}}
{{/if}}

ในเทมเพลตของคุณคุณจะสามารถแสดงเนื้อหาที่แตกต่างกันได้ขึ้นอยู่กับสถานะของสัญญา เมื่อหน้าของคุณโหลดครั้งแรกส่วน "เหตุผลที่ฉันชอบชีส" จะLoading...ปรากฏขึ้น เมื่อคำมั่นสัญญาถูกโหลดคำสัญญาจะแสดงเหตุผลทั้งหมดที่เกี่ยวข้องสำหรับแต่ละเร็กคอร์ดของโมเดลของคุณ

แต่ละส่วนจะโหลดอย่างอิสระและไม่บล็อกเนื้อหาหลักจากการแสดงผลทันที

นี่เป็นตัวอย่างที่เรียบง่าย แต่ฉันหวังว่าทุกคนจะพบว่ามันมีประโยชน์เหมือนที่ฉันทำ

หากคุณต้องการทำสิ่งที่คล้ายกันสำหรับเนื้อหาหลายแถวคุณอาจพบว่าตัวอย่างของ Novelys ด้านบนมีความเกี่ยวข้องมากขึ้น หากไม่เป็นเช่นนั้นข้างต้นน่าจะใช้ได้ผลสำหรับคุณ


8

นี่อาจไม่ใช่แนวทางปฏิบัติที่ดีที่สุดและเป็นแนวทางที่ไร้เดียงสา แต่แสดงให้เห็นถึงแนวคิดว่าคุณจะดำเนินการอย่างไรกับการมีโมเดลหลายรุ่นที่มีอยู่บนเส้นทางกลางสายเดียว:

App.PostRoute = Ember.Route.extend({
  model: function() {
    var multimodel = Ember.Object.create(
      {
        posts: App.Post.find(),
        comments: App.Comments.find(),
        whatever: App.WhatEver.find()
      });
    return multiModel;
  },
  setupController: function(controller, model) {
    // now you have here model.posts, model.comments, etc.
    // as promises, so you can do stuff like
    controller.set('contentA', model.posts);
    controller.set('contentB', model.comments);
    // or ...
    this.controllerFor('whatEver').set('content', model.whatever);
  }
});

หวังว่ามันจะช่วยได้


1
วิธีนี้ใช้ได้ดีเพียงแค่ไม่ใช้ประโยชน์จาก Ember Data มากเกินไป สำหรับบางสถานการณ์ที่โมเดลไม่เกี่ยวข้องกันฉันจะได้รับสิ่งที่คล้ายกันนี้
MilkyWayJoe

4

ขอบคุณสำหรับคำตอบที่ยอดเยี่ยมอื่น ๆ ฉันได้สร้างมิกซ์อินที่รวมโซลูชันที่ดีที่สุดไว้ในอินเทอร์เฟซที่เรียบง่ายและใช้ซ้ำได้ มันรันEmber.RSVP.hashในสำหรับรูปแบบที่คุณระบุแล้วอัดฉีดคุณสมบัติเข้าไปควบคุมในafterModel setupControllerมันไม่รบกวนmodelตะขอมาตรฐานดังนั้นคุณยังคงกำหนดว่าเป็นเรื่องปกติ

ตัวอย่างการใช้งาน:

App.PostRoute = Ember.Route.extend(App.AdditionalRouteModelsMixin, {

  // define your model hook normally
  model: function(params) {
    return this.store.find('post', params.post_id);
  },

  // now define your other models as a hash of property names to inject onto the controller
  additionalModels: function() {
    return {
      users: this.store.find('user'), 
      comments: this.store.find('comment')
    }
  }
});

นี่คือ mixin:

App.AdditionalRouteModelsMixin = Ember.Mixin.create({

  // the main hook: override to return a hash of models to set on the controller
  additionalModels: function(model, transition, queryParams) {},

  // returns a promise that will resolve once all additional models have resolved
  initializeAdditionalModels: function(model, transition, queryParams) {
    var models, promise;
    models = this.additionalModels(model, transition, queryParams);
    if (models) {
      promise = Ember.RSVP.hash(models);
      this.set('_additionalModelsPromise', promise);
      return promise;
    }
  },

  // copies the resolved properties onto the controller
  setupControllerAdditionalModels: function(controller) {
    var modelsPromise;
    modelsPromise = this.get('_additionalModelsPromise');
    if (modelsPromise) {
      modelsPromise.then(function(hash) {
        controller.setProperties(hash);
      });
    }
  },

  // hook to resolve the additional models -- blocks until resolved
  afterModel: function(model, transition, queryParams) {
    return this.initializeAdditionalModels(model, transition, queryParams);
  },

  // hook to copy the models onto the controller
  setupController: function(controller, model) {
    this._super(controller, model);
    this.setupControllerAdditionalModels(controller);
  }
});

2

https://stackoverflow.com/a/16466427/2637573ใช้ได้สำหรับรุ่นที่เกี่ยวข้อง อย่างไรก็ตามด้วย Ember CLI และ Ember Data เวอร์ชันล่าสุดมีแนวทางที่ง่ายกว่าสำหรับรุ่นที่ไม่เกี่ยวข้อง:

import Ember from 'ember';
import DS from 'ember-data';

export default Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller,model);
    var model2 = DS.PromiseArray.create({
      promise: this.store.find('model2')
    });
    model2.then(function() {
      controller.set('model2', model2)
    });
  }
});

หากคุณต้องการเพียงแค่ดึงคุณสมบัติของวัตถุให้model2ใช้DS.PromiseObjectแทนDS.PromiseArray :

import Ember from 'ember';
import DS from 'ember-data';

export default Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller,model);
    var model2 = DS.PromiseObject.create({
      promise: this.store.find('model2')
    });
    model2.then(function() {
      controller.set('model2', model2.get('value'))
    });
  }
});

ฉันมีpostเส้นทางแก้ไข / มุมมองที่ฉันต้องการแสดงแท็กที่มีอยู่ทั้งหมดในฐานข้อมูลเพื่อให้ผู้ใช้สามารถคลิกเพื่อเพิ่มลงในโพสต์ที่กำลังแก้ไข ฉันต้องการกำหนดตัวแปรที่แสดงถึงอาร์เรย์ / ชุดของแท็กเหล่านี้ แนวทางที่คุณใช้ข้างต้นจะใช้ได้ผลหรือไม่?
โจ

แน่นอนว่าคุณต้องสร้างPromiseArray(เช่น "แท็ก") จากนั้นในเทมเพลตของคุณคุณจะส่งต่อไปยังองค์ประกอบการเลือกของแบบฟอร์มที่เกี่ยวข้อง
AWM

1

การเพิ่มคำตอบของ MilkyWayJoe ขอบคุณ btw:

this.store.find('post',1) 

ผลตอบแทน

{
    id: 1,
    title: 'string',
    body: 'string string string string...',
    author_id: 1,
    comment_ids: [1, 2, 3, 6],
    tag_ids: [3,4]
};

ผู้เขียนจะเป็น

{
    id: 1,
    firstName: 'Joe',
    lastName: 'Way',
    email: 'MilkyWayJoe@example.com',
    points: 6181,
    post_ids: [1,2,3,...,n],
    comment_ids: [1,2,3,...,n],
}

ความคิดเห็น

{
    id:1,
    author_id:1,
    body:'some words and stuff...',
    post_id:1,
}

... ฉันเชื่อว่าการเชื่อมโยงกลับมีความสำคัญเพื่อให้ความสัมพันธ์เต็มรูปแบบ หวังว่าจะช่วยใครบางคน


0

คุณสามารถใช้beforeModelหรือafterModelhooks ตามที่เรียกได้เสมอแม้ว่าmodelจะไม่ถูกเรียกเนื่องจากคุณใช้กลุ่มไดนามิก

ตามเอกสารการกำหนดเส้นทางแบบอะซิงโครนัส :

เบ็ดรุ่นครอบคลุมกรณีการใช้งานจำนวนมากสำหรับการเปลี่ยนแบบหยุดชั่วคราวตามสัญญา แต่บางครั้งคุณจะต้องได้รับความช่วยเหลือจาก hooks ที่เกี่ยวข้อง beforeModel และ afterModel สาเหตุที่พบบ่อยที่สุดคือหากคุณกำลังเปลี่ยนไปใช้เส้นทางที่มีกลุ่ม URL แบบไดนามิกผ่าน {{link-to}} หรือ transitionTo (ตรงข้ามกับการเปลี่ยนแปลงที่เกิดจากการเปลี่ยนแปลง URL) โมเดลสำหรับเส้นทางที่คุณ "กำลังเปลี่ยนไปใช้จะถูกระบุไว้แล้ว (เช่น {{# link-to 'article' article}} หรือ this.transitionTo ('article', article)) ซึ่งในกรณีนี้จะไม่เรียก model hook ในกรณีเหล่านี้คุณจะต้องใช้ hook beforeModel หรือ afterModel เพื่อสร้างตรรกะใด ๆ ในขณะที่เราเตอร์ยังคงรวบรวมโมเดลของเส้นทางทั้งหมดเพื่อทำการเปลี่ยน

สมมติว่าคุณมีthemesทรัพย์สินอยู่SiteControllerคุณอาจมีสิ่งนี้:

themes: null,
afterModel: function(site, transition) {
  return this.store.find('themes').then(function(result) {
    this.set('themes', result.content);
  }.bind(this));
},
setupController: function(controller, model) {
  controller.set('model', model);
  controller.set('themes', this.get('themes'));
}

1
ฉันคิดว่าการใช้thisภายในสัญญาจะทำให้เกิดข้อความแสดงข้อผิดพลาด คุณสามารถตั้งค่าvar _this = thisก่อนกลับแล้วทำ_this.set(ตามthen(วิธีการเพื่อให้ได้ผลลัพธ์ที่ต้องการ
Duncan Walker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.