Salesforce Platform Developer I：Lightning Web コンポーネント（LWC）の基本

# Lightning Web コンポーネント(LWC)
## Lightning Web コンポーネントを使用する理由
Lightning Web コンポーネントは、コア Web コンポーネント標準を使用し、Salesforce でサポート対象のブラウザで適切に動作するために必要な機能のみを提供します。Lightning Web コンポーネントは、ブラウザでネイティブに実行されるコード上に構築されるため、軽量で卓越したパフォーマンスを発揮します。記述するコードの大部分は、標準の JavaScript および HTML です。

## シンプルなコンポーネントの作成
JavaScriptファイル：コアビジネスロジックとイベント処理を定義します。
HTMLファイル：コンポーネントの構造を提供します。
CSS ファイル：コンポーネントのデザインとアニメーションを提供します。※CSS必須ではない
## 作成のIDE
**・インストールツール**
　　VSCode
**・お勧めツール**
　　webcomponents.dev（デザイン表示、直観的なツール）

**　PS：webcomponents.devツールリンク**
　　https://webcomponents.dev/create/lwc

## VSCodeでLightning Web コンポーネントを作成
**①Visual Studio Code で、Ctrl+Shift+P (Windows) または Cmd+Shift+P (macOS) を押して、コマンドパレットを開きます。**
**②「SFDX: プロジェクトを作成」選択**
　テンプレート：標準
　プロジェクト名：bikeCard
**③lwc フォルダを右クリックして [SFDX: Create Lightning Web Component (SFDX: Lightning Web コンポーネントを作成)]**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/def2d942-070d-9406-afae-afbf0d34f1b9.png)

　フォルダー：lwc
　コンポーネント名：bikeCard
**④コンポーネントファイルのコンテンツをこのユニットからVisualStudioCodeのファイルにコピーします。**
　bikeCard.html
　BikeCard.js
　bikeCard.js-meta.xml
**⑤BikeCardコンポーネントファイルを組織にデプロイします**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/134a842e-9212-75f2-31e7-d3abe01e5f7b.png)
<font color="red">**※デプロイ失敗、下記のエラーが出た時、一つの原因はプロジェクト作成する時選択のフォルダが長すぎまた別のプロジェクトの中にフォルダ作成した。
「Unable to build Lightning Component source for markup://c:bikeCard: Invalid suffix: json.」**</font>

**⑥Lightningアプリページを作成します。**
　Lightningアプリケーションビルダーに新規「App Page」作成
　Label: Bike Card
　Developer Name: Bike_Card
**⑦bikeCardコンポーネントをページに追加します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/e29a0c56-b5e7-34c9-63aa-5d6288cc157c.png)

**⑧すべてのユーザーのページを有効化する**
## LightningWebコンポーネントでイベントを処理する
tile: 個々の品目を表示します。
list: タイルを配置します。
detail: タイルがクリックされると品目の詳細を表示します (作成した bikeCard に類似)。
selector: すべてのコンポーネントが含まれます。コンテナコンポーネントは必要ありませんが、ここでは、イベント処理をしやすくするためにコンテナを 1 つ使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/522ef384-9a31-307a-24c9-9d99dfda4f7e.png)

### コンポーネントの関係
一部のコンポーネントは、他のコンポーネント内にネストされています。
複雑なコンポーネント（複数の親コンポーネントと子コンポーネントを含むコンポーネント）では、コンポーネントは上下に通信できます。

### スタイル設定
①*.cssの中に、設定したいの項目をCSS設定可
・設定サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/d910d66e-88dc-6de9-86be-cceacfbbb9f0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/3f2f47ad-6040-8762-2738-bd0b80488a5b.png)
②Salesforce Lightning Design System(SLDS)のスタイルの適用。
<font color="red">※設定できるスタイルは下記のリンク参照</font>
https://lightningdesignsystem.com/design-tokens/

・設定サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/e4e813b6-4886-dd69-9d09-709d364a8660.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/fd21dcc2-6b6d-8eaa-8eb6-5bf21a6f2c4b.png)

