秘银组件状态以不同的方式呈现不同

时间:2017-07-19 12:46:56

标签: javascript arrays mithril.js

所以,我有一个数组,我有2个组件(子和父),我遍历父组件内的数组,我渲染子组件,我从数组中给它们attrs(道具)。

子组件的attrs(props)递增和递减。

父组件可以将新项添加到数组中并重新渲染。

问题:为什么chid它使用.push()渲染,而使用.unshift()渲染不好。使用concat和[newItem,... oldArray]一切都还可以,但是当他们在数组前面添加项目时,同样的事情还不错?另外如何正确地将.unshift()新项目(评论,计数器,图像,帖子,例如任何东西)放入状态,以便首先渲染?

PS:React,Infero和Aurelia也会出现这种情况。

PPS:我的反应更多,也许我对待Mithril的vnode并不是我想的那样。

const root = document.getElementById('root')

var data = [0, 12, -10, 1, 0]

class app {
    oninit(vnode){
        vnode.state.data = data
    }
    oncreate(vnode) {
        vnode.state.addCounter = function(e){
            vnode.state.data.unshift(1)
        }
    }
    view(vnode){
        if(vnode.state.data){
            return([
                m('button',{onclick: vnode.state.addCounter},'add another counter'),
                vnode.state.data.map((e,i)=>{
                    return(
                        m(Counter, {data: e, key: i})
                    )
                })
            ])
        }
    }
}

class Counter {
    oninit(vnode){
        vnode.state.data = vnode.attrs.data
        vnode.state.increment = function(e){
            vnode.state.data = vnode.state.data + 1
        }
        vnode.state.decrement = function(e){
            vnode.state.data = vnode.state.data - 1;
        }
    }
    view(vnode){
        return(
            m('p',{style: 'display:inline;margin: 10px;'},[
                m('b',{onclick: vnode.state.increment, style:'cursor: pointer'}, '+'),
                m('i', vnode.state.data),
                m('b',{onclick: vnode.state.decrement, style:'cursor: pointer'}, '-')
            ])
        )
    }
}

m.mount(root, app)

1 个答案:

答案 0 :(得分:0)

错误是由key引起的。在渲染子项时使用数组索引作为键:

vnode.state.data.map((e,i)=>{
    return(
        m(Counter, {data: e, key: i})
    )
})

简单的解决方案是使用正确的密钥,在这种情况下,唯一有意义的是传递给孩子的数字:

vnode.state.data.map((number)=>{
    return(
        m(Counter, {data: number, key: number})
    )
})

小提琴:https://jsfiddle.net/6kh0ggrb/


代码失败的地方

通常使用数组索引作为键是一个坏主意(在任何键控库/框架中包括Mithril.js),并且您的用例就是一个很好的例子。

让我们一步一步地看看:

1:设置

您从数组[0, 12, -10, 1, 0]开始,并为数组中的相应数字渲染Counter。新组件的键为0到4。

------------------------
| key | number | shows |
------------------------
|   0 |      0 |     0 |
|   1 |     12 |    12 |
|   2 |    -10 |   -10 |
|   3 |      1 |     1 |
|   4 |      0 |     0 |
------------------------

2:添加到数组的开头

您将1添加到数组的开头,获取[1, 0, 12, -10, 1, 0]。这可以像你期望的那样工作。然而,当你渲染它时,前5个孩子有一个密钥,秘密重新组合,而不是创建新的组件,秘银使用与以前相同的组件。因此,在您的情况下,前五个组件将被重用。

因为你的Counter每个人只关心attrs收到的

class Counter {
    oninit(vnode){
        vnode.state.data = vnode.attrs.data
        ...

...重复使用相同的组件来呈现新号码将无效

------------------------------------------------
| key | current number |   prev number | shows |
------------------------------------------------
|   0 |              1 |             0 |     0 |
|   1 |              0 |            12 |    12 |
|   2 |             12 |           -10 |   -10 |
|   3 |            -10 |             1 |     1 |
|   4 |              1 |             0 |     0 |
|   5 |              0 | new component |     0 |
------------------------------------------------

现有的组件重用它们初始化的数字,只有最后一个使用它在attrs中收到的数字。