Beyond Console.log, Episod III: Benotzerdefinéiert Formater an Devtools

Dësen Artikel ass Deel vun enger Serie vu Pabeieren op der Chrome Console;
Virdrun op "Beyond console.log"
Sidd Dir midd fir ze gesinn datt Är Objekter ëmmer op déiselwecht Manéier an der Konsol ageloggt sinn? Dir hutt d'Chrome Dev Tools gär, awer Dir wëllt den Numm vun den Instanzen vun Eleve gëtt a rout, orange oder gréng ugewisen jee no sengem Wäert? Bleift op dëser Säit, Dir musst net méi wäit goen.

Viraussetzung: aktivéiert Custom Formatter

An DevTools, gitt op d'Astellungen, kontrolléiert dann d'Këscht "Enable Custom Formatter" an der Rubrik "Konsol".

Wat sinn Custom Formatter?

Les Benotzerdefinéiert Formater sinn eng Array vun Objeten am Objet gespäichert window. Si erlaben eis den Affichage vun engem bestëmmten Objet ze personaliséieren wéi mir wëllen. Sou kënne si d'Liesbarkeet vun eise Logbicher staark verbesseren. Oder besser: maachen d'Ae vun eise Kollegen bludden (kuckt hei ënnen).
Screenshot vun wann mir aloggen () en Objet mat de Benotzerdefinéiert formatters: hei schéngen d'Bréiwer op Feier!
Trotz der Nëtzlechkeet fannen ech dat net e wäit bekannten Thema, et ginn eng ganz kleng Unzuel un Artikelen zum Thema um Netz, alles op Englesch. Ouni weider Gedold, loosst eis dës Ongerechtegkeet fixéieren andeems mir eis Hänn dreckeg maachen.

D'Zil

  • Als éischt wäerte mir suergen datt d'Instanzen vun eiser zukünfteger Studenteklass hiren Numm am Format Virnumm + NUMM weisen, an dëst muss rout bis gréng faarweg sinn no der Moyenne vu senge Marken.
  • Da wäerte mir suergen, datt Dir en einfach erhale Code hutt

loosst eis Code

Als éischt, loosst eis d'Studenteklass codéieren:

class Student {
    constructor(firstname, lastname, notations) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.notations = notations;
    }
    getAverageNotation() {
        return this.notations.reduce((total, notation) => total += notation, 0) / this.notations.length;
    }
}

... Dann erkläre mer eise Formater an fügen se an d'Array derbäi:

const studentFormatter = {
    header: (x) => {
        if (x instanceof Student) {
            const moyenne = x.getAverageNotation();
            const color = (moyenne > 15) ? 'limegreen' : (moyenne > 5) ? 'orangered' : 'firebrick';
            return [
                'span',
                {
                    style: 'color: ' + color
                },
                x.lastname.toUpperCase() + ' ' + x.firstname
            ];
        }
    },
    hasBody: x => x instanceof Student,
    body: (x) => {
        return [
            'table',
            {},
            ['tr', {},
                ['td', {style: 'color: burlywood'}, 'Prénom: '],
                ['td', {}, `${x.firstname}`],
            ],
            ['tr', {},
                ['td', {style: 'color: burlywood'}, 'Nom: '],
                ['td', {}, `${x.lastname}`],
            ],
            ['tr', {},
                ['td', {style: 'color: burlywood'}, 'Notes: '],
                ['object', {object: x.notes}],
            ],
        ];
    }
};
window.devtoolsFormatters = [ studentFormatter ];

Elo kënne mir eng Rei vu Studenten aloggen:

const ducobu = new Student('Élève', 'Ducobu', [2, 5, 3]);
const willHunting = new Student('William', 'Hunt', [18, 20, 19]);
const nicolasLePetit = new Student('Nicolas', 'Le Petit', [10, 10, 10]);
console.info([ducobu, willHunting, nicolasLePetit]);

Screenshot vun devtools wann Dir en Objet mat Custom Formatter protokolléiert

Kuerz Code Analyse