### 動的データ表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/b49deff3-5334-d1c1-b89e-c22a96afbd17.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/933c81ef-db41-ad41-812e-abe071218942.png)

## キーワード
### 変数声明
@track XXX　コンポーネント内部私有変数、動的、変更すると画面連動
@api XXX　　外部から取得可能、動的、変更すると画面連動
XXX　　　　　コンポーネント内部私有変数、画面初期化する時一回のみ取得、変更しても、画面変わらない
### Apex呼び出し
・@wire　　　初期化する時呼び出し、データ取得のみお勧め、データ操作関連は勧めではない

<font color="red">※パラメータは必ず初期値設定必要、設定しない場合、データ取得できないかもしれません</font>

```js
import getdata from '@salesforce/apex/MydataController.getdata';
export default class GetData  extends LightningElement {
 let recordId='';
 @wire(getdata, { recordId: '$recordId' })
    wiredData({ error, data }) {
      if(data){
         //データ取得後の処理
      }else if(error){
         //エラーメッセージ出力
      }
}
```
または

```js
import getdata from '@salesforce/apex/MydataController.getdata';
export default class GetData  extends LightningElement {
 let recordId='';
 @wire(getdata, { recordId: '$recordId' })
    .then(data => {
         //データ取得後の処理
      })
      .catch(error =>{
         //エラーメッセージ出力
      }
}
```

・Apexクラスリネーム、直接呼び出し

```js
import insertDatafrom '@salesforce/apex/MydataController.insertData';
export default class GetData  extends LightningElement {
  insertData({data: dataRecord})
          .then(result => {
              //成功処理
          })
          .catch(error => {
              //エラー処理
              });
  }
}
```

# ソース
## data
```data.js
export const bikes = [
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Mountain","value":"Mountain"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1arAAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-12T02:57:48.000Z"},"Level__c":{"displayValue":"Racer","value":"Racer"},"MSRP__c":{"displayValue":"$7,800","value":7800},"Material__c":{"displayValue":"Carbon","value":"Carbon"},"Name":{"displayValue":null,"value":"DYNAMO X1"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox1.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-12T02:57:48.000Z"}},"id":"a0256000001F1arAAC","lastModifiedById":null,"lastModifiedDate":"2018-10-12T02:57:48.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-12T02:57:48.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Mountain","value":"Mountain"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1atAAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-10T17:26:47.000Z"},"Level__c":{"displayValue":"Racer","value":"Racer"},"MSRP__c":{"displayValue":"$6,802","value":6802},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"DYNAMO X2"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox2.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-10T17:26:47.000Z"}},"id":"a0256000001F1atAAC","lastModifiedById":null,"lastModifiedDate":"2018-10-10T17:26:47.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-10T17:26:47.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Mountain","value":"Mountain"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1auAAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T04:37:56.000Z"},"Level__c":{"displayValue":"Enthusiast","value":"Enthusiast"},"MSRP__c":{"displayValue":"$5,601","value":5601},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"DYNAMO X3"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox3.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T04:37:56.000Z"}},"id":"a0256000001F1auAAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T04:37:56.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T04:37:56.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Mountain","value":"Mountain"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1avAAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Level__c":{"displayValue":"Enthusiast","value":"Enthusiast"},"MSRP__c":{"displayValue":"$5,500","value":5500},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"DYNAMO X4"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox4.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"}},"id":"a0256000001F1avAAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T03:29:52.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T03:29:52.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Mountain","value":"Mountain"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1azAAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Level__c":{"displayValue":"Enthusiast","value":"Enthusiast"},"MSRP__c":{"displayValue":"$4,600","value":4600},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"FUSE X1"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/fusex1.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"}},"id":"a0256000001F1azAAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T03:29:52.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T03:29:52.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Commuter","value":"Commuter"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1b2AAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T04:41:56.000Z"},"Level__c":{"displayValue":"Beginner","value":"Beginner"},"MSRP__c":{"displayValue":"$3,200","value":3200},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"ELECTRA X1"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax1.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T04:41:56.000Z"}},"id":"a0256000001F1b2AAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T04:41:56.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T04:41:56.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Commuter","value":"Commuter"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1b3AAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Level__c":{"displayValue":"Beginner","value":"Beginner"},"MSRP__c":{"displayValue":"$3,200","value":3200},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"ELECTRA X2"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax2.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"}},"id":"a0256000001F1b3AAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T03:29:52.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T03:29:52.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Commuter","value":"Commuter"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1b6AAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Level__c":{"displayValue":"Beginner","value":"Beginner"},"MSRP__c":{"displayValue":"$2,700","value":2700},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"ELECTRA X3"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax3.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"}},"id":"a0256000001F1b6AAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T03:29:52.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T03:29:52.000Z"},
    {"apiName":"Product__c","childRelationships":{},"fields":{"Category__c":{"displayValue":"Commuter","value":"Commuter"},"CreatedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Description__c":{"displayValue":null,"value":"A durable e-bike with great looks."},"Id":{"displayValue":null,"value":"a0256000001F1b7AAC"},"LastModifiedDate":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"},"Level__c":{"displayValue":"Beginner","value":"Beginner"},"MSRP__c":{"displayValue":"$2,700","value":2700},"Material__c":{"displayValue":"Aluminum","value":"Aluminum"},"Name":{"displayValue":null,"value":"ELECTRA X4"},"Picture_URL__c":{"displayValue":null,"value":"https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg"},"SystemModstamp":{"displayValue":null,"value":"2018-10-09T03:29:52.000Z"}},"id":"a0256000001F1b7AAC","lastModifiedById":null,"lastModifiedDate":"2018-10-09T03:29:52.000Z","recordTypeInfo":null,"systemModstamp":"2018-10-09T03:29:52.000Z"}
];
```
```data.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
```

