|
28 | 28 | callback = ops.callback || function (item) {
|
29 | 29 | changes.push(item);
|
30 | 30 | },
|
31 |
| - i, len, prop, id, newIndex; |
| 31 | + i, len, prop, id; |
32 | 32 |
|
33 | 33 | if (!isObject(oldObj) || !isObject(newObj)) {
|
34 | 34 | if (oldObj !== newObj) {
|
|
55 | 55 |
|
56 | 56 | if (sample === UNDEFINED) return changes;
|
57 | 57 |
|
58 |
| - if (typeof sample === 'object') { |
59 |
| - var idProp = |
60 |
| - (ops.idProps && |
61 |
| - ( |
62 |
| - ops.idProps[oldPath.map(numberToAsterisk).join('.')] || |
63 |
| - ops.idProps[oldPath.join('.')] |
64 |
| - )) || ID_PROP, |
65 |
| - oldHash = indexBy(oldObj, idProp), |
66 |
| - newHash = indexBy(newObj, idProp); |
67 |
| - |
68 |
| - for (i = 0, len = oldObj.length; i < len; i++) { |
69 |
| - id = oldObj[i][idProp]; |
70 |
| - newIndex = newObj.indexOf(newHash[id]); |
71 |
| - |
72 |
| - if (_DEV_) { |
73 |
| - if (typeof id === 'undefined') { |
74 |
| - console.error('item #%s do not has "%s" property in array %s', i, idProp, oldPath.join('.')); |
75 |
| - } |
76 |
| - } |
| 58 | + var objective = typeof sample === 'object'; |
77 | 59 |
|
78 |
| - if (newIndex === -1 || i >= newObj.length || id !== newObj[i][idProp]) { |
79 |
| - callback({ |
80 |
| - oldPath: oldPath, |
81 |
| - newPath: newPath, |
82 |
| - type: newIndex === -1 ? REMOVE_ITEM_EVENT : MOVE_ITEM_EVENT, |
83 |
| - oldIndex: i, |
84 |
| - newIndex: newIndex |
85 |
| - }); |
86 |
| - } |
| 60 | + var idProp = |
| 61 | + (objective && ops.idProps && |
| 62 | + ( |
| 63 | + ops.idProps[oldPath.map(numberToAsterisk).join('.')] || |
| 64 | + ops.idProps[oldPath.join('.')] |
| 65 | + )) || ID_PROP, |
| 66 | + oldHash = objective ? indexBy(oldObj, idProp) : hashOf(oldObj), |
| 67 | + newHash = objective ? indexBy(newObj, idProp) : hashOf(newObj), |
| 68 | + curArray = [].concat(oldObj), |
| 69 | + curIndex, oldIndex; |
87 | 70 |
|
88 |
| - if (newHash.hasOwnProperty(id)) { |
89 |
| - diff(oldObj[i], newHash[id], extend({}, ops, { |
90 |
| - callback: callback, |
91 |
| - oldPath: oldPath.concat(i), |
92 |
| - newPath: newPath.concat(newIndex) |
93 |
| - })); |
94 |
| - } |
95 |
| - } |
| 71 | + for (i = 0, len = oldObj.length; i < len; i++) { |
| 72 | + id = objective ? oldObj[i][idProp] : oldObj[i]; |
96 | 73 |
|
97 |
| - for (i = 0, len = newObj.length; i < len; i++) { |
98 |
| - if (_DEV_) { |
99 |
| - if (typeof newObj[i][idProp] === 'undefined') { |
100 |
| - console.error('item #%s do not has "%s" property in array %s', i, idProp, newPath.join('.')); |
101 |
| - } |
102 |
| - } |
| 74 | + if (!newHash.hasOwnProperty(id)) { |
| 75 | + curIndex = curArray.indexOf(oldObj[i]); |
| 76 | + curArray.splice(curIndex, 1); |
103 | 77 |
|
104 |
| - if (!oldHash.hasOwnProperty(newObj[i][idProp])) { |
105 |
| - callback({ |
106 |
| - oldPath: oldPath, |
107 |
| - newPath: newPath, |
108 |
| - type: ADD_ITEM_EVENT, |
109 |
| - oldIndex: -1, |
110 |
| - newIndex: i, |
111 |
| - newValue: newObj[i] |
112 |
| - }); |
113 |
| - } |
| 78 | + callback({ |
| 79 | + oldPath: oldPath, |
| 80 | + newPath: newPath, |
| 81 | + type: REMOVE_ITEM_EVENT, |
| 82 | + oldIndex: i, |
| 83 | + curIndex: curIndex, |
| 84 | + newIndex: -1 |
| 85 | + }); |
114 | 86 | }
|
115 | 87 | }
|
116 |
| - else { |
117 |
| - var oldObjHash = {}, offset = 0; |
118 |
| - |
119 |
| - for (i = 0, len = oldObj.length; i < len; i++) { |
120 |
| - oldObjHash[oldObj[i]] = i; |
121 |
| - |
122 |
| - newIndex = newObj.indexOf(oldObj[i]); |
123 |
| - |
124 |
| - if (newIndex === -1 || (oldObj[i] !== newObj[i] && oldObj[i] !== newObj[i - offset])) { |
125 |
| - callback({ |
126 |
| - oldPath: oldPath, |
127 |
| - newPath: newPath, |
128 |
| - type: newIndex === -1 ? REMOVE_ITEM_EVENT : MOVE_ITEM_EVENT, |
129 |
| - oldIndex: i, |
130 |
| - newIndex: newIndex |
131 |
| - }); |
132 |
| - } |
133 | 88 |
|
134 |
| - if (newIndex === -1) { |
135 |
| - offset++; |
| 89 | + for (i = 0, len = newObj.length; i < len; i++) { |
| 90 | + id = objective ? newObj[i][idProp] : newObj[i]; |
| 91 | + |
| 92 | + if (!oldHash.hasOwnProperty(id)) { |
| 93 | + callback({ |
| 94 | + oldPath: oldPath, |
| 95 | + newPath: newPath, |
| 96 | + type: ADD_ITEM_EVENT, |
| 97 | + oldIndex: -1, |
| 98 | + curIndex: -1, |
| 99 | + newIndex: i, |
| 100 | + newValue: newObj[i] |
| 101 | + }); |
| 102 | + |
| 103 | + if (i >= curArray.length) { |
| 104 | + curArray.push(newObj[i]); |
| 105 | + } |
| 106 | + else { |
| 107 | + curArray.splice(i, 0, newObj[i]); |
136 | 108 | }
|
137 | 109 | }
|
| 110 | + } |
138 | 111 |
|
139 |
| - for (i = 0, len = newObj.length; i < len; i++) { |
140 |
| - if (!oldObjHash.hasOwnProperty(newObj[i])) { |
141 |
| - callback({ |
142 |
| - oldPath: oldPath, |
143 |
| - newPath: newPath, |
144 |
| - type: ADD_ITEM_EVENT, |
145 |
| - oldIndex: -1, |
146 |
| - newIndex: i, |
147 |
| - newValue: newObj[i] |
148 |
| - }); |
149 |
| - } |
| 112 | + for (i = 0, len = newObj.length; i < len; i++) { |
| 113 | + id = objective ? newObj[i][idProp] : newObj[i]; |
| 114 | + |
| 115 | + if (!oldHash.hasOwnProperty(id)) continue; |
| 116 | + |
| 117 | + oldIndex = oldObj.indexOf(oldHash[id]); |
| 118 | + curIndex = curArray.indexOf(oldHash[id]); |
| 119 | + |
| 120 | + if (i !== curIndex) { |
| 121 | + callback({ |
| 122 | + oldPath: oldPath, |
| 123 | + newPath: newPath, |
| 124 | + type: MOVE_ITEM_EVENT, |
| 125 | + oldIndex: oldIndex, |
| 126 | + curIndex: curIndex, |
| 127 | + newIndex: i |
| 128 | + }); |
| 129 | + |
| 130 | + curArray.splice(curIndex, 1); |
| 131 | + curArray.splice(i, 0, oldHash[id]); |
150 | 132 | }
|
| 133 | + |
| 134 | + diff(oldHash[id], newObj[i], extend({}, ops, { |
| 135 | + callback: callback, |
| 136 | + oldPath: oldPath.concat(oldIndex), |
| 137 | + newPath: newPath.concat(i) |
| 138 | + })); |
151 | 139 | }
|
152 | 140 | }
|
153 | 141 | else {
|
|
224 | 212 | return hash;
|
225 | 213 | }
|
226 | 214 |
|
| 215 | + function hashOf(array) { |
| 216 | + var hash = {}; |
| 217 | + |
| 218 | + for (var i = 0, len = array.length; i < len; i++) { |
| 219 | + hash[array[i]] = array[i]; |
| 220 | + } |
| 221 | + |
| 222 | + return hash; |
| 223 | + } |
| 224 | + |
227 | 225 | function extend(target) {
|
228 | 226 | for (var i = 1, len = arguments.length; i < len; i++) {
|
229 | 227 | var source = arguments[i];
|
|
0 commit comments