Salesforce LWC學習(三) import & export / api & track

 咱們使用vs code建立lwc 時,文件會默認生成包含 template做爲頭的html文件,包含了 import LightningElement的 js文件以及對應的.js-meta.xml文件。前一個LWC學習的文章中已經說過當瀏覽器渲染的時候,碰見<template>會將其渲染成<namespace-component-name>,好比 helloWorld.html引入在頁面中瀏覽器進行渲染時,此文件的template會被渲染成<c-hello-world>。這裏不知道你們是否有過疑問, import / export 是幹什麼用的,針對變量聲明和html以及js之間的數據綁定如何實現的,這些都將會在下面有簡單的描述。javascript

 一. 變量聲明, api以及trackhtml

咱們想要實現一個簡單的功能,默認顯示 'hello World!',下面存在一個輸入框,當輸入內容之後,'World'便會變成其餘的值而且以大寫顯示,同時輸入框中不容許輸入xx,咱們在下方有一個輸入歷史記錄區域會記錄當前輸入的內容。在Aura框架下你們都知道,只須要設置一個attribute,事件觸發之後component.set()即可以實現實時修改了。在lwc中,html使用{}將屬性包圍起來,{property}後臺聲明property,想要計算這個property的值,咱們只須要調用 get property便可獲取到property的值。須要注意的是當一個component從新渲染的時候,裏面全部的表達式都會從新渲染。OK下面咱們進行實現。前端

testVariable.htmljava

 1 <template>
 2     Hello,{wiredGreeting}!
 3     <br/>
 4     <lightning-input label="Name" value={greeting} onchange={handleChange} onblur={logHistory}></lightning-input>
 5     <template if:true={showDetail}>
 6         <div class="slds-m-vertical_medium">
 7             不容許輸入xx
 8         </div>
 9     </template>
10 
11     <template if:true={showHistory}>
12         <lightning-card title="input history list">
13             <ul class="slds-m-around_medium">
14                 <template for:each={historyList} for:item="h">
15                     <li key={h.Id}>
16                         {h.Name}
17                     </li>
18                 </template>
19             </ul>
20         </lightning-card>
21     </template>
22 </template>

testVariable.jsreact

 1 import { LightningElement,track } from 'lwc';
 2 
 3 export default class MyTestVariable extends LightningElement {
 4     @track greeting = 'World';
 5     @track showDetail = false;
 6     @track historyList = new Array();
 7 
 8     handleChange(event) {
 9         this.greeting = event.target.value;
10         if(this.greeting.toLocaleLowerCase() === 'xx') {
11             this.showDetail = true;
12         } else {
13             this.showDetail = false;
14         }
15     }
16 
17     logHistory(event) {
18         const previousHistoryValue = this.historyList.length > 0 ? this.historyList[this.historyList.length - 1].Name : '';
19         const previousHistoryId = this.historyList.length > 0 ? this.historyList[this.historyList.length - 1].Id : 0;
20         if((previousHistoryValue !== '' && event.target.value !== '' && previousHistoryValue !== event.target.value) || (previousHistoryValue === '' && event.target.value !== '')) {
21             const tmpId = previousHistoryId + 1;
22             const tmpName = event.target.value;
23             const history = {Id:tmpId,Name:tmpName};
24             //this.historyList = [...this.historyList,history];
25             this.historyList.push(history);
26         }
27     }
28 
29     get wiredGreeting() {
30         return this.greeting.toUpperCase();
31     }
32 
33     get showHistory() {
34         return this.historyList.length > 0 ? true : false;
35     }
36 }

咱們將metadata文件設置爲能夠放在lightning_app/ lightning_home以及lightning_record之後,部署之後即可以放在home的page layout中展現了。api

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="myTestVariable">
 3     <apiVersion>46.0</apiVersion>
 4     <isExposed>true</isExposed>
 5     <targets>
 6         <target>lightning__AppPage</target>
 7         <target>lightning__HomePage</target>
 8         <target>lightning__RecordPage</target>
 9     </targets>
10 </LightningComponentBundle>

結果以下圖所示:瀏覽器

這個demo中涉及到了幾個關鍵的學習的點:app

 if:true: 作過aura的小夥伴都知道aura:if標籤,if:true和aura:if的功能相似,或者小夥伴作過angular也會知道ng-if,功能爲true的狀況下展現包含的內容,false的狀況下則不展現;框架