moss opgereegt
Wow, et ass Magie, d'Nimm vun de Studenten erschéngen an Haaptstied an et ass faarweg no der Moyenne! Wéi konnt ech ouni sou wäit liewen? Mäi Liewen als Programméierer ass fir ëmmer geännert!
All Objet an der personaliséierter Formater-Array muss dräi Methoden hunn: Kappball, deen e JSONML-Objet muss maachen, deen benotzt gëtt fir den Numm vum Objet ze weisen wann en zesummegeklappt ass, huet Kierper, wat weist ob den Objet ausklappbar ass a schlussendlech Kierper déi d'HTML-Schabloun vum ausgeklappte Kierper vum Objet muss maachen, am JSONML-Format. Wéi och ëmmer, déi eenzeg erlaabt HTML Elementer sinn Dësch, tr, ts, ol, li, div et span
Hei kucken ech ob x ass eng Instanz vun Student avec instanceof. Notéiert datt dëst zréck wäert true fir all Ënnerklass vun Student. Wa mir de Formatter nëmmen aktivéiere wollten wann den Objet genee eng Instanz ass Student, mir hätte kënne schreiwen:
if (x.constructor === Student)

Géi méi wäit

All dat ass wierklech net schlecht. Awer an engem grousse Projet gesinn ech net datt d'Leit d'Klass addéieren déi se just an d'Fënster erstallt hunn.devtoolsFormatters Array vun der Hand. Et wier besser wann de Student CustomFormatter an der Klass selwer definéiert wier. Mee dat géif en Nodeel duerstellen: et géif eis Schüler verschmotzen, et kéint zu Kollisiounen féieren. Et ass mat dëser Aart vu Probleemer am Kapp datt mir vu Symboler profitéieren:

const CustomFormatterToken = Symbol('CustomFormatter');
// en ajoutant cette propriété à Symbol, ça permet à notre
// fonctionnalité d'être accessible partout :
Symbol.customFormatter = CustomFormatterToken;
// Voici la nouvelle version de la classe Eleve :
class Student {
    constructor(firstname, lastname, notations) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.notations = notations;
    }
    get [CustomFormatterToken]() {
        return {
            header: () => {
                const averageNotation = this.getAverageNotation();
                const color = (moyenne > 15) ? 'limegreen' : (moyenne > 5) ? 'orangered' : 'firebrick';
                return [
                    'span',
                    {
                        style: 'color: '+ color + '}'
                    },
                    this.lastname.toUpperCase() + 'this.firstname'
                ];
            },
            hasBody: () => true,
            body: () => [
                'table',
                {},
                ['tr', {},
                    ['td', {style: 'color: burlywood'}, 'prenom: '],
                    ['td', {}, `${this.firstname}`],
                ],
                ['tr', {},
                    ['td', {style: 'color: burlywood'}, 'nom: '],
                    ['td', {}, `${this.lastname}`],
                ],
                ['tr', {},
                    ['td', {style: 'color: burlywood'}, 'notes: '],
                    ['object', {object: this.notations}],
                ],
            ]
        };
    }
    getAverageNotation() {
        return this.notations.reduce((total, notation) => total += notation, 0) / this.notations.length;
    }
}
// Dorénavant, devtoolsFormatters n'aura qu'une seule valeur : AllPurposeFormatter
const AllPurposeFormatter = {
    header: x => {
        const formatter = x[Symbol.customFormatter];
        if (formatter) {
            return formatter.header();
        }
    },
    hasBody: x => {
        const formatter = x[Symbol.customFormatter];
        if (formatter) {
            return formatter.hasBody();
        }
    },
    body: x => {
        const formatter = x[Symbol.customFormatter];
        if (formatter) {
            return formatter.body();
        }
    },
};
window.devtoolsFormatters = [ AllPurposeFormatter ];
const ducobu = new Student('Élève', 'Ducobu', [2, 5, 3]);
const willHunting = new Student('William', 'Hunt', [18, 20, 19]);
const nicolasLePetit = new Student('Nicolas', 'Le Petit', [10, 10, 10]);
console.info([ducobu, willHunting, nicolasLePetit]);
// les propriétés qui ont pour clé un symbole n'apparaissent pas...
// Notre objet n'est pas pollué \o/
console.log(Object.keys(ducobu)); // => ["firstname", "lastname", "notations"]

Trainere
Gutt, dat ass alles fir haut. Bis geschwënn fir nei Abenteuer mat Chromes Dev Tools!