はじめに
以前書いたときはJavaScriptのclassの仕組みをあんまり理解できていなかったため、とんちんかんなアプローチをしていました。
LWCのJS内でクラス(っぽいもの)を用意したい
今回ある程度学が身についたので「あれ、できるんじゃね?」と試したところあっさりできたので、ご報告も兼ねて完全版を残しておこうと思います。
やりたかったこと
画面に表示するデータを、同じデータ構造で複数種類保つ必要があったため、クラスに定義して保存するようにしたかった。
できたこと
コード
画面用のclassの外で利用したいclassを定義する。
import { LightningElement } from 'lwc';
export default class TestComponent extends LightningElement {
personList = [];
connectedCallback() {
this.personList.push(new person('テスト A'));
this.personList.push(new person('テスト B'));
this.personList.push(new person('テスト C'));
}
}
class person {
/**
* 名前
*/
name;
/**
* 年齢
*/
age;
/**
* 身長
*/
height;
/**
* 体重
*/
weight;
constructor(name) {
this.name = name;
this.age = this.getRandomInt(100);
this.height = 120 + this.getRandomInt(80);
this.weight = 30 + this.getRandomInt(100);
}
/**
* 自己紹介文
*/
get selfIntroduction() {
return `私の名前は${this.name}。\r\n`
+ `年齢は${this.age}歳だよ。`;
}
/**
* 乱数を生成する
*/
getRandomInt(max) {
return Math.floor(Math.random() * max);
}
}
<template>
<lightning-card icon-name="custom:custom27" title="テスト">
<div class="slds-var-p-around_medium">
<template for:each={personList} for:item="person">
<div key={person.name} class="slds-box slds-var-p-around_small slds-var-m-bottom_small">
<p>氏名:{person.name}</p>
<p>年齢:{person.age}歳</p>
<p>身長:{person.height}cm</p>
<p>体重:{person.weight}kg</p>
<div class="slds-box slds-theme_shade">{person.selfIntroduction}</div>
</div>
</template>
</div>
</lightning-card>
</template>
良い点
見るべきところを纏められる
他の言語でclassを作ったときと概ね同じ。
javadocがきちんと効く
以前書いたものだと、コードの記法次第でjavadocが効かないことがあったが、今回のものは完璧!
javadocがばっちり効きます。
要素ごとのgetterが定義できる → ループ内でそれぞれ動作させられる!
先程のコードサンプルにあったget selfIntroduction()
をループ内で呼び出してる部分ですが、実は(個人的に)ちょっと画期的なことで・・。
LWCのループ内部で、要素ごとに関数を適用するのって一筋縄ではできないんですよね。
そんな悩みもclassを作ることで解決します。やったね。
apexから渡された値を、かなり手軽にclassに変換できるっぽい
const personObject = {
name: 'テストA'
,age: 19
,height: 170
,weight: 60
,unnecessaryProperty: 'abc'
};
const personClass = Object.assign(new person(), personObject));
これだけでclassに変換できました。
余計なプロパティunnecessaryProperty
はエラーなどが出たりはせず、保持したままとなっていました。
悪い点
未定義プロパティに値を設定できる
誤字や作ったつもりで、未定義のプロパティを参照したとき、なんの問題もなく処理が進んでしまいました。
classはuse strict
が適用されているはずなんだけど・・なんでだ・・?
厳格モード - JavaScript | MDN
誤字に気をつけるしかない!というのがちょっと気持ち悪いところではあります。
privateが使えない
これはLWC側の規約ですが・・。
privateメソッドやプロパティが使えないようです。
実際に定義してデプロイすると、下記のエラーが発生します。
LWC1535: Unexpected plugin compilation error: Plugin - lwc, Hook - transform, Cause - SyntaxError: LWC1007: /home/sfdc/tools/lwc/248.10.2-5.0.8/testComponent.js: Class private methods are not enabled. Please add '@babel/plugin-transform-private-methods' to your configuration.
まあ使いたいシーンがあるかと言われると微妙なので、そこまで支障ないとは思いますが・・。
ちょっと残念。
以前と比べて良くなったところ
そもそも、無理やり作ったclassっぽいものではなく、きちんと仕様に則ってclassを作っているというだけでかなりこう、気持ちが違います。
あとは、関数を用意したい場合に別途getterの定義をしなくて良くなったのが大きいですね。
使い勝手の向上って感じだ。