上一篇我们介绍了针对LWC中常用的LDS的适配的wire service以及@salesforce模块提供的相关的service,其实LWC中还提供其他的好用的service,比如针对导航相关的lightning/navigation以及展示toast提示信息相关的lightning/platformShowToastEvent。此篇主要针对这两个service进行简单的介绍。
一. lightning/navigation
我们有好多场景会用到跳转操作,比如创建记录以后跳转到此记录详情页,点击连接跳转到下载页面或者直接下载文件,跳转到某个列表等等。LWC中封装了lightning/navigation service去实现相关的跳转操作。当然,此service除了封装了跳转相关的功能,还封装了获取当前PageReference的功能。详情如下所示。
1. CurrentPageReference:此方法用于获取当前页面的引用,使用以下的声明便可以获取到当前的页面的引用了。如果我们想编辑其键值对的parameter,我们需要更新当前page reference的Page state。至于如何更新,下面会有介绍。
1 import { CurrentPageReference } from 'lightning/navigation';
2 @wire(CurrentPageReference)
3 pageRef;
返回的pageRef为PageReference变量。PageReference为js封装的对象,有三个变量。 1) type:当前PageReference的类型。lwc封装了以下的类型:
这些PageReference详情可以参看:https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.reference_page_reference_type 我们常用的有Lightning Component / Object Page / Record Page / Record Relationship Page / Web Page。 2)attribute:声明不同类型的PageReference创建PageReference需要配置不同的attribute,细节的attribute的配置同看上面链接。
3)state:用来存储键值对类型的parameter。我们在URL中可能传递参数,使用CurrentPageReference获取到的PageReference中,state存储的便是其参数部分。
下面来一个demo更好的了解用法以及返回内容。
getCurrentPageReferenceDemo.js:装载CurrentPagReference,将引用赋值给pageRef;
1 import { LightningElement, wire } from 'lwc';
2 import {CurrentPageReference} from 'lightning/navigation';
3 export default class GetCurrentPageReferenceDemo extends LightningElement {
4 @wire(CurrentPageReference)
5 pageRef;
6
7 get currentPageInfo() {
8 if(this.pageRef !== undefined) {
9 return JSON.stringify(this.pageRef);
10 }
11 return '';
12 }
13 }
getCurrentPageReferenceDemo.html:
1 <template>
2 {currentPageInfo}
3 </template>
显示结果:我们将此component放在contacts的详情页里面,并且针对详情页的URL手动设置了parameter,返回的结果如下图所示。
2. NavigationMixin:使用此adapter实现跳转功能。此adapter封装了两个API实现跳转。
[NavigationMixin.Navigate](pageReference, [replace])
- 在应用中一个component调用此API跳转到另外一个页面;[NavigationMixin.GenerateUrl](pageReference)
- component调用此API获取需要跳转的URL的Promise。这两个API,先调用GenerateUrl获取到Promise,然后使用Navigate的API即可实现跳转。我们使用此service前需要先在头引入,和其他的区别为我们还需要在javascript的class中去继承NavigationMixin。
import { NavigationMixin } from 'lightning/navigation';
export default class MyCustomElement extends NavigationMixin(LightningElement) {}
上面的两个API我们也可以看见pageReference参数,此参数和上面的CurrentPageReference返回值类型相同,均为javascript中封装的CurrentPageReference对象。我们可以使用plain object去拼接此对象的变量。说的比较绕,下面通过一个官方的demo便可以更好的了解。
navigationLineExample.js:在connectedCallback生命周期处声明了PageReference的Promise,用于handleClick时去触发。
1 import { LightningElement, track } from 'lwc';
2 import { NavigationMixin } from 'lightning/navigation';
3
4 export default class NavigationLinkExample extends NavigationMixin(LightningElement) {
5 @track url;
6
7 connectedCallback() {
8 // Store the PageReference in a variable to use in handleClick.
9 // This is a plain Javascript object that conforms to the
10 // PageReference type by including "type" and "attributes" properties.
11 // The "state" property is optional.
12 this.accountHomePageRef = {
13 type: "standard__objectPage",
14 attributes: {
15 "objectApiName": "Account",
16 "actionName": "home"
17 }
18 };
19 this[NavigationMixin.GenerateUrl](this.accountHomePageRef)
20 .then(url => this.url = url);
21 }
22
23 handleClick(evt) {
24 // Stop the event's default behavior.
25 // Stop the event from bubbling up in the DOM.
26 evt.preventDefault();
27 evt.stopPropagation();
28 // Navigate to the Account Home page.
29 this[NavigationMixin.Navigate](this.accountHomePageRef);
30 }
31 }
navigationLineExample.html:点击按钮触发handleClick方法
1 <template>
2 <div>
3 <a href={url} onclick={handleClick}>Account Home</a>
4 </div>
5 </template>
将demo配置在account的record page中,通过上面的demo我们便可以实现跳转到Account的home页面的功能,也可以看到声明 PageReference中的type以及attributes的神奇之处。原理了解以后只需要通过改变PageReference Type以及其对应的attribute我们便可以实现更多的功能,感兴趣的小伙伴可以自行尝试。
我们在跳转或者自刷新时,有时需要传递参数,在LWC中上面也提到过使用state变量传递参数,我们在更新此变量前先了解一下相关的限制和要求。
通过上述1,2,3,4点我们可以看出来,1属于限制,2,3,4属于规范。我们针对跳转到其他页面直接设置state即可,如果针对跳转到当前页面,只是参数变化,便需要考虑上面的第一点。通过官方提供的demo可以更好的了解针对parameter的处理。
pageStateChangeExample.js:demo中考虑的时跳转到当前页面,只是参数的变化的处理。此时pagereference已经冻结,只能通过Object.assign方法去处理。
1 import { LightningElement, wire, track } from 'lwc';
2 import { CurrentPageReference, NavigationMixin } from 'lightning/navigation';
3
4 export default class PageStateChangeExample extends NavigationMixin(LightningElement) {
5
6 // Injects the page reference that describes the current page
7 @wire(CurrentPageReference)
8 setCurrentPageReference(currentPageReference) {
9 this.currentPageReference = currentPageReference;
10
11 if (this.connected) {
12 // We need both the currentPageReference, and to be connected before
13 // we can use NavigationMixin
14 this.generateUrls();
15 } else {
16 // NavigationMixin doesn't work before connectedCallback, so if we have
17 // the currentPageReference, but haven't connected yet, queue it up
18 this.generateUrlOnConnected = true;
19 }
20 }
21 @track
22 showPanelUrl;
23
24 @track
25 noPanelUrl;
26
27 // Determines the display for the component's panel
28 get showPanel() {
29 // Derive this property's value from the current page state
30 return this.currentPageReference &&
31 this.currentPageReference.state.c__showPanel == 'true';
32 }
33
34 generateUrls() {
35 this[NavigationMixin.GenerateUrl](this.showPanelPageReference)
36 .then(url => this.showPanelUrl = url);
37 this[NavigationMixin.GenerateUrl](this.noPanelPageReference)
38 .then(url => this.noPanelUrl = url);
39 }
40
41 // Returns a page reference that matches the current page
42 // but sets the "c__showPanel" page state property to "true"
43 get showPanelPageReference() {
44 return this.getUpdatedPageReference({
45 c__showPanel: 'true' // Value must be a string
46 });
47 }
48
49 // Returns a page reference that matches the current page
50 // but removes the "c__showPanel" page state property
51 get noPanelPageReference() {
52 return this.getUpdatedPageReference({
53 // Removes this property from the state
54 c__showPanel: undefined
55 });
56 }
57
58 // Utility function that returns a copy of the current page reference
59 // after applying the stateChanges to the state on the new copy
60 getUpdatedPageReference(stateChanges) {
61 // The currentPageReference property is read-only.
62 // To navigate to the same page with a modified state,
63 // copy the currentPageReference and modify the copy.
64 return Object.assign({}, this.currentPageReference, {
65 // Copy the existing page state to preserve other parameters
66 // If any property on stateChanges is present but has an undefined
67 // value, that property in the page state is removed.
68 state: Object.assign({}, this.currentPageReference.state, stateChanges)
69 });
70 }
71
72 connectedCallback() {
73 this.connected = true;
74
75 // If the CurrentPageReference returned before this component was connected,
76 // we can use NavigationMixin to generate the URLs
77 if (this.generateUrlOnConnected) {
78 this.generateUrls();
79 }
80 }
81
82 handleShowPanelClick(evt) {
83 evt.preventDefault();
84 evt.stopPropagation();
85 // This example passes true to the 'replace' argument on the navigate API
86 // to change the page state without pushing a new history entry onto the
87 // browser history stack. This prevents the user from having to press back
88 // twice to return to the previous page.
89 this[NavigationMixin.Navigate](this.showPanelPageReference, true);
90 }
91
92 handleNoPanelClick(evt) {
93 evt.preventDefault();
94 evt.stopPropagation();
95 this[NavigationMixin.Navigate](this.noPanelPageReference, true);
96 }
97 }
pageStateChangeExample.html:针对showPanel以及noPanelUrl的处理
<template>
<div>
<a href={showPanelUrl} onclick={handleShowPanelClick}>Show Panel</a>
</div>
<div if:true={showPanel}>
<h1>This is the panel</h1>
<a href={noPanelUrl} onclick={handleNoPanelClick}>Hide Panel</a>
</div>
</template>
二. Lightning/platformShowToastEvent
当我们进行DML操作或者某种场景或者validation需要展示一些信息,当然我们可以通过ligtning-messages展示信息在页面上,另外一种方式可以使用toast方式仅显示几秒的提示信息随后消失的样式。LWC提供了lightning/platformShowToastEvent实现此功能。模块中封装了ShowToastEvent事件,实例化以后dispatchEvent即可使用。
ShowToastEvent事件有以下的几个参数
我们在recordEditFormSample展示此用法。
1 <template>
2 <lightning-record-edit-form
3 record-id={recordId}
4 object-api-name={objectApiName}
5 onsubmit={handleSubmit}
6 onload={handleLoad}
7 onsuccess={handleSuccess}
8 onerror={handleError}
9 >
10 <lightning-messages></lightning-messages>
11 <lightning-input-field field-name="Name"></lightning-input-field>
12 <lightning-input-field field-name="Industry"></lightning-input-field>
13 <lightning-input-field field-name="AnnualRevenue"></lightning-input-field>
14 <div class="slds-m-top_medium">
15 <lightning-button class="slds-m-top_small" label="Cancel" onclick={handleReset}></lightning-button>
16 <lightning-button class="slds-m-top_small" type="submit" label="Save Record"></lightning-button>
17 </div>
18 </lightning-record-edit-form>
19 </template>
recordEditFormSample.js
1 /* eslint-disable no-console */
2 import { LightningElement, api } from 'lwc';
3 import { ShowToastEvent } from 'lightning/platformShowToastEvent';
4 export default class RecordEditFormSample extends LightningElement {
5
6 @api recordId;
7 @api objectApiName;
8
9 handleSubmit(event) {
10 event.preventDefault(); // stop the form from submitting
11 const fields = event.detail.fields;
12 if(fields.Industry === null || fields.Industry === '') {
13 const evt = new ShowToastEvent({
14 title: "Account Operated Failed",
15 message: "Account Industry cannot be blank",
16 variant: "error",
17 mode:"pester"
18 });
19 this.dispatchEvent(evt);
20 return;
21 }
22 this.template.querySelector('lightning-record-edit-form').submit(fields);
23 }
24
25 handleLoad(event) {
26 console.log('execute load');
27 }
28
29 handleSuccess(event) {
30 const evt = new ShowToastEvent({
31 title: "Account Operated Success",
32 message: "Record is :" + event.detail.id,
33 variant: "success"
34 });
35 this.dispatchEvent(evt);
36 }
37
38 handleError(event) {
39 const evt = new ShowToastEvent({
40 title: "Account Operated Failed",
41 message: event.detail.message,
42 variant: "error",
43 mode: "sticky"
44 });
45 this.dispatchEvent(evt);
46 }
47
48 handleReset(event) {
49 const inputFields = this.template.querySelectorAll(
50 'lightning-input-field'
51 );
52 if (inputFields) {
53 inputFields.forEach(field => {
54 field.reset();
55 });
56 }
57 }
58 }
效果展示:
sticky样式,只有点击关闭按钮才能消失toast。
总结:此篇主要说的是Navigation以及Toast相关的知识,其中Navigation可以根据不同的type以及attribute去做不同功能的跳转以及下载等操作,篇中例举的比较少,感兴趣的可以深入学习。篇中有错误地方欢迎指出,有不懂的欢迎留言。