Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active July 14, 2016 00:29
Show Gist options
  • Save niieani/a986f5c6e3c5202d64b3d49a084981d0 to your computer and use it in GitHub Desktop.
Save niieani/a986f5c6e3c5202d64b3d49a084981d0 to your computer and use it in GitHub Desktop.
Aurelia: Suboptimal repeat element lifecycle [alternative swap arrays + diffing + 9000 elements]
<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 = []
this.componentsAlternative = []
for (let i = 0; i <= 9000; i++) {
this.components.push(i)
this.componentsAlternative.push(i)
}
this.componentsAlternative[5] = 'changed'
this.componentsProxy = this.components.slice(0);
}
swapArrays() {
[this.components, this.componentsAlternative] = [this.componentsAlternative, this.components]
const differences = DeepDiff.diff(this.componentsProxy, this.components)
/* 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]];
}
switch (change.kind) {
case 'A':
applyArrayChange(change.path ? it[change.path[i]] : it, change.index, change.item);
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) {
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':
applyArrayChange(it[change.path[i]], change.index, change.item);
break;
case 'D':
it.splice(change.path[i], 1)
break;
case 'E':
it.splice(change.path[i], 1, change.rhs)
break;
case 'N':
it.splice(change.path[i], 0, change.rhs)
break;
}
} else {
switch (change.kind) {
case 'A':
applyArrayChange(arr[index], change.index, change.item);
break;
case 'D':
arr.splice(index, 1)
break;
case 'E':
arr.splice(index, 1, change.rhs)
break;
case 'N':
arr.splice(index, 0, change.rhs)
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