## detail
```detail.html
<template>
    <template if:true={product}>
        <div class="container">
            <div class="slds-text-heading_small">{product.fields.Name.value}</div>
            <div class="price">{product.fields.MSRP__c.displayValue}</div>
            <div class="description">{product.fields.Description__c.value}</div>
            <img class="product-img" src={product.fields.Picture_URL__c.value}></img>
            <p>
                <lightning-badge label={product.fields.Material__c.value}></lightning-badge>
                <lightning-badge label={product.fields.Level__c.value}></lightning-badge>
            </p>
            <p>
                <lightning-badge label={product.fields.Category__c.value}></lightning-badge>
            </p>
        </div>
    </template>
    <template if:false={product}>
        <div class="slds-text-heading_medium">Select a bike</div>
    </template>
</template>
```
```detail.css
body{
  margin: 0;
}
.price {
  color: green;
  font-weight: bold;
}
```
```detail.js
import { LightningElement, api } from 'lwc';
import { bikes } from 'c/data';

export default class Detail extends LightningElement {

    // Ensure changes are reactive when product is updated
    product;

    // Private var to track @api productId
    _productId = undefined;

    // Use set and get to process the value every time it's
    // requested while switching between products
    set productId(value) {
        this._productId = value;
        this.product = bikes.find(bike => bike.fields.Id.value === value);
    }
    
    // getter for productId
    @api get productId(){
        return this._productId;
    }
}
```
```detail.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
```

## tile
```tile.html
<template>
    <div class="container">
        <a onclick={tileClick}>
            <div class="title">{product.fields.Name.value}</div>
            <img class="product-img" src={product.fields.Picture_URL__c.value}></img>
        </a>
    </div>
</template>
```
```tile.css
.container {
    border: 1px rgb(168, 166, 166) solid;
    border-radius: 5px;
    background-color: white;
    margin:5px;
    padding: 2px;
    max-width: 110px;
    display: flex;
    
}

.title {
    font-weight: strong;
}

.product-img {
    max-width: 100px;
}

a {
    text-decoration: none;
}

a:link {
    color: rgb(159, 159, 159);
}
a:visited {
    color: green;
}
a:hover {
    color: hotpink;
}
a:active {
    color: blue;
}
```
```tile.js
import { LightningElement, api } from 'lwc';

export default class Tile extends LightningElement {
    @api product;

    tileClick() {
        const event = new CustomEvent('tileclick', {
            // detail contains only primitives
            detail: this.product.fields.Id.value
        });
        // Fire the event from c-tile
        this.dispatchEvent(event);
    }
}

```
```tile.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
```