for:each:在LWC中,針對list的遍歷有兩種循環方式,一種是使用for:each方式,一種是使用iterator方式。demo中使用的是for:each接收list,for:item做爲他的每一個循環中的item變量用來訪問當前的item,若是咱們想訪問當前的index,咱們能夠用for:index來接收當前的index,這裏須要注意一點的是,針對每個item,必需要有key這個屬性聲明,當list的值變了之後,系統渲染list的時候看當前的key對應的數據是否有變化來進行渲染,沒有變化就不會從新渲染。key必須是惟一的,並且不能使用index的值做爲key,而且針對key的類型只能是String或者Number;另一種iterator:iteratorName={array}方式來聲明list,這種聲明的方式爲它封裝了first,last兩個屬性,能夠判斷出來當前的item是否爲這個列表的first和last。詳情用法參看:https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_lists性能

上面的js代碼中你們能夠看到咱們import了track,而且針對前端的展現的變量咱們都使用了@track這個註解進行了聲明。若是沒有聲明會怎樣呢?實際上沒有了track的聲明之後,當咱們在前臺改變了World的值之後,上方的區域不會實時的變化成輸入的值,下面的input History List也不會在失去焦點的狀況下增長了item。能夠說由於有了track的存在,使這些變量的值改變之後,前臺的component進行了reRender(從新渲染)操做。針對LWC的變量改變是否會從新渲染前臺component,咱們能夠將變量分紅兩種類型:Private 以及 Reactive。

 不論是Private 仍是 Reactive類型,lwc針對變量聲明都有相同的規範。即:聲明變量必須聽從駝峯標準,使用駝峯標準好處是若是有父子引用等,能夠將js中的變量按照指定規則識別成html中的attribute,好比變量名稱爲itemName會在html中識別成item-name,固然這個在後面的demo中會用到。除了這個聲明的規範之外,LWC還有一些變量聲明的要求,好比變量聲明中不能以 on / aria / data做爲起始字符;變量名不能爲slot / part / is 等限制。感興趣的能夠自行查看文檔。

接下來回到 Private 以及 Reactive,針對 Private,舉一個不太恰當的比喻,在apex中能夠聲明變量爲 private / public / global 類型,其中 private只能當前這個類當中引用,而且 apex page中沒法引用,這裏的 Private也有這層意思,區別是 Private類型變量能夠在component中使用,可是他的後期的任何變化不會對component進行從新渲染,並且父頁面也沒法經過注入方式修改此類型變量;咱們更多的要介紹的是 Reactive類型變量,此種變量的特色爲當此變量改變之後,component便會從新渲染,在這個component中的全部的表達式都會從新計算。此種變量有兩個類型: public / tracked(private). public 使用@api註解進行修飾。tracked使用@track註解進行修飾。這裏須要注意的是,若是使用了@track 或者@api,必需要import track或者 import api在頭部才能使用。

 Tracked: Tracked類型也能夠稱爲Private類型的Reactive,此種聲明類型能夠實現當變量改變之後,component進行reRender操做,此種類型的變量當其餘的component引用之後,不能夠經過attribute方式進行注入值,;此種類型頭部聲明須要引用:

import { LightningElement, track} from 'lwc';

Public:Public類型和Track類型區別爲當其餘的component進行引用時,能夠經過attribute進行注入值。此種類型聲明時頭部須要引用:

import { LightningElement, api} from 'lwc';

看到上面這幾種類型的介紹,咱們可能會有一個疑問,聲明成reactive是否是比private更好更方便?其實在變量聲明時咱們必定要千萬的注意考慮好變量的做用域,變量類型。reactive類型當改變之後整個component都會reRender,全部template中包含的表達式都會被從新計算,使用不當可能會形成不許確或者沒必要要的性能影響,因此聲明之前要考慮清楚變量用途。下面的Demo用來深化一下Tracked以及Public的用法。咱們想要知道LWC封裝了哪些component,咱們能夠訪問:https://developer.salesforce.com/docs/component-library/overview/components進行查看。

 chartBar.html: 展現了一個區域用來顯示percentage,旁邊使用lightning-progress-bar展現目前percentage對應的比例。

 1 <template>
 2     <div class="container">
 3         <lightning-layout vertical-align="center">
 4             <lightning-layout-item>
 5                 {percentage}%
 6             </lightning-layout-item>
 7             <lightning-layout-item flexibility="grow">
 8                 <lightning-progress-bar value={percentage} size="large"></lightning-progress-bar>
 9             </lightning-layout-item>
10         </lightning-layout>
11     </div>
12 </template>

