秘银:在事件/动态渲染组件

时间:2015-08-05 16:45:10

标签: javascript mithril.js

试图了解秘银,不能理解一件事。我可以在事件上渲染组件吗?

假设我有一个父组件:

var MyApp = {
    view: function() {
        return m("div", [
            m.component(MyApp.header, {}),
            m("div", {id: "menu-container"})
        ])
    }

};

m.mount(document.body, megogo.main);

它呈现标题组件(以及菜单的占位符(我甚至需要它吗?)):

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')
        ])
    }
}

当用户点击菜单链接时,我想从我的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, {})
}

那么,问题是在事件上渲染组件的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

首先,您要使用m.component的返回值,方法是将其从view返回,或者(更可能是您想要的)将其作为子项另一个节点;使用prop跟踪当前是否已打开,并在您希望打开时设置prop

回答实际问题:默认情况下,当onclickonkeydown等事件发生时,Mithril会自动触发重绘,但要自行触发重绘,您会想要使用m.redrawm.startComputation / m.endComputation

它们之间的区别在于m.redraw会在调用后立即触发重绘,而m.startComputationm.endComputation只会触发一次重绘{{1}调用m.endComputation的次数相同,因此如果多个函数在完成后需要触发重绘,则不会重新绘制视图。

答案 1 :(得分:2)

试试这个: 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);