RubyLouvre / avalon

an elegant efficient express mvvm framework
http://avalonjs.coding.me/
Other
5.8k stars 1.42k forks source link

对象类型的vm的属性,无法同步新增key #75

Closed wiz-Cll closed 11 years ago

wiz-Cll commented 11 years ago

声明一个vm对象,其中设置它的一个属性为对象类型( 实际为一个map, 比如以guid为key ). 后期获取更多的数据后试图将新数据加入进去,结果在数据更新后视图没有更新.

是avalon现在还没有支持新增属性的视图同步吗? 还是obj类型也跟array类型一样有专门有划过的avalon内部方法来实现添加属性的操作?

wiz-Cll commented 11 years ago

大致代码如下:

var vmList = avalon.define('list',function(vm){
    vm.lists = processedList;
    vm.newList = function( e ){
        var newInput = e.target;
        if( newInput.value.trim() && e.which === 13 ){
            var newListGuid = ( new Date() ).valueOf();

                var newList = {
                    listName: newInput.value,
                    todoCount: 0,
                    shareState: 0,
                    listGuid: newListGuid
                };

                vm.lists[ newListGuid ] = newList;
                newInput.value = '';
        }
    };
}

其中procesedList形如:

{
    guid1: { prop1:val1, prop2: val2 },
    guid2: {}
    ... ...
}
RubyLouvre commented 11 years ago

https://github.com/RubyLouvre/avalon/blob/master/index21with.html

https://github.com/RubyLouvre/avalon/blob/master/index21with.html

看这里的例子,只能对VM的一个对象属性的键值进行增删

wiz-Cll commented 11 years ago

我在尝试用avalon实现类似 Wunderlist 的应用, todo的列表.按照上面给出的demo,已经可以实现以list数据的map对象作为vm的属性,然后用ms-with迭代, 如我在上面给出的代码,html部分:

<nav ms-controller="list">
    <ul ms-with="lists">
        <li ms-data-lid="$val.listGuid" ms-click="clickHandler"> {{ $val.listName }} 
            <span class="l-share"> {{ $val.shareState? '私有': '公开' }} </span> 
            <span class="l-count"> {{ $val.todoCount }} </span> 
        </li>
    </ul>
    <input id="new-input" type="text" placeholder="新建列表" ms-keyup="newList">
</nav>

新建列表时给processedList添加新的属性然后再付给vm.lists,正如你在demo中给出的:

processedList[ newListGuid ] = newList;
vm.lists = processedList;

一问: 这样有效率问题吗?全新的对象传给你,avalon做了这方面的优化吗? 二问: 在操作list对应的todo数据时,newTodo的操作的同时我希望可以把列表的todoCount字段也更新了: 注: list数据和todo数据是分开的两个对象: processedList 和 todoData , todoData是一个数组```

vm.newTodo = function( e ){
    if( e.target.value && e.which === 13 ){
        var newTodo = {
            name: e.target.value,
            status: 0
        };
        var len = vm.todoData.length;
        for(var i=0; i<len; i++){
            if( vm.todoData[i].listGuid === vm.curLGuid ){
                vm.todoData[i].data.push( newTodo );
                break;
            }
            else{
                continue;
            }

        }

        e.target.value = '';
        processedList[ vm.curLGuid ].todoCount++;
        vm.lists = processedList;

    }
};

这时绑定的list列表中的数据并没有更新,这个有什么解决方案吗?

RubyLouvre commented 11 years ago

是你用法不对吧。不可能不更新的。

给出一个简单的页面我看看

你为什么不用 ms-each 这里的例子与你的需求应该好相似 http://rubylouvre.github.io/mvvm/todos.html 你仔细把我的 项目下以index开头的html示例都运行一遍,再看入门教程

wiz-Cll commented 11 years ago

地址: wunderlist的avalon实现

昨天提了问题之后跟同事讨论了,确实使用ms-each更好,然后创建一个对应vm.lists数组中元素的map,方便根据guid操作. 不过确实不能更新哈,请司徒桑看看是什么问题~

RubyLouvre commented 11 years ago

大大简化一下你的代码,样式还是原来的样式

html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
nav,
section {
  height: 100%;
  outline: 1px solid #000;
}
nav {
  width: 500px;
  float: left;
  background: #557799;
  color: #ffffff;
}
nav #new-input {
  margin-left: 40px;
  height: 2em;
  width: 250px;
}
section {
  margin-left: 500px;
}
#newtodo-input,
#new-input {
  margin-left: 40px;
  height: 2em;
  width: 250px;
}
ul {
  list-style: none;
}
ul li {
  hegiht: 2em;
  padding: 0.25em;
  font-size: 1em;
  line-height: 1.5em;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-transition: all 300ms ease;
  -moz-transition: all 300ms ease;
  -ms-transition: all 300ms ease;
  -o-transition: all 300ms ease;
  transition: all 300ms ease;
  cursor: pointer;
}
ul li:hover {
  background: #ffffff;
  color: #557799;
}
ul li .l-count,
ul li .l-share {
  float: right;
  margin-right: 20px;
}

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Avalon简单实现wunderlist</title>
        <link rel="stylesheet" href="list.css" />
        <script src="avalon.js"></script>
        <script src="list.js">     </script>
    </head>
    <body ms-controller="list">
        <nav >
            <ul ms-each-el="lists">
                <li  ms-click="show(el.listGuid)"> {{ el.listName }} 
                    <span class="l-share"> {{ el.shareState? '私有': '公开' }} </span> 
                    <span class="l-count"> {{ el.data.size() }} </span> 
                </li>
            </ul>
            <input id="new-input" type="text" placeholder="新建列表" ms-keyup="addList">
        </nav>
        <section>

            <div ms-each-el="lists">
                <div ms-visible="el.listGuid == showId">
                    <input type="text" id="newtodo-input" placeholder="新建待办事项" ms-keyup="addData($event,el)">
                    <ul ms-each-elem="el.data"  >
                        <li>{{ elem.name }}  <span>{{ elem.status? '已完成':'未完成' }}</span>
                            <button type="button" ms-click="$remove">remove</button>
                        </li>

                    </ul>
                </div>
            </div>

        </section>

    </body>
</html>

avalon.ready(function() {
    var listData = [
        {
            listName: 'less推动样式表模块化开发',
            shareState: 0,
            listGuid: '01010101',
            data: [
                {
                    name: 'xxxxxxxxx',
                    status: 0
                },
                {
                    name: 'yyyyyyyy',
                    status: 0
                }
            ]
        },
        {
            listName: '企业管理后台的mvvm实现',
            shareState: 1,
            listGuid: '10101010',
            data: [
                {
                    name: '11111111',
                    status: 0
                },
                {
                    name: '222222',
                    status: 0
                },
                {
                    name: '3333333',
                    status: 0
                }
            ]
        },
        {
            listName: 'lifeStyle',
            shareState: 0,
            listGuid: '11111111',
            data: [{
                    name: 'tttttt',
                    status: 0
                },
                {
                    name: 'ssssss',
                    status: 0
                },
                {
                    name: 'ooooooo',
                    status: 0
                }
            ]
        }
    ];
    avalon.define('list', function(vm) {
        vm.lists = listData;
        vm.addList = function(e) {
            if (this.value.trim() && e.which === 13) {
                var newList = {
                    listName: this.value,
                    shareState: 0,
                    listGuid: new Date - 0,
                    data: []
                }
                vm.lists.push(newList)
                this.value = '';
            }
        };
        vm.showId = "01010101"
        vm.show = function(id) {
            vm.showId = id
        };
        vm.addData = function(e, el) {
            if (this.value.trim() && e.which === 13) {
                el.data.push({
                    name: this.value,
                    status: 0
                })
                this.value = '';
            }
        }

    });

    avalon.scan();
});
RubyLouvre commented 11 years ago

我改一改,放到官网上展示了 http://rubylouvre.github.io/mvvm/avalon.wunderlist.html

wiz-Cll commented 11 years ago

en,确实简洁了很多.ok,我把issue关了啊~