## list
```list.html
<template>
    <div class="container">
        <template for:each={bikes} for:item="bike">
            <c-tile 
                key={bike.fields.Id.value} 
                product={bike} 
                ontileclick={handleTileClick}>
            </c-tile>
        </template>
    </div>
</template>
```
```list.css
.container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
```
```list.js
import { LightningElement } from 'lwc';
import { bikes } from 'c/data';

export default class List extends LightningElement {
    bikes = bikes;

    handleTileClick(evt) {
        // This component wants to emit a productselected event to its parent
        const event = new CustomEvent('productselected', {
            detail: evt.detail
        });
        // Fire the event from c-list
        this.dispatchEvent(event);
    }
}

```
```list.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
```

## selector

```selector.html
<template>
    <div class="wrapper">
    <header class="header">Available Bikes for {name}</header>
    <section class="content">
        <div class="columns">
        <main class="main" >
            <c-list onproductselected={handleProductSelected}></c-list>
        </main>
        <aside class="sidebar-second">
            <c-detail product-id={selectedProductId}></c-detail>
        </aside>
        </div>
    </section>
    </div>
</template>
```

```selector.css
body {
  margin: 0;
} 
.wrapper{
  min-height: 100vh;
  background: #ccc;
  display: flex;
  flex-direction: column;
}
.header, .footer{
  height: 50px;
  background: rgb(255, 255, 255);
  color: rgb(46, 46, 46);
  font-size: x-large;
  padding: 10px;
}
.content {
  display: flex;
  flex: 1;
  background: #999;
  color: #000; 
}
.columns{
  display: flex;
  flex:1;
}
.main{
  flex: 1;
  order: 2;
  background: #eee;
}
.sidebar-first{
  width: 20%;
  background: #ccc;
  order: 1;
}
.sidebar-second{ 
  width: 30%;
  order: 3;
  background: #ddd;
}
```

```selector.js
//wire 導入
import { LightningElement, wire } from 'lwc';
//import { 「wire アダプタの ID」 } from '「wire アダプタ関数が含まれるモジュールの ID」';　レコード取得API導入
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
//取得対象はID設定（項目をインポートして、ワイヤアダプタの設定オブジェクトで使用します。）
import Id from '@salesforce/user/Id';
//同上　取得対象「ユーザ．名前」はNAME_FIELDに設定（項目をインポートして、ワイヤアダプタの設定オブジェクトで使用します。）
import NAME_FIELD from '@salesforce/schema/User.Name';
//定数定義
const fields = [NAME_FIELD];
export default class Selector extends LightningElement {
    selectedProductId;
    handleProductSelected(evt) {
        this.selectedProductId = evt.detail;
    }
    //取得したIdをuserId変数に設定
    userId = Id;
    //変数userIdを条件で、「ユーザ．名前」を取得する
    @wire(getRecord, { recordId: '$userId', fields })
    //取得データ格納
    user;
    get name() {
        //取得データから画面に返却するため、name設定
        return getFieldValue(this.user.data, NAME_FIELD);
    }
}
```

```selector.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

```

# 参考リンク
**wireの説明**

https://developer.salesforce.com/docs/component-library/documentation/ja-jp/lwc/lwc.data_wire_service_about

**webcomponents.dev**

https://liginc.co.jp/web/html-css/html/58267

**SLDS**

https://qiita.com/xuwenzhen/items/e0b2f87e25a2f261fc21