前端mvvm框架底层学习(二、数组处理)

前言

上一篇《前端mvvm框架学习(一、我们来实现一个最简单的MVVM)》介绍了我们如何实现一个最简单的MVVM。但之前处理过的model数值都只是最原始的数值(即primitive类型,如string,number,symbol,boolean)。这一篇我们尝试来处理数组类型,怎么简单怎么来吧,我们引用lodash库和还是用传统的方式拼接html字符串的方式来处理View层吧。

接着上一篇的代码,添加对数组的处理,生成一个表格


See the Pen MVVM Array by Nelson Kuang (@nelsonkuang) on CodePen
1

View层代码:

<div id="classmates">
  <h3>Classmates</h3>
  <table>
    <thead><tr><th>Name</th><th>Gender</th><th>Age</th></tr></thead>
    <tbody id="classmates__list">
      <!-- 下面是 mvvm 中的 View层 -->
      <tr><td>张三</td><td>男</td><td>18</td></tr>
      <tr><td>李四</td><td>男</td><td>17</td></tr>
      <tr><td>王五</td><td>女</td><td>19</td></tr>
    </tbody>
  </table>
</div>

Model层代码 :

var newPerson = {
  name: 'Nelson Kuang',
  age: 18,
  classMates: [ // 新增的数组model数据
    {
      name: '张三',
      gender: '男',
      age: 18
    },
    {
      name: '李四',
      gender: '男',
      age: 17
    },
    {
      name: '王五',
      gender: '女',
      age: 19
    }
  ]
};

ViewModel层代码:

function updateTable(newVal, oldVal) { // 传统的拼接html字符串的方式实现更新视图View
  if(_.isArray(newVal)) {
    var el = document.querySelector('#classmates__list'),
        strHtml = '';
    newVal.forEach(function(item){
      strHtml += '<tr><td>' + item.name + '</td><td>' + item.gender + '</td><td>' + item.age + '</td></tr>';
    })
    el.innerHTML = strHtml
  }
}
Object.defineProperty(newPerson, 'classMates', {
    set: function (x) {
        if (!_.isEqual(x, this.oldPropValue)) { // 数组或者对象的比较与普通的数值的比较不一样,要深度遍历进行比较
          console.log(x);
          updateTable(x, this.oldPropValue);
          this.oldPropValue = x;
        } else {
            console.log('classMates的值没变')
        }
    },
    get: function () {
        console.log('in property get accessor');
        return this.oldPropValue;
    },
    enumerable: true,
    configurable: true
});

为什么数组Array及对象Object类型不能直接用“==”或者‘‘’===’来进行比较呢?下面的代码就可以发现问题所在,数组及对象类型都是Object类型,两个对象存储的地址是不一样,所以肯定不相等。因此我们只能通过遍历的方式的对对象的所有属性及其顺序进行比较才能知道两对象是否相等,lodash库的isEqual函数也是这样实现的。

[1,2] === [1,2] // => false
{a:1} === {a:1}  // => false
_.isEqual([1,2], [1,2]) // => true
_.isEqual({a:1}, {a:1}) // => true

现在尝试更新Model层数据,View层应该就可以自动更新了。

  setTimeout(function(){
    // mvvm 数据驱动开发方式
    newPerson.name = 'Gary Li'
    newPerson.age = 20
    newPerson.classMates = [ // 修改新增的model数据
    {
      name: '小明',
      gender: '男',
      age: 17
    },
    {
      name: '小强',
      gender: '男',
      age: 19
    },
    {
      name: '小梅',
      gender: '女',
      age: 19
    }]
  }, 5000)

结束语

通过上面的demo我们可以知道,处理数组数据其实在实际项目中是会经常会遇到的,但上面我们还是用了的传统处理方式来做出MVVM的风格,这样实现肯定还会有很多的问题的,下一篇我们继续来优化上面的Demo,看看可以玩成怎么样。

作者: 博主

Talk is cheap, show me the code!