代码之家  ›  专栏  ›  技术社区  ›  ColdHands

Mithril组件状态使用unshift进行不同的渲染

  •  0
  • ColdHands  · 技术社区  · 9 年前

    子组件的属性(props)有递增和递减。

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

    问题:为什么chid用.push()表示ok,用.unshift()表示bad。concat和[newItem,…oldArray]也没问题,但当它们在数组前面添加项时,同样的东西会有问题吗?另外,如何正确地.unshift()将新项目(注释、计数器、图像、帖子,例如任何内容)转换为状态,以便它们首先呈现?

    PPS:我更喜欢反应,也许我对待米特里尔的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 回复  |  直到 9 年前
        1
  •  1
  •   Community Mohan Dere    6 年前

    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

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

    您添加 1 到数组的开头,获取 [1, 0, 12, -10, 1, 0]

    因为你们每个人 柜台 `s只关心 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 |
    ------------------------------------------------
    

    现有组件重用它们初始化时使用的数字,只有最后一个组件使用它在中接收的数字 属性