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