Salesforce LWC學習(十) 前端處理之 list 處理


本篇參看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

list是我們經常要處理的內容,lwc前端針對list主要有幾個函數處理,不同函數針對不同場景有不同的功能。下面就根據幾個常用的處理list的方法進行簡單的介紹。

一. forEach

我們針對list處理經常需要迭代去處理,通常可能用到for(var index = 0;index < sampleList.length; index++)這種方式,其實我們可以直接通過forEach函數去搞定,功能以及操作和上述方式相同。有幾個參數可供選擇。

/*
(method) Array<number>.forEach(callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@param callbackfn — A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
@param thisArg — An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/

下面通過一個demo來進行了解。

forEachSample.html:展示幾個輸入框,點擊cancel以后會將所有的字段輸入內容清空。

<template>
    <lightning-record-edit-form 
        record-id={recordId}
        object-api-name="Contact">
            <lightning-messages></lightning-messages>
            <lightning-input-field field-name="FirstName"></lightning-input-field>
            <lightning-input-field field-name="LastName"></lightning-input-field>
            <lightning-input-field field-name="Email"></lightning-input-field> 
            <lightning-input-field field-name="Phone"></lightning-input-field> 
            <div class="slds-align_absolute-center slds-p-around_medium">
                <lightning-button class="slds-m-around_xx-small" label="Cancel" onclick={handleReset}></lightning-button>
                <lightning-button class="slds-m-around_xx-small" label="Create Contact" type="submit" variant="brand" ></lightning-button>
            </div>
    </lightning-record-edit-form>
</template>

forEachSample.js:handleReset方法首先先獲取到所有的lightning-inut-field然后使用forEach,這里只用了field,不需要用index,然后 =>方式 {}括起來去進行處理,reset是lightning-input-field的封裝的方法,感興趣的可以自行查看,lightning-input & lightning-input-field有很多好用的方法,后期有機會可以單獨抽出來一篇博客講解。

import { LightningElement,api } from 'lwc';

export default class ForEachSample extends LightningElement {
    @api recordId;
    handleReset(event) {
        const inputFields = this.template.querySelectorAll(
            'lightning-input-field'
        );
        if (inputFields) {
            inputFields.forEach(field => {
                field.reset();
            });
        }
     }
}

二. find & findIndex

find和findIndex在lwc中針對list處理會經常用到,用於列表針對某一個條件去查找匹配的數據,匹配上則返回第一條匹配的數據然后終止遍歷,如果沒有匹配值則返回undefined, findIndex用於列表針對某一個條件去查找匹配的數據,匹配上返回第一條匹配的數據的下標然后終止遍歷,下標從0開始,如果沒有匹配則返回-1.我們可以根據find / findIndex來做那種選擇列表中選擇指定一條以后顯示那條的數據信息或者獲取那條數據詳細信息,根據ID作為條件的遍歷。demo找的是官方的一個功能,代碼如下:

 ContactController.cls:簡單的獲取list的列表數據

public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContactList() {
        return [SELECT Id, Name, Title, Phone, Email FROM Contact LIMIT 10];
    }
}

eventWithData.html:上面是一個list,點擊以后觸發事件獲取到指定的那條數據然后展示在另一個區域

<template>
    <lightning-card title="EventWithData" icon-name="standard:logging">
        <template if:true={contacts.data}>
            <lightning-layout class="slds-m-around_medium">
                <lightning-layout-item>
                    <template for:each={contacts.data} for:item="contact">
                        <c-contact-list-item
                            key={contact.Id}
                            contact={contact}
                            onselect={handleSelect}
                        ></c-contact-list-item>
                    </template>
                </lightning-layout-item>
                <lightning-layout-item class="slds-m-left_medium">
                    <template if:true={selectedContact}>
                        
                        <p>{selectedContact.Name}</p>
                        <p>{selectedContact.Title}</p>
                        <p>
                            <lightning-formatted-phone
                                value={selectedContact.Phone}
                            ></lightning-formatted-phone>
                        </p>
                        <p>
                            <lightning-formatted-email
                                value={selectedContact.Email}
                            ></lightning-formatted-email>
                        </p>
                    </template>
                </lightning-layout-item>
            </lightning-layout>
        </template>

    </lightning-card>
</template>

eventWithData.js: 在handleSelect中,使用find根據ID去進行匹配,匹配后便會獲取到list中的指定的那條數據記錄。下面的console中也弄了一個findIndex的寫法。

/* eslint-disable no-console */
import { LightningElement, wire, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class EventWithData extends LightningElement {
    @track selectedContact;

    @wire(getContactList) contacts;

    handleSelect(event) {
        const contactId = event.detail;
        /**
         * find方法定義如下: find(predicate: (this: void, value: number, index: number, obj: number[]) => value is number, thisArg?: any)
         * array.find方法用於通過某個指定的條件去獲取滿足條件的第一個的數據,找到滿足條件的以后,后面的便不會在執行,如果遍歷沒有找到符合的則返回undefined.
         * 此函數不影響原有的array
         */
        this.selectedContact = this.contacts.data.find(
            contact => contact.Id === contactId
        );

        let datalist = [10,1,13,14];
        let result1 = datalist.findIndex(
            data => data > 20
        );
        console.log(result1);
        
    }
}

結果展示:

 三.  some & every

我們有時候會有需求為判斷當前的列表的內容是否滿足某些條件,有一個滿足內容則返回true,都不滿足返回false;或者是全部滿足返回true,有一個不滿足就返回false。這個時候就要用到some & every了。 some用於列表的內容只要有一個item滿足了條件則返回true,every為所有的都滿足才返回true,這兩個返回類型為布爾類型,不影響原有的list的值。在for循環中使用和在函數中使用寫法可能多少有點區別,下面給一個demo用來展示寫法。需求為我們將account表中的test__c(multi picklist)展示成列表樣式來判斷某個item是否選中,代碼如下:

someEverySample.html:列表展示multi picklist的樣式

<template>
    <table class="slds-table slds-table_cell-buffer slds-table_bordered">
        <thead>
            <tr class="slds-line-height_reset">
                <td>組件名稱</td>
                <template if:true={resultList}>
                    <template for:each={resultList} for:item="result">
                        <th class="" scope="col" key={result.label}>
                            <div class="slds-truncate">{result.label}</div>
                        </th>
                    </template>
                </template>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>是否選中</td>
                <template if:true={resultList}>
                    <template for:each={resultList} for:item="result">
                        <td key={result.label}>
                            {result.isSelected}
                        </td>
                        
                    </template>
                </template>
            </tr>
                        
        </tbody>
    </table>
</template>

someEverySample.js: result list中有針對some / every的demo以及寫法,在函數內寫法和在for循環中寫法多少有點區別,因為for循環里面寫有一些限制。

/* eslint-disable no-console */
import { LightningElement,api,wire } from 'lwc';
import { getRecord,getFieldValue } from 'lightning/uiRecordApi';
import ACCOUNT_TEST_FIELD from '@salesforce/schema/Account.test__c';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import {getPicklistValues} from 'lightning/uiObjectInfoApi';

export default class SomeEverySample extends LightningElement {

    @api recordId;

    @wire(getRecord,{recordId:'$recordId',fields:ACCOUNT_TEST_FIELD})
    wiredAccount;

    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    accountInfo;

    @wire(getPicklistValues,{ recordTypeId: '$accountInfo.data.defaultRecordTypeId', fieldApiName: ACCOUNT_TEST_FIELD })
    testList;

    get resultList() {
        if(this.wiredAccount && this.wiredAccount.data && this.testList && this.testList.data && this.testList.data.values) {
            let testFieldValueStr = getFieldValue(this.wiredAccount.data,ACCOUNT_TEST_FIELD);
            let selectedTestValues = testFieldValueStr != null ? testFieldValueStr.split(';') : [];
            let testValues = this.testList.data.values;
            let results = [];
            let res = results.some((item,index) => item > 10 && index > 0);
            let resEvery = results.every((item,index) => item > 10 && index > 0);
            console.log(res);
            console.log(resEvery);
            for(let index in testValues) {
                
                if(selectedTestValues.some(function(item,itemIndex) {
                    console.log(itemIndex);
                    return item === testValues[index].value;
                    
                }, this)) {
                    results.push({'label':testValues[index].label,'isSelected':true});
                } else {
                    results.push({'label':testValues[index].label,'isSelected':false});
                }

            }
            return results;
        }
        return [];
    }



    
}

效果展示:123/1234等值為我們Test__c表里面的picklist values,true/false為我們在這條數據中是否選擇了相關的item。

 四. reduce

reduce用來接收一個函數作為累加器(accumulator),數組中的每個值(從左到右)開始合並,最終為一個值.所以我們使用reduce對列表處理最終會返回一個值,要么是布爾,要么是number等。reduce常用場景也可以查看篇中最上面的鏈接去詳細查看。

/*
(method) Array<any>.reduce(callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any (+2 overloads)
        Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
        @param callbackfn — A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
        @param initialValue — If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
 */

我們對reduce有一個了解以后弄一個常用的demo來更好的消化。

reduceSample.html:展示多個輸入框,點擊button去觸發一個事件處理

<template>
    <lightning-card title="LdsUpdateRecord" icon-name="standard:record">
        <div class="slds-m-around_medium">
            <template if:true={contact.data}>
                <lightning-input label="Id" disabled value={contact.data.Id}></lightning-input>
                <lightning-input label="First Name" value={contact.data.FirstName} data-field="FirstName" onchange={handleChange} class="slds-m-bottom_x-small"></lightning-input>
                <lightning-input label="Last Name" value={contact.data.LastName} data-field="LastName" onchange={handleChange} class="slds-m-bottom_x-small" required></lightning-input>
                <lightning-button label="Update Contact" variant="brand" onclick={updateContact} disabled={disabled}></lightning-button>
            </template>
            <template if:true={contact.error}>
                <!-- handle Apex error -->
            </template>
        </div>
    </lightning-card>
</template>

reduceSample.js:demo中是對lightning-input進行遍歷,如果有沒有滿足check的,則報錯,然后執行報錯的提示信息,只有所有的都不報錯了以后才執行validation 通過的邏輯。reportValidity以及checkValidity是lightning針對Input常用的很好的自帶的方法,后期可能對Lightning input進行單獨的博客講解,感興趣的可以自行查看這兩個方法。我們通過reduce方法最后只返回一個true/false的值。

import { LightningElement, track, wire } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

import getSingleContact from '@salesforce/apex/ContactController.getSingleContact';

export default class ReduceSample extends LightningElement {
    @track disabled = false;
    @track error;

    @wire(getSingleContact)
    contact;

    handleChange(event) {
         // Display field-level errors and disable button if a name field is empty.
        if (!event.target.value) {
            event.target.reportValidity();
            this.disabled = true;
        }
        else {
            this.disabled = false;
        }
    }

    updateContact() {
        let allInputList = Array.from(this.template.querySelectorAll('lightning-input'));
        /*
        方法聲明如下:
        (method) Array<any>.reduce(callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any (+2 overloads)
        Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
        @param callbackfn — A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
        @param initialValue — If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
         */
        const allValid = allInputList.reduce((validSoFar, inputFields) => {
                inputFields.reportValidity();
                return validSoFar && inputFields.checkValidity();
            }, true);

        if (allValid) {
            //TODO success related operation
        } else {
            // The form is not valid
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Something is wrong',
                    message: 'Check your input and try again.',
                    variant: 'error'
                })
             );
        }
    }
}

