baidu / san

A fast, portable, flexible JavaScript component framework
https://baidu.github.io/san/
MIT License
4.73k stars 551 forks source link

this.data.set功能,在修改对象内的某个属性值时,对象内的属性顺序改变,是否合理? #693

Closed donghualei closed 3 years ago

donghualei commented 3 years ago

代码如下,

export default class App extends Component {
  static template = `
    <div>
      <span s-for="item in obj">
       {{item}}
     </span>
  </div>
`
    initData() {
        return {
            obj: {
                a: 0,
                b: 1,
                c: 2
            }
        };
    }
}

渲染后的结果为

<div>
            <span>
                0
            </span>
            <span>
                1
            </span>
            <span>
                2
            </span>
  </div>

如果我修改数据,this.data.set('obj.a', 3);

则渲染为

<div>
            <span>
                1
            </span>
            <span>
                2
            </span>
            <span>
                3
            </span>
  </div>

我觉得对象内属性值改变,不应该改变对象内的属性顺序,麻烦erik确认这个是否合理?如果确认属性顺序可以不改变,我提pr

errorrik commented 3 years ago

对象哪来的顺序

donghualei commented 3 years ago

对象哪来的顺序

跟往这个对象里面添加属性的顺序有关,在san的immutableSet这个方法中,每次修改对象中的某个值时,都是新创建了一个对象,先把不需要修改的属性直接复制,最后才添加了要修改的属性,导致了要修改的属性出现在了偏后;

function immutableSet(source, exprPaths, pathsStart, pathsLen, value, data) {
    if (pathsStart >= pathsLen) {
        return value;
    }

    if (source == null) {
        source = {};
    }

    var pathExpr = exprPaths[pathsStart];
    var prop = evalExpr(pathExpr, data);
    var result = source;

    if (source instanceof Array) {
        // console.log('source instanceof Array');
        var index = +prop;
        prop = isNaN(index) ? prop : index;

        result = source.slice(0);
        result[prop] = immutableSet(source[prop], exprPaths, pathsStart + 1, pathsLen, value, data);
    }
    else if (typeof source === 'object') {
        // console.log('typeof source === object', source);
        result = {};

        for (var key in source) {
            // console.log('key, prop', key, prop);
            /* istanbul ignore else  */
            if (key !== prop && source.hasOwnProperty(key)) {
                result[key] = source[key];
            }
        }
        // console.log('key, prop', result);

        result[prop] = immutableSet(source[prop], exprPaths, pathsStart + 1, pathsLen, value, data);
    }

    if (pathExpr.value == null) {
        exprPaths[pathsStart] = {
            type: typeof prop === 'string' ? 1 : 2,
            value: prop
        };
    }

    return result;
}

处理逻辑在else if (typeof source === 'object')这个里面?

errorrik commented 3 years ago

基本无成本的尽可能让可能的顺序变化影响更小,我觉得ok @donghualei 你提 pull-request 吧,issue 我关了

donghualei commented 3 years ago

基本无成本的尽可能让可能的顺序变化影响更小,我觉得ok @donghualei 你提 pull-request 吧,issue 我关了

收到,感谢errorrik