Salesforce LWC学习(十) 前端处理之 list 处理

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

list是咱们常常要处理的内容,lwc前端针对list主要有几个函数处理,不一样函数针对不一样场景有不一样的功能。下面就根据几个经常使用的处理list的方法进行简单的介绍。前端

一. forEachapi

咱们针对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来进行了解。ide

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 & findIndexui

find和findIndex在lwc中针对list处理会常常用到,用于列表针对某一个条件去查找匹配的数据,匹配上则返回第一条匹配的数据而后终止遍历,若是没有匹配值则返回undefined, findIndex用于列表针对某一个条件去查找匹配的数据,匹配上返回第一条匹配的数据的下标而后终止遍历,下标从0开始,若是没有匹配则返回-1.咱们能够根据find / findIndex来作那种选择列表中选择指定一条之后显示那条的数据信息或者获取那条数据详细信息,根据ID做为条件的遍历。demo找的是官方的一个功能,代码以下:this

 ContactController.cls:简单的获取list的列表数据spa

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的经常使用的前端的使用方法,除了上述的方法之外还有其余的不少方法没有列出,小伙伴们自行查看。篇中有错误的地方欢迎指出,有不懂的欢迎留言。

相关文章
相关标签/搜索