问题
in knockoutjs you can output the ViewModel in a nice json format for debugging
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
if there is a way to accomplish the same in Aurelia
回答1:
You could create a custom element.
Here's an example: https://gist.run?id=9eea8902521f4523ee2c
app.html
<template>
<require from="./debug"></require>
<input value.bind="firstName">
<input value.bind="lastName">
<debug></debug>
</template>
app.js
export class App {
firstName = 'Donald';
lastName = 'Draper';
}
debug.html
<template>
<pre><code>${json}</code></pre>
</template>
debug.js
export class Debug {
bindingContext = null;
updateJson() {
if (this.bindingContext === null) {
this.json = 'null';
} else if (this.bindingContext === undefined) {
this.json = 'undefined'
} else {
// todo: use a stringify function that can handle circular references.
this.json = JSON.stringify(this.bindingContext, null, 2);
}
}
bind(bindingContext) {
this.bindingContext = bindingContext;
this.updateJson();
this.interval = setInterval(::this.updateJson, 150);
}
unbind() {
this.bindingContext = null;
clearInterval(this.interval);
}
}
Result
回答2:
The closest I've got is to define a Value Converter. So in json.js
I have
export class JsonValueConverter {
toView(value) {
return JSON.stringify(value, null, "\t");
}
}
then in my view-model index.js
I have my data:
export class IndexViewModel {
data = {
name: "nobody!"
};
}
and finally the view index.hml
binds and uses the converter:
<template>
<require from="../resources/converters/json"></require>
<pre textContent.bind="customElementModel | json"></pre>
</template>
However, I'm stumped at the moment by the lack of live binding between the model and the HTML so this may not fully answer your question?
回答3:
As an addendum to the answer of Jeremy Danyow, you can also use a custom binding behavior on a particular attribute of your view model, instead of the whole view model. This has the advantage that you have control over the elements you want to see, therefore you can avoid the problem with circular dependencies (if you watch only those elements you know to be non-circular...)
First define a JsonValueConverter (same as the one in Phil's answer):
export class JsonValueConverter {
toView(value) {
return JSON.stringify(value, null, " ");
}
}
Then the binding behavior. Note that the binding notifies itself via a custom signal to cope with deep model updates.
import {inject} from "aurelia-dependency-injection";
import {ValueConverter} from "aurelia-binding";
import {BindingSignaler, SignalBindingBehavior} from "aurelia-templating-resources";
@inject(BindingSignaler, SignalBindingBehavior)
export class JsonBindingBehavior {
constructor(signaler, signalBindingBehavior) {
this.signaler = signaler;
this.signalBindingBehavior = signalBindingBehavior;
}
bind(binding, scope) {
// bind the signal behavior (ie. listen on signal 'update-json')
this.signalBindingBehavior.bind(binding, scope, 'update-json');
// rewrite the expression to use the JsonValueConverter.
// pass through any args to the binding behavior to the JsonValueConverter
let sourceExpression = binding.sourceExpression;
// do create the sourceExpression only once
if (sourceExpression.rewritten) {
return;
}
sourceExpression.rewritten = true;
let expression = sourceExpression.expression;
sourceExpression.expression = new ValueConverter(
expression,
'json',
sourceExpression.args,
[expression, ...sourceExpression.args]);
// send signal to ourselves each 150ms to update the binding
this.interval = window.setInterval(() => this.signaler.signal('update-json'), 150);
}
unbind(binding, scope) {
window.clearInterval(this.interval);
this.signalBindingBehavior.unbind(binding, scope);
}
}
You can put both classes in the same file, e.g. json.js
. Then require it in your template:
<template>
<require from="./json"></require>
...
<pre>${myData & json}</pre>
</template>
... or make it available as a global resource.
Here's an example: https://gist.run/?id=bde01135fa85f76202c72c11d3cb183a
You could also extract the signalling to a second custom behaviour, just as Jeremy Danyow did in this SO answer. With this in place, you would just do:
${myData | json & signal:'tick'}
来源:https://stackoverflow.com/questions/32365884/debug-aurelia-viewmodel-similar-to-ko-tojson