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的基础知识,深刻学习还请本身查看文档。篇中有错误地方欢迎指出,有不懂的欢迎留言。

相关文章
相关标签/搜索