Salesforce LWC學習(十七) 前端知識之 onclick & onblur & onmousedown


Salesforce LWC學習(八) Look Up組件實現篇中,我們實現了公用的lookup組件,使用的過程中,會發現當我們輸入內容以后,搜索出來的列表便無法被清空。

 針對此種情況我們打算優化一下代碼,針對前端的輸入框,增加onblur函數,當鼠標移除情況下,設置searchTerm為空字符串並且不讓下方的options展示,當鼠標移入或者輸入內容情況下在展示下方的options.

customLookUpForLwc.html:輸入框添加onblur,下方options使用變量控制顯隱

<template>
    <div>
        <div class="slds-form-element">
            <div class="slds-form-element__control">
                <div class="slds-combobox_container">
                    <div id="box" class={boxClass} aria-expanded="true" aria-haspopup="listbox" role="combobox">
                        {searchLabel}
                        <div class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" role="none">
                            <template if:true={isValue}>
                                <div id="lookup-pill" class="slds-pill-container">
                                    <lightning-pill class="pillSize" label={valueObj} name={valueObj} onremove={handleRemovePill}>
                                        <lightning-icon icon-name={iconName} alternative-text="acc" ></lightning-icon>
                                    </lightning-pill>
                                </div>
                            </template>
                            <template if:false={isValue}>
                                <div class="slds-p-top_none">
                                    <lightning-input class={inputClass} type="search" id="input" value={searchTerm}
                                        onclick={handleClick}  onchange={onChange}
                                        onblur={handleBlurEvent}
                                        variant="label-hidden" autocomplete="off" placeholder="Search..." label='account search'>
                                    </lightning-input>
                                </div>
                            </template>
                        </div>
                        <template if:true={isEnableShowOptions}>
                            <div id="listbox-id-1" class="slds-dropdown slds-dropdown_length-with-icon-7 slds-dropdown_fluid" role="listbox">
                                <ul class="slds-listbox slds-listbox_vertical" role="presentation">
                                    <template for:each={options} for:item="item">
                                        <li key={item.Id} onclick={onSelect} data-id={item.Id} role="presentation">
                                            <span class="slds-lookup__item-action slds-lookup__item-action--label" role="option">
                                                <lightning-icon class="slds-icon slds-icon--small slds-icon-text-default" icon-name={iconName} alternative-text={objName} size="small"></lightning-icon>
                                                <span class="slds-truncate">{item.Name}</span>
                                            </span>
                                        </li>
                                    </template>
                                </ul>
                            </div>
                        </template>
                        
                    </div>
                </div>
            </div>
        </div>
    </div>

</template>

customLookUpForLwc.js:搜索結果處增加處理項,同時增加是否顯隱標簽的判斷邏輯

/* eslint-disable no-console */
/* eslint-disable @lwc/lwc/no-async-operation */

import lookUp from '@salesforce/apex/CustomLookUpForLwcController.lookUp';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import { getRecord } from 'lightning/uiRecordApi';
import { api, LightningElement, track, wire } from 'lwc';

export default class CustomLookUpForLwc extends LightningElement {
    //store object record id
    @api valueId;
    //record API name
    @api objName;
    //record icon name,see Lightning Design System to choose
    @api iconName;

    @api filter = '';
    //unique key used to mark the unique component. several component use this component need to mapping
    @api uniqueKey;
    //used to set the field to fetch.eg: ['Account.Name'] means we need to search account name field as filter
    @api fields;

    //search label show in lookup component
    @api searchLabel;

    @track searchTerm = '';
    //record name value
    @track valueObj;
    //record href
    @track href;
    //fetch result
    @track options;
    //fetch result backup
    @track optionsBackup;
    //is available value to show in lightning-pill
    @track isValue = false;
    //indicator if enable show options
    @track isEnableShowOptions = true;

    //css
    @track boxClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus';
    @track inputClass = '';

    @wire(lookUp, {searchTerm : '$searchTerm', myObject : '$objName', filter : '$filter'})
    wiredRecords({ error, data }) {
        if (data) {
            this.record = data;
            this.error = undefined;
            if(this.searchTerm && this.isEnableShowOptions) {
                this.options = this.record;
            } else if(this.isEnableShowOptions) {
                if(!this.optionsBackup) {
                    this.optionsBackup = this.record;
                }
                this.options = this.optionsBackup;
            }
        } else if (error) {
            this.error = error;
            this.record = undefined;
        }
    }

    //To get preselected or selected record
    @wire(getRecord, { recordId: '$valueId', fields: '$fields' })
    wiredOptions({ error, data }) {
        if (data) {
            this.record = data;
            this.error = undefined;
            this.valueObj = this.record.fields.Name.value;
            this.href = '/'+this.record.id;
            this.isValue = true;
        } else if (error) {
            this.error = error;
            this.record = undefined;
        }
    }

    handleClick() {
        
        this.searchTerm = '';
        this.isEnableShowOptions = true;
        this.inputClass = 'slds-has-focus';
        this.boxClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus slds-is-open';
    }

    onSelect(event) {
        console.log("In onSelect");
        let ele = event.currentTarget;
        let selectedId = ele.dataset.id;
        //As a best practise sending selected value to parent and inreturn parent sends the value to @api valueId
        let key = this.uniqueKey;
        const valueSelectedEvent = new CustomEvent('valueselect', {
            detail: { selectedId, key },
        });
        this.dispatchEvent(valueSelectedEvent);
        this.boxClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus';
    }

    onChange(event) {
        this.searchTerm = event.target.value;
        this.isEnableShowOptions = true;
    }

    handleBlurEvent() {
        this.isEnableShowOptions = false;
        this.searchTerm = '';
    }

    handleRemovePill() {
        this.isValue = false;
        let selectedId = '';
        let key = this.uniqueKey;
        const valueSelectedEvent = new CustomEvent('valueselect', {
            detail: { selectedId, key },
        });
        this.dispatchEvent(valueSelectedEvent);
    }

}

我們修改以后運行結果為:當我們輸入內容onblur失去焦點時,確實實現了下方內容隱藏,但是當我們輸入內容有結果選中下方item時,item也並沒有選中而是同樣出現了下方內容隱藏的效果。這個是什么原因呢?

這個時候需要考慮的一點就是標准事件的執行順序問題,標准事件中,我們常用的有 onclick / onblur,大家都知道onclick 是按鈕按壓以后執行,onblur是元素失去焦點以后執行。相當於onclick 為 onmousedown -> onmouseup這兩個操作以后作為onclick,onblur在onmousedown以后,但是在onmouseup以前,也就是說Onblur在onclick操作以前,所以上述的demo中,下面的ul li的onclick事件無法調用到只能調用到input的onblur的事件,針對這種情況我們最終只需要將li的事件從onclick 修改成onmousedown即可完美的解決上述的問題。

 總結:篇中主要是通過優化共通方法來引出 onclick / onblur 的執行順序問題以及提出如何解決此種問題的方案,知識點很簡單,純粹前端知識,篇中有錯誤地方歡迎指出,有不懂歡迎留言。


免責聲明!

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



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