五. map & filter

map用來返回一個新數組,不影響原有的操作的list。這個新數組可以為這個list的每條數據針對某個條件處理以后的值,比如我們想要將一個list的里面的每一個值都乘以5然后返回一個新的數組,這個時候我們就可以使用map,只需要條件為對item * 5的操作即可。

filter用來使用指定的函數測試所有元素,並返回一個包含所有通過測試的元素的新數組,此方法不影響原有的list。

這兩個基礎的意思了解以后,來個demo更好的了解一下。

mapSample.html

<template>
    <lightning-input label="Category 1" type="checkbox" onchange={handleCheckboxChange}></lightning-input>
    <lightning-input label="Category 2" type="checkbox" onchange={handleCheckboxChange}></lightning-input>
</template>

mapSample.js: 點擊checkbox以后獲取選中的選項的label名稱,通過filter獲取到指定的想要數據,通過map獲取到list的變形,及我們根據規則獲取到的想要的數據。

/* eslint-disable no-console */
import { LightningElement } from 'lwc';

export default class MapSample extends LightningElement {
    handleCheckboxChange() {
        const lightningInputList = Array.from(
            this.template.querySelectorAll('lightning-input'));
        console.log(JSON.stringify(lightningInputList));
        const filters =  lightningInputList.filter(element => element.checked)
            .map(element => element.label);
        
        console.log(JSON.stringify(filters));
    }
}

總結:篇中都是lwc中針對list的常用的前端的使用方法,除了上述的方法以外還有其他的很多方法沒有列出,小伙伴們自行查看。篇中有錯誤的地方歡迎指出,有不懂的歡迎留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM