Mithril:event/dynamically 上的渲染组件
Mithril: render component on event/dynamically
试图掌握秘银的诀窍,却无法真正理解一件事。我可以在事件上渲染组件吗?
假设我有一个 parent 组件:
var MyApp = {
view: function() {
return m("div", [
m.component(MyApp.header, {}),
m("div", {id: "menu-container"})
])
}
};
m.mount(document.body, megogo.main);
它呈现 header 组件(和菜单的占位符(我什至需要它吗?)):
MyApp.header = {
view: function() {
return m("div", {
id: 'app-header'
}, [
m('a', {
href: '#',
id: 'menu-button',
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
}, 'Menu')
])
}
}
当用户单击菜单时 link 我想从 API 加载菜单项,然后才呈现菜单。
MyApp.menu = {
controller: function() {
var categories = m.request({method: "GET", url: "https://api.site.com/?params"});
return {categories: categories};
},
view: function(ctrl) {
return m("div", ctrl.categories().data.items.map(function(item) {
return m("a", {
href: "#",
class: 'link-button',
onkeydown: MyApp.menu.keydown
}, item.title)
}));
},
keydown: function(e){
e.preventDefault();
var code = e.keyCode || e.which;
switch(code){
// ...
}
}
};
这部分显然不行
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
那么,问题是在事件上渲染组件的正确方式是什么?
首先,您需要使用 m.component
的 return 值,或者通过 return 从 view
获取它,或者(更可能是你想要)把它作为另一个节点的 child ;使用 prop
来跟踪它当前是否打开,并在您希望打开它时设置 prop
。
回答实际问题:默认情况下,Mithril 会在 onclick
和 onkeydown
等事件发生时自行触发重绘,但要自行触发重绘,您需要使用m.redraw
or m.startComputation / m.endComputation
.
它们的区别在于m.redraw
一调用就会触发重绘,而m.startComputation
和m.endComputation
只会在m.endComputation
调用一次才触发重绘被调用的次数与 m.startComputation
被调用的次数相同,因此如果多个函数在完成后需要触发重绘,视图不会被重绘多次。
试试这个:
http://jsbin.com/nilesi/3/edit?js,output
您甚至可以切换菜单。
请记住,您从对 m.request 的调用中获得了包含在 m.prop 中的承诺。您需要检查它是否已返回,然后才能单击菜单按钮。
// I'd stick this in a view-model
var showMenu = m.prop(false)
var MyApp = {
view: function(ctrl) {
return m("div", [
m.component(MyApp.header, {}),
showMenu() ? m.component(MyApp.menu) : ''
])
}
};
MyApp.header = {
view: function() {
return m("div", {
id: 'app-header'
}, [
m('a', {
href: '#',
id: 'menu-button',
onclick: function(){
showMenu(!showMenu())
}
}, 'Menu')
])
}
}
MyApp.menu = {
controller: function() {
//var categories = m.request({method: "GET", url: "https://api.site.com/?params"});
var categories = m.prop([{title: 'good'}, {title: 'bad'}, {title: 'ugly'}])
return {categories: categories};
},
view: function(ctrl) {
return m("div.menu", ctrl.categories().map(function(item) {
return m("a", {
href: "#",
class: 'link-button',
onkeydown: MyApp.menu.keydown
}, item.title)
}));
},
keydown: function(e){
e.preventDefault();
var code = e.keyCode || e.which;
switch(code){
// ...
}
}
};
m.mount(document.body, MyApp);
试图掌握秘银的诀窍,却无法真正理解一件事。我可以在事件上渲染组件吗?
假设我有一个 parent 组件:
var MyApp = {
view: function() {
return m("div", [
m.component(MyApp.header, {}),
m("div", {id: "menu-container"})
])
}
};
m.mount(document.body, megogo.main);
它呈现 header 组件(和菜单的占位符(我什至需要它吗?)):
MyApp.header = {
view: function() {
return m("div", {
id: 'app-header'
}, [
m('a', {
href: '#',
id: 'menu-button',
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
}, 'Menu')
])
}
}
当用户单击菜单时 link 我想从 API 加载菜单项,然后才呈现菜单。
MyApp.menu = {
controller: function() {
var categories = m.request({method: "GET", url: "https://api.site.com/?params"});
return {categories: categories};
},
view: function(ctrl) {
return m("div", ctrl.categories().data.items.map(function(item) {
return m("a", {
href: "#",
class: 'link-button',
onkeydown: MyApp.menu.keydown
}, item.title)
}));
},
keydown: function(e){
e.preventDefault();
var code = e.keyCode || e.which;
switch(code){
// ...
}
}
};
这部分显然不行
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
那么,问题是在事件上渲染组件的正确方式是什么?
首先,您需要使用 m.component
的 return 值,或者通过 return 从 view
获取它,或者(更可能是你想要)把它作为另一个节点的 child ;使用 prop
来跟踪它当前是否打开,并在您希望打开它时设置 prop
。
回答实际问题:默认情况下,Mithril 会在 onclick
和 onkeydown
等事件发生时自行触发重绘,但要自行触发重绘,您需要使用m.redraw
or m.startComputation / m.endComputation
.
它们的区别在于m.redraw
一调用就会触发重绘,而m.startComputation
和m.endComputation
只会在m.endComputation
调用一次才触发重绘被调用的次数与 m.startComputation
被调用的次数相同,因此如果多个函数在完成后需要触发重绘,视图不会被重绘多次。
试试这个: http://jsbin.com/nilesi/3/edit?js,output
您甚至可以切换菜单。
请记住,您从对 m.request 的调用中获得了包含在 m.prop 中的承诺。您需要检查它是否已返回,然后才能单击菜单按钮。
// I'd stick this in a view-model
var showMenu = m.prop(false)
var MyApp = {
view: function(ctrl) {
return m("div", [
m.component(MyApp.header, {}),
showMenu() ? m.component(MyApp.menu) : ''
])
}
};
MyApp.header = {
view: function() {
return m("div", {
id: 'app-header'
}, [
m('a', {
href: '#',
id: 'menu-button',
onclick: function(){
showMenu(!showMenu())
}
}, 'Menu')
])
}
}
MyApp.menu = {
controller: function() {
//var categories = m.request({method: "GET", url: "https://api.site.com/?params"});
var categories = m.prop([{title: 'good'}, {title: 'bad'}, {title: 'ugly'}])
return {categories: categories};
},
view: function(ctrl) {
return m("div.menu", ctrl.categories().map(function(item) {
return m("a", {
href: "#",
class: 'link-button',
onkeydown: MyApp.menu.keydown
}, item.title)
}));
},
keydown: function(e){
e.preventDefault();
var code = e.keyCode || e.which;
switch(code){
// ...
}
}
};
m.mount(document.body, MyApp);