想象以下情况。我有一个绝对位于侧边栏的工具栏,然后还有一些绝对位于该侧边栏内的东西。在该边栏中,我有一个按钮,其中显示一个菜单,模板如下所示:

<button>Click me</button>
{{#if shouldDisplayMenu}}
    {{view App.MyMenu}}
{{/if}}

我喜欢此解决方案并希望保留的是,模板中的菜单位于按钮旁边,因此具有很好的可维护性。

问题是我希望菜单相对于视口(viewport)定位,即渲染到document.body并使用绝对位置定位。这样,它将渲染到侧边栏中并使滚动条可见,因为我已经通过相对于父元素之一的位置重置了定位上下文。

有什么方法可以将{{view App.MyMenu}}保留在现在的位置,但可以呈现到正文中(也许使用插座或其他某种机制)?对于这种情况,推荐的模式是什么?

最佳答案

有很多方法可以用ember和相关上下文呈现 View 。我提出了四种方法(我认为第一种可能是您想要的方法):

1. 如果需要将 View 放置在车把模板之外的某个位置,则可以使用jQuery将呈现的内容放置在所需的任何位置。

(由于替换viewt元素是在didInsertElement之后进行的,因此可能还需要添加样式以不显示该元素,例如display:none,并在重新定位后显示它)

示例
http://emberjs.jsbin.com/gotabore/1/edit

2. (如果该位置位于另一个模板中的某个位置),请使用{{render}}帮助器将该 View 呈现。尽管我不确定上下文要求,但是此帮助程序非常灵活(http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper)。

示例
http://emberjs.jsbin.com/xibayava/1/edit

3. 使用{{outlet}}帮助器可根据访问的route中指定的内容呈现 View 。 (http://emberjs.com/guides/routing/rendering-a-template/)

示例
http://emberjs.jsbin.com/tiyuqenu/1/edit

4. 使用ContainerView在需要的地方以编程方式推送 View 。

示例
http://emberjs.jsbin.com/yoyujeqi/1/edit

方法4的更新:对于等于或大于1.8.x的版本,为,为避免http://emberjs.com/guides/deprecations/#toc_global-lookup-of-views中提到的错误,可以指定与ContainerView关联的属性,如以下示例所示

http://emberjs.jsbin.com/difayakeki/1/edit?html,js,output

相关代码

方法1

hbs

<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    This is index<br/>
    {{view App.TestView}}
  </script>
  <script type="text/x-handlebars" data-template-name="test">
    This is the test view<br/>
    <b>{{myProp}}</b>
  </script>

  <div id="a-div" style="background-color:lightgray">
    This is a div somewhere,<br/>
  </div>

js
App = Ember.Application.create();

App.Router.map(function() {
  // put your routes here
});

App.IndexController = Ember.Controller.extend({
  myProp:"index controller prop"
});

App.IndexView = Ember.View.extend({
  placeTestViewSomewhere:function(){

    var theTestView = this.$(".my-test-view").detach();
    $("#a-div").append(theTestView);

  }.on("didInsertElement")
});

App.TestView = Ember.View.extend({
  templateName:"test",
  classNames:["my-test-view"]
});

方法2

hbs
<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    This is index<br/>

    <div style="background-color:lightgray">
    This is a div in index template with render helper,<br/>
    {{render "test"}}
  </div>
  </script>
  <script type="text/x-handlebars" data-template-name="test">
    This is the test view<br/>
    <b>{{myProp}}</b>
  </script>

js
App.IndexView = Ember.View.extend({
  placeTestViewSomewhere:function(){

//     var theTestView = this.$(".my-test-view").detach();
//     $("#a-div").append(theTestView);

  }.on("didInsertElement")
});

App.TestController = Ember.Controller.extend({
  myProp:"test controller prop"
});

App.TestView = Ember.View.extend({
  templateName:"test"
});

方法3

hbs
<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
    <div style="background-color:lightgray">
    This is a div in application template with outlet helper,<br/>
    {{outlet "test-outlet"}}
  </div>
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    This is index<br/>

  </script>
  <script type="text/x-handlebars" data-template-name="test">
    This is the test view<br/>
    <b>{{myProp}}</b>
  </script>

js
App.IndexRoute = Ember.Route.extend({
  renderTemplate: function() {
    this.render("index");
    this.render('test', {   // the template to render
      into: 'application',                // the template to render into
      outlet: 'test-outlet'             // the name of the outlet in that template
    });
  }
});

App.IndexView = Ember.View.extend({
  placeTestViewSomewhere:function(){

//     var theTestView = this.$(".my-test-view").detach();
//     $("#a-div").append(theTestView);

  }.on("didInsertElement")
});

App.TestController = Ember.Controller.extend({
  myProp:"test controller prop"
});

App.TestView = Ember.View.extend({
  templateName:"test"
});

方法4

hbs
<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
    <div style="background-color:lightgray">
    This is a div in application template with view helper and a view container,<br/>
    {{view Ember.ContainerView viewName="my-menu-container"}}
  </div>

  </div>
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    This is index<br/>
  </script>
  <script type="text/x-handlebars" data-template-name="test">
    This is the test view<br/>
    <b>{{myProp}}</b>
  </script>

js
App.IndexController = Ember.Controller.extend({
  myProp:"index controller prop"
});

App.IndexView = Ember.View.extend({
  placeTestViewSomewhere:function(){

    var theTestView = App.TestView.create({});
    theTestView.set("context",this.get("context"));
    this.get("parentView.my-menu-container").pushObject(theTestView);

  }.on("didInsertElement")
});


App.TestView = Ember.View.extend({
  templateName:"test"
});

方法4的更新:

js
App.ApplicationView = Em.View.extend({
  containerView:Em.ContainerView
});

hbs
{{view view.containerView viewName="my-menu-container"}}

10-05 20:54
查看更多