Open leetschau opened 9 years ago
我不太清楚你指的是哪个按钮, 如果是 title 上的那些左边的 Back, 右边的:Edit 按钮的话, 那么这样设计就是对的. 因为 title 属于 layoutTemplate, 并不属于 lists.html 中. 你在 lists.html 使用的是 contentFor 的方法去定义一个属于其他 template 的内容的. 你可以指定内容但是无法指定 event 的响应在本 template 中.
如果你说的不是这种情况请说明代码位置, 我再看
原来问题的详细说明:
lists.html中,<button class="button button-clear" id="showProfileMenu">
这个按钮在lists template中,
这个按钮的点击事件是layout.coffee中的'click #showProfileMenu': (event, t)->
,这行代码属于Template.layout.events
,所以是layout template的事件,为什么lists template中的组件(按钮showProfileMenu)的事件没有定义在Template.lists.events
中,却在Template.layout.events
中?
您的回答中提到:
你在 lists.html 使用的是 contentFor 的方法去定义一个属于其他 template 的内容的
是否可以理解为:
<template name="lists">
...
{{#contentFor "headerButtonRight"}}
<button class="button button-clear" id="showProfileMenu">
...
</button>
{{/contentFor}}
...
</template>
其中的button showProfileMenu由于被包在{{#contentFor "headerButtonRight"}}
中,所以不属于template lists?
那么它应该属于哪个template?
另外,Meteor中template A中的组件的事件,是否必须定义在Template.A.events
中?
呵呵我昨天看这到段代码的时候就猜到你可能是问的这个,我也有过同样的疑问。
我是这样理解的:Template.layout.events这个调用里的selector可以选中layout template里面的child element,#showProfileMenu虽然是在lists那个template里面,但不可否认lists也是layout的child element,所以当然可以选中。那么为什么非要在layout里做这件事,而不在lists里做呢?这样岂不是有违模块化设计?这是因为我们在event handler中需要layout这个template的template instance:
t.ActionSheetButtons = []
if Meteor.user()?
t.ActionSheetButtons.push {actionId:'addPost', text: 'New Post <i class="icon ion-ios-compose"></i>'}
t.ActionSheetButtons.push {actionId:'logout', text: 'Logout <i class="icon ion-log-out"></i>'}
else
t.ActionSheetButtons.push {actionId:'login', text: 'Login <i class="icon ion-log-in"></i>'}
我没仔细研究过这个ActionSheetButtons,但我试过把Template.layout.events改成Template.lists.events,也就是试着把ActionSheetButtons加到lists那个template instance上是不灵的。
我也被弄糊涂了,我试了即使这么简单的event handler也不灵:
Template.lists.events
'click #showProfileMenu': (event, t)->
alert "hello"
看来真的是因为被包在{{#contentFor "headerButtonRight"}}中的element不属于template lists?这也太不合理啦。
有参考价值的讨论
view中的内容才是当前模板的内容 之外的内容都是对layout 比如标题 导航等的配置 会动态插入到所有模板共用的layout的footer或header
最简单的方法就是直接看dom结构 是否保含特定元素。 这是ionic的设计,使用blaze实现 与meteor或blaze无关 即使ionic的angular版本也是这样配置的
那为什么不把{{#contentFor “headerButtonRight”}}直接就写在模板外面?写在模板里面,生成的DOM却不在模板里面,很混乱啊?
因为每个页面的标题都不一样 需要定制
这里关键是理解模板代码是有逻辑的代码 不是静态的内容 静态内容取决于最后真正生成在页面的 这样就会习惯的 感觉这样的设计是为了避免冗余 每个模板都有自己独立的header就会有很多重复代码
contentFor 从命名来说就是这里在指定一个地方的内容,但这个内容不一定属于这个模板
同求答案~
上面不是已经有十分清晰的答案了啊, 你问的是同一个问题么?
@kevingzhang
<template name="lists">
...
{{#contentFor "headerButtonRight"}}
<button class="button button-clear">
...
</button>
{{/contentFor}}
...
</template>
如果想监听 headerButtonRight 中的button点击事件该怎么写?
写在Template.layout.events 里,layout是布局模板名 Template.layout.events({ 'click cssSelector',function(){/***/} })
@ennea8 非常感谢,我比较担心都写在layout会冲突
目前我在用到的模板中这么写得, 看着有些奇怪
Template.ionNavBar.events({
'click [data-action=binding-done]': function (event, template){
}
});
这个事件绑定问题有另一种处理方法 去掉 layout中的 {{> ionNavBar class="bar-positive"}} 然后每个模板中添加自己的 bar-header,甚至不加,若不需要, 然后事件绑定就可以写到各自的模板js文件里了,互不冲突. 这样做的好处header的内容和样式可以随意定制,灵活性更大
附加一个info 供了解 从资源损耗角度,把事件写在layout里是代价最小的,发现meteor的事件绑定内部都使用代理的方式进行了优化。 也就是不论往layout上绑了多少个click,其实从浏览器角度只绑了一个,有一个函数处理队列(数组),目前的了解是这样 https://github.com/meteor/meteor/wiki/Using-Blaze 文章的底部有对delegate的一些描述
@qdsang 你那种把事件写ionNavBar的方式应该比layou应该更易读更模块化些
点击用户按钮事件定义在template layout中, 用户按钮组件是定义lists.html中的, 问题: 为什么html组件和它的事件可以不在同一个template中定义? 这两个template需要满足什么样的关系?