chartBar.js: 聲明瞭兩個變量。一個是track註解的private類型的reactive變量,一個是api註解的public類型的reactive變量。由於process-bar 最小值爲0,最大值爲100, 因此咱們針對這個percentage進行限制,大於等於100設置爲100, 小於等於0或者不是數字狀況下設置爲0,其餘狀況下正常顯示。咱們對percentage進行track,同時將formattedPercentage暴露給其餘的APP用來能夠賦值注入,針對變量,若是有get則必需要有set,兩個儘可能作到一塊兒出現,並且官方建議在get方法去聲明@api註解。set方法去作數據的初始化處理

 1 import { LightningElement, api, track } from 'lwc';
 2 
 3 export default class ChartBar extends LightningElement {
 4 
 5     @track percentage;
 6 
 7     @api get formatedPercentage() {
 8         return this.percentage;
 9     }
10 
11     set formatedPercentage(value) {
12         if(isNaN(value) || value === '') {
13             this.percentage = 0;
14         } else {
15             const integerValue = parseInt(value);
16             if(integerValue < 0) {
17                 this.percentage = 0;
18             } else if(integerValue > 100) {
19                 this.percentage = 100;
20             } else {
21                 this.percentage = integerValue;
22             }
23         }
24     }
25 }

apiProperty.html: 咱們聲明瞭一個輸入框,固然這裏面也能夠不用指定上限下限以及類型,由於咱們在chartBar中已經在set方法中進行了邏輯處理

1 <template>
2     <lightning-input label="Percentage" type="number" min="0" max="100"
3         value={percentage} onchange={handlePercentageChange}></lightning-input>
4     <c-chart-bar formated-percentage={percentage}></c-chart-bar>
5 </template>

apiProperty.js: 咱們對變量進行了track標籤處理以及新增方法去實時獲取輸入的值給子component.

1 import { LightningElement, track } from 'lwc';
2 
3 export default class ApiProperty extends LightningElement {
4     @track percentage = 50;
5 
6     handlePercentageChange(event) {
7         this.percentage = event.target.value;
8     }
9 }

 顯示效果以下:咱們輸入值之後,由於apiProperty中percentage是track的,因此改變之後會reRender 這個component中全部的表達式,c-chart-bar的formated-percentage便會走set方法從而chartBar component的percentage變化。chartBar的percentage變化便會從新渲染chartBar的全部的表達式,因此下方的進度條也會跟着變化。

咱們經常使用的註解除了@track 以及 @api之外,還會常用@wire,區別爲前兩個是針對前臺的,後面的這個是wire service,能夠用來獲取數據,建立數據,調用apex等等,這個之後會有講解。

既然reActive類型變量這麼神奇,是否有什麼相關的limitation呢?答案是有的。針對reActive類型變量只支持三種類型:

  • Primitive values
  • Plain objects created with {…}
  • Arrays created with []

只有這三種類型容許reActive,其餘的類型即便聲明瞭,也無法作到改變之後從新渲染component,而且會在console log裏面提示你當前類型不支持track。

二. Import / Export

上面的例子中,咱們默認須要import LightningElement,咱們自動生成的類會有export變量,那import / export有什麼用呢?

 export 詳細介紹:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export

 import 詳細介紹:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

讀完上面的兩個聲明的用法之後,咱們能夠簡單的理解爲若是咱們有方法或者模塊能夠做爲公用的方法去進行javascript share,咱們即可以使用export標籤去聲明,聲明之後其餘的component js或者其餘須要引入的即可以 import而且直接使用其封裝好的功能。import中會用到的更多,好比咱們代碼中用到了track / api / wire,咱們便須要對他們進行import,咱們引用了第三方的庫存在了static resource中,咱們也要進行import,咱們使用了其餘的公用的js,咱們一樣須要將其import進來。下面進行一個簡單的例子去理解一下import/ export

 commonUtils.js:用來聲明一個公用方法,傳入date,返回當前date的最大的一天

 1 const getMaxDayForThisMonth = (currentDate) => {
 2     if(currentDate.getMonth() === 12) {
 3         return 31;
 4     } else {
 5         const tmpDate = new Date(currentDate.getFullYear(),currentDate.getMonth() + 1,1);
 6         return (new Date(tmpDate - 24*60*60*1000)).getDate();
 7     }
 8 };
 9 
10 export {getMaxDayForThisMonth};

useCommonUtils.html:顯示最大天數

1 <template>
2     {maxDate}
3 </template>

useCommonUtils.js: 引入commonUtils暴露的方法,而且引用此方法。

1 import { LightningElement } from 'lwc';
2 import {getMaxDayForThisMonth} from 'c/commonUtils';
3 
4 export default class UseCommonUtils extends LightningElement {
5     maxDate = getMaxDayForThisMonth(new Date()); 
6 }

結果展現:當前的日期是8月,最大的一天是31,因此結果輸出爲31.

 

總結:篇中只簡單的介紹了關於track / api 以及 import / export的基礎知識,深刻學習還請本身查看文檔。篇中有錯誤地方歡迎指出,有不懂的歡迎留言。

相關文章
相關標籤/搜索