簡體   English   中英

秘銀:事件/動態渲染組件

[英]Mithril: render component on event/dynamically

試圖擺脫秘銀的束縛,真的無法理解一件事。 我可以在事件上渲染組件嗎?

假設我有一個父組件:

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, {})
}

因此,問題是在事件上呈現組件的正確方法是什么?

首先,您將希望使用m.component的返回值,方法是從view返回它,或者(更可能是您想要的)將其作為另一個節點的子m.component 使用prop來跟蹤prop當前是否處於打開狀態,並在希望打開prop時進行設置。

要回答實際問題:默認情況下,在發生諸如onclickonkeydown類的事件時,秘銀會觸發重繪本身,但是要自行觸發重繪,您將需要使用m.redrawm.startComputation / m.endComputation

它們之間的區別是, m.redraw將盡快它被稱為觸發重繪,而m.startComputationm.endComputation只會觸發一個重繪一次m.endComputation稱為該次等量m.startComputation被稱為,因此如果多個函數完成后需要觸發重繪,則視圖不會重繪一次。

試試看: http : //jsbin.com/nilesi/3/edit?js,輸出

您甚至可以切換菜單。

記住,從對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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM