Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active April 19, 2016 17:11
Show Gist options
  • Save niieani/bf67e4f99a44924eaea2b4540826eccc to your computer and use it in GitHub Desktop.
Save niieani/bf67e4f99a44924eaea2b4540826eccc to your computer and use it in GitHub Desktop.
Aurelia: Suboptimal repeat element lifecycle [alternative swap arrays + diffing v2]
<template>
<require from="./component"></require>
<button click.delegate="swapArrays()">Swap arrays</button>
<br>
<component
repeat.for="id of componentsProxy"
id.bind="id"
></component>
</template>
import {Component} from './component'
export class App {
constructor() {
// this.components = [6, 51, 7, 8, 9, 10, 51]
// this.componentsAlternative = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
this.components = [1, 2, 3, 4, 5, 1, 2]
this.componentsAlternative = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
this.componentsProxy = this.components.slice(0);
}
swapArrays() {
[this.components, this.componentsAlternative] = [this.componentsAlternative, this.components]
const differences = DeepDiff.diff(this.componentsProxy, this.components)
console.log(differences)
/* We must apply the differences in reverse order, since the array indices
in the diff become stale/invalid if you delete elements from the array
whose indices are in ascending order */
for (let i = differences.length - 1; i >= 0; i--) {
applyChange(this.componentsProxy, true, differences[i])
}
}
}
function applyChange(target, source, change) {
if (target && source && change && change.kind) {
var it = target,
i = -1,
last = change.path ? change.path.length - 1 : 0;
while (++i < last) {
if (typeof it[change.path[i]] === 'undefined') {
it[change.path[i]] = (typeof change.path[i] === 'number') ? [] : {};
}
it = it[change.path[i]];
}
let shift = 0
switch (change.kind) {
case 'A':
shift += applyArrayChange(change.path ? it[change.path[i]] : it, change.index, change.item, shift);
break;
case 'D':
if (it instanceof Array)
it.splice(change.path[i], 1);
else
delete it[change.path[i]];
break;
case 'E':
if (it instanceof Array)
it.splice(change.path[i], 1, change.rhs)
else
it[change.path[i]] = change.rhs
break;
case 'N':
if (it instanceof Array)
it.splice(change.path[i], 0, change.rhs)
else
it[change.path[i]] = change.rhs
break;
}
}
}
function applyArrayChange(arr, index, change, shift) {
if (change.path && change.path.length) {
var it = arr[index],
i, u = change.path.length - 1;
for (i = 0; i < u; i++) {
it = it[change.path[i]];
}
switch (change.kind) {
case 'A':
return applyArrayChange(it[change.path[i]], change.index, change.item, shift);
break;
case 'D':
it.splice(change.path[i] + shift, 1)
return -1
break;
case 'E':
it.splice(change.path[i] + shift, 1, change.rhs)
return 0
break;
case 'N':
it.splice(change.path[i] + shift, 0, change.rhs)
return 1
break;
}
} else {
switch (change.kind) {
case 'A':
return applyArrayChange(arr[index], change.index, change.item, shift);
break;
case 'D':
arr.splice(index + shift, 1)
return -1
break;
case 'E':
arr.splice(index + shift, 1, change.rhs)
return 0
break;
case 'N':
arr.splice(index + shift, 0, change.rhs)
return 1
break;
}
}
return arr;
}
import {inlineView, bindable} from 'aurelia-framework'
@inlineView('<template>${id}<br></template>')
export class Component {
@bindable id
bind() {
console.log('bind', this.id)
}
unbind() {
console.log('unbind', this.id)
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script src="https://rawgit.com/flitbit/diff/master/releases/deep-diff-0.3.3.min.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script>
<script>
require(['aurelia-bootstrapper']);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment