HTML Templates
嗨,同学们,咱们接着讲Lightning Web Components里一个非常重要的部分——模板系统。你可能会问,模板系统强在哪儿?我告诉你啊,它的强处在于它用了虚拟DOM,来智能高效地渲染组件。 咱们在写LWC组件时,模板的根标签一定是 `<template>`,这个别搞错了。在这个根 `<template>` 里面,我们还可以嵌套其他的 `<template>` 标签,这些嵌套的标签可以和指令配合使用,帮我们控制哪些内容该显示、哪些内容要循环。 那从最基础的讲起,数据绑定很简单,你在模板里用花括号 `{property}` 就能把JavaScript里的属性值显示出来。比如你有一个 `message` 属性,写 `{message}` 就绑定了。 更进一步,模板里还能写复杂的表达式,比如做简单的计算,或者调用getter函数,让界面动态变化。 当你想根据条件来显示或隐藏某一块内容的时候,我们就用条件渲染。LWC提供了 `if:true` 和 `if:false` 指令,写在 `<template>` 标签上。比如你想在 `isLoggedIn` 为真时显示“欢迎回来”,就写 `<template if:true={isLoggedIn}>欢迎回来</template>`,非常直观。 列表迭代呢,用 `for:each` 指令,绑一个数组,然后用 `for:item` 指定当前项,`for:index` 指定索引,再搭配 `key` 指令给每个元素一个唯一标识,这样性能最好。像这样: ```html <template for:each={contacts} for:item="contact" for:index="index"> <p key={contact.id}>{index}. {contact.name}</p> </template> ``` 你看,从最基础的数据绑定,到稍微复杂一点的表达式,再到条件渲染和列表循环,这些全都涵盖在咱们的模板系统里,而且背后虚拟DOM会智能地只更新变化的部分,让组件跑得飞快。 好了,这个Slide的核心点就这么多,大家消化一下,下一节我们深入实践。
本课程共有 19 个章节
同学们,今天我们来讲讲 Lightning Web Components 的 HTML 模板文件里的一些硬性规定,别看是基础,但一不小心就会踩坑。 每个 LWC 组件都必须有一个 HTML 文件,这个文件就是组件的脸蛋。它的根标签必须是 `<template>`,而且整个文件的大小不能超过 128 KB。这个限制平时不太会碰到,除非你往里塞了一大坨内联样式或者乱七八糟的东西,心里有个数就行。 接下来重点说说嵌套 `<template>`。如果你在根 `<template>` 里面又放了 `<template>`,那内层的这个模板标签就必须带上特定的指令,比如循环用的 `for:each`、`iterator`,或者条件渲染用的 `lwc:if`、`lwc:elseif`、`lwc:else`,还有老式的 `if:true` 和 `if:false`。最关键的是,这种嵌套的 `<template>` 上不能加任何其他 HTML 属性,什么 `class`、`id`、`style` 统统不行。如果你真的需要加属性,很简单,在外面包一个 `<div>` 或者 `<span>`,把样式、类名写在这个包装器上,里面的 `<template>` 只负责逻辑指令。框架这样设计是为了让渲染更干净高效。 还有一点,等到组件真正渲染到页面上的时候,`<template>` 标签自己会消失,被你的组件自定义标签取代,最终用户看到的是你 `<template>` 包裹里的真实内容。 说到自定义标签,在 HTML 里使用咱们的组件时,千万要写完整的闭合标签,比如 `<c-my-component></c-my-component>`,不能偷懒写成 `<c-my-component />`。因为根据 HTML 规范,自定义元素不属于空元素,必须显式结束。写自闭合虽然看起来简洁,但可能会引起解析问题。 最后推荐大家安装 VS Code 的 Salesforce Extension Pack 插件,它能实时标出模板里的格式错误,比如嵌套 template 用了不该用的属性,马上就会给你波浪线提示,省得部署之后才发现。 好啦,这几个规则记住了,你写起模板来就会顺手很多。下节我们接着聊。
好,同学们,我们来聊聊Lightning Web Components里的数据绑定和反应式特性,这部分非常关键,懂了它,你的组件就能活起来。 首先看数据绑定,就是怎么把JavaScript里的数据显示到模板上。在HTML模板中我们用大括号 `{}` 括起属性名,比如 `{data}` 或者 `{data.name}`,注意,里面不能有空格,也不能写复杂的表达式,像 `person[2].name` 这种是,不允许,的。所以保持简单,直接引用属性就行。 然后是事件绑定,当我们需要响应用户操作时,比如按钮点击,我们用 `{handlerName}` 的形式把事件和JavaScript里的方法连接起来,注意事件绑定的写法就是在事件属性里直接给方法名,不用加括号。 接着我们说一下,Getters,。如果要显示的值需要一些逻辑计算,官方推荐用getter,也就是 `get 属性名()` 这种JavaScript访问器。它不仅仅是一个计算属性,它本身就是一个函数,方便你写单元测试。所以比起直接在模板里试图写计算,用getter更规范、更易维护。 最棒的是,LWC里的字段都是,反应式,的。啥意思呢?就是说,只要你在模板里直接用了一个属性,或者在getter里间接用到了它,当那个属性的值发生变化时,组件就会自动重新渲染。不需要你手动干预,LWC会自动追踪依赖。 而且一旦重新渲染,模板里所有的表达式都会被重新计算,所以显示的数据始终是最新的。 好了,记住这些,你的组件就能动态更新、实时响应用户操作。这个Slide内容就到这里,我们下节课继续学习。
大家好,今天我们来聊一个非常实用的小更新——类对象绑定,从 API 版本 62.0 开始支持。别被名字吓到,简单说,就是你在 JavaScript 里动态拼接 CSS 类名的时候,现在写起来更省心,结果也更干净了。 想象一下,你有一个组件,要根据状态切换样式,以前我们可能传一个数组或者对象给 class 属性。在旧版本里,如果你传数组,它会把所有东西都用逗号连起来,比如 `['btn', isActive && 'active', null]`,结果可能变成 “btn,active,” 这种带多余逗号的字符串。传对象的话,布尔值 false 会变成字符串 “false” 出现在类名里,数字也会变成字符串,一个普通对象直接变成 “[object Object]” ,看起来乱七八糟。 从 API 62.0 开始,这一切都理顺了。数组现在会用空格来连接,而且自动去掉那些空值、假值,比如 false、null、undefined 和空字符串。所以刚才那个数组会干净地输出 “btn active”。传对象的话,只有那些属性值为真(truthy)的键名才会被添加到类列表里,布尔、数字、函数这些不会变成奇怪的类名,直接就被忽略了。这样做出来的 DOM 类属性特别整齐,不容易出错。 当然,如果你确实想把一个数字或者布尔值显示为类名,那就要自己动手,在绑定表达式里先用 String() 转成字符串,这样才会被呈现出来。新版本这样做,其实是鼓励我们写出更规范、更好维护的代码。 所以,如果你还没升级,我强烈建议把组件的 API 版本调到 62.0 或更高,这样就能用上更聪明的类绑定逻辑。已经上线的项目,也可以趁这个机会检查一下那些动态样式的地方,看看有没有因为版本升级变得更清爽。这个小小的改动,会让你的模板代码更可靠,也更易读。 好了,关于类对象绑定就讲到这儿,下节课我们继续。
同学们,咱们今天来看看Lightning Web Components里如何处理样式,特别是内联样式,以及大家要养成的好习惯。 先记一个核心原则:,能用CSS类就不要用内联样式,。类可以复用,好维护,性能也更好。那什么时候用内联样式呢?只有当样式值是动态计算出来的,比如根据数据变动的宽度、颜色,才需要直接用内联样式。 好,那怎么写内联样式呢?在你的HTML模板里,给元素加一个`style`属性,然后绑定到组件JavaScript里的一个,getter函数,。这个getter要返回一个,CSS字符串,。 要注意三点: 第一,CSS属性名得用“烤肉串式”命名,也就是小写单词用连字符连接,比如`font-size`、`background-color`,不能写驼峰。 第二,多个样式规则之间用,分号,分隔,就像你正常写内联样式一样。所以返回的字符串就是这样:`"font-size: 20px; color: red;"` 第三,这个字符串完全是动态拼出来的,所以你可以根据组件里的数据算。 我举个最简单的父子组件例子:假如你有一个图表条子组件,宽度是父组件传过来的百分比。父组件计算好,比如`barWidth = 75`,传给子组件。子组件用一个getter,返回`width: ${this.percentage}%`这样的字符串,再绑定到`style`上,这个图表条就会根据数据伸缩了。这正是动态内联样式的好例子。 最后提醒大家,遵守MDN文档里关于全局`style`属性的规范,你写的CSS字符串必须合法。这样你的代码既规范又灵活。 记住了吗?优先用类,动态值才用内联样式,属性用烤肉串,拼接字符串用分号隔开。下课后可以自己写个简单的进度条组件练练手。
同学们,今天我们来聊一个很有趣的新功能,叫做“复杂模板表达式”。这是一个Beta测试版,需要你的组件API版本是66.0及以上才能使用。它让我们直接在HTML模板里写一些简单的JavaScript表达式,不用再为了一个简单的显示值去专门写一个getter方法啦。 你想想,以前如果我们要显示一个读作“先生”或者“女士”这样的称呼,就得在JS里定义一个getter,返回某个表达式的结果。现在,这些轻量级的逻辑可以直接写在模板里,支持模板字面量、三元运算符、逻辑运算符、函数调用、数组操作,还有那种带空值合并的安全链式访问。听起来是不是很方便? 要启用这个功能,你得在组件的.js-meta.xml配置文件中,把apiVersion设成66.0或更高。系统看到这个版本,就会开启强大的表达式支持;如果版本低一些,它会老老实实退回到原来那种只能做基本属性绑定的模式,不会出错。 不过,一定要记住,这是Beta版功能。也就是说,现在不能用在正式的生产环境里哦。它适合我们在开发测试、沙盒环境、内部工具或者纯粹学习的时候拿出来用,提前感受一下它带来的便利。 好,关于复杂模板表达式我们就讲到这里。等它正式发布以后,就可以直接用到你的项目中,让代码更简洁了。有什么问题,随时可以问我。
同学们,今天咱们来看LWC模板里一个很实用的特性——复杂表达式。你可以把它想象成在HTML中直接写JavaScript小片段的能力,它让我们的模板变得更聪明,能直接处理各种数据类型和运算。 首先,这些表达式能支持几乎所有基本的JavaScript字面量。你可以直接写字符串,用单引号或双引号包裹;写数字,不管是整数、小数,还是二进制、八进制、十六进制,甚至科学计数法的指数形式,都没问题。布尔值true和false当然也可以,还有空值null。这样一来,我们就省去了很多在控制器里预先定义变量的麻烦。 接着,特别要提的是模板文字。它用反引号把字符串包起来,里面可以用`${}`嵌入任何表达式。比如你想拼接一个问候语,可以直接写`你好,${userName}`,非常直观,不需要再写加号拼接了。而且,还有一种进阶用法叫标记的模板文字,它允许你把整个模板字符串传给一个函数去自定义处理,虽然日常开发中我们用得相对少,但知道有这回事就好。 再者,表达式还支持标识符和成员表达,也就是你可以直接从组件属性一路点下去,访问嵌套的属性,甚至调用方法,形成链式操作。比如直接写`record.name.toUpperCase()`,或者`list.length`,完全没问题,你不用在JS里专门弄一个getter来返回这些值。 总之,有了这些能力,以前我们为了在页面上显示一个计算结果,往往要单独写个getter方法,现在直接在模板里就能完成内联计算。代码简洁多了,也更易读。好了,关于复杂表达式这部分,我们就说到这儿,下节继续。
好,我们这一页来聊聊 LWC 里 JavaScript 表达式支持的运算符,这些在你写模板里的 `{expression}` 时会用到。 首先,,三元操作符是可以嵌套的,,也就是说你可以写 `条件 ? 值1 : 条件2 ? 值2 : 值3` 这样的多层判断,但别嵌套太深,否则可读性会很差。 然后是,逻辑运算符,。`&&` 可以用来做“真实性检查链”,比如 `isLoggedIn && userName`,只有前面是真,后面才会被求值并返回。`||` 则常用来给一个后备值,像 `name || '匿名用户'`,如果 name 是假值,就展示“匿名用户”。 ,一元运算符,也全部支持:逻辑非 `!` 可以取反,按位非 `~`,还有 `typeof` 查看类型,`void` 忽略返回值。这些你都能直接在表达式里用。 ,算术运算,方面,加减乘除、求幂 `,` 都行。,关系比较,,大于、大于等于、全等 `===`、不全等 `!==`,也都正常支持。注意比较时最好用全等,避免类型转换带来的意外。 有一个特别重要的,HTML合规性提醒,:在模板的文本节点里,你不能直接写 `<` 字符,因为浏览器会把它当成 HTML 标签的开头。如果你需要表示“小于”,就用 `=` 或者用单引号括起来的属性表达式里写 `<`(前提是那个位置能正确解析)。简单讲,别在文本表达式中裸写 `<`,用 `<` 或者把逻辑放到返回字符串的 getter 里处理。另外,按位运算符像 `&`、`|`、`^` 等等,在 LWC 表达式中也支持对数字操作。 总之,LWC 模板表达式很强大,常用运算符基本都覆盖到了,你只需要注意那个 `<` 的小坑,和尽量保持表达式简洁就好。
同学们,我们来看今天这一页 Slide,它讲的是 ,LWC 模板里的表达式有多强大,。你可以在 HTML 模板里直接写很多 JavaScript 的表达式,省去不少在 JS 控制器里预处理的步骤。 首先,,函数调用不光能传参,还支持链式调用,。比如你要把一堆物品的名字用逗号连起来,可以直接在模板里写 `{items.map(item => item.name).join(', ')}`,非常直白。 然后你可能会担心,如果某个函数不存在就调用会报错吧?别急,,可选调用表达式, `?.()` 就派上用场了。写成 `{myFunc?.()}` 就只在 myFunc 确实是个函数时才调用,安全得很。 接下来是,数组表达式,,你可以在模板里,内联创建数组,,也可以做 `join`、`filter`、`map`、`reduce` 这些操作。注意这里的 `reduce` 就是通常说的“归并”。所以临时拼个小数组做展示,完全不用跑回控制器写代码。 同样,,对象表达式,也能内联创建对象字面量,像 `{ { id: 1, label: '我的标签' } }` 这样,在循环里动态拼对象很方便。 安全访问方面,,可选链 `?.`, 和,空值合并运算符 `??`, 提供了双重保障。`?.` 让你在访问深层属性时,即便中间是 null 或 undefined 也不会抛错,直接返回 undefined。而 `??` 能设置默认值,比如 `{data?.name ?? '未命名'}`,如果 name 是 null 或 undefined,就显示“未命名”。 还有,,计算属性,支持用方括号加动态键来访问属性,键名里可以用模板字面量。比如你想取某个对象里的 `{obj['prefix_' + type]}`,一下子就拿到了带前缀的属性值,灵活性极高。 最后是一个工程化的好习惯:如果你有一些,可复用的格式化函数,,比如日期格式化、金额大写转换,,最好把它们放在一个共享的 API 模块组件里,,然后在需要的组件里 `import` 进来。这样逻辑集中、一改全改,后期维护轻松很多。 好了,这一页其实就是让你在模板里把 JavaScript 表达式用得游刃有余,既提高了代码的可读性,又减少了控制器里的冗余代码。记住这些写法,慢慢练习,模板会变得更智能。下节课我们再继续深挖。
同学们,我们今天来看一下在 Lightning Web Components 的模板中,如何利用表达式写出更灵活、更强大的内联逻辑。这块内容比较有趣,因为你可以直接在 HTML 模板里做一些过去只能在 JavaScript 控制器里做的事,而且既能保证性能,又不会破坏 LWC 的安全模型。 首先,箭头函数是可以在模板中直接使用的。什么意思呢?比如你有一个数组,想把它映射成另一个结构、或者过滤出符合条件的元素、再或者查找某一项,你都可以直接在模板表达式里用一个箭头函数完成,不需要专门到 JS 文件里去写方法。这样写起来非常直截了当。 不过,使用箭头函数的时候有几条规则你得记住,否则编译会报错。第一,箭头函数内部是允许进行赋值操作的,包括 `++` 这种自增运算,像 `item.count++` 是没问题的。但是,你不允许写带花括号的函数体,也就是 `{ return ... }` 这种形式,必须使用简洁的单行表达式版本。举个例子,只能用 `(item) => item.name`,而不能写成 `(item) => { return item.name; }`。第二,不允许使用生成器箭头函数,也就是那种带 `function*` 的写法,同样普通的函数声明也不能摆在模板表达式里。记住,模板里只能用最简洁的表达式型箭头函数。 接下来,迭代器指令,像 `for:each`,可以和复杂的运算式组合在一起,帮你在渲染的同时做过滤和动态内容的生成。比如你可以在 `for:each` 的表达式里结合 `filter`,只循环那些满足条件的元素,然后展示出来,整个过程一气呵成。同样,`if:true` 这样的条件指令也不是只能接受一个简单的布尔属性,它可以处理相当复杂的布尔运算式,比如多个条件的与或非组合,非常灵活。 总的来说,LWC 的模板表达式给了我们很大的内联计算能力,让我们在保持代码清晰的同时,还能写出动态、高效的界面。它底层的编译器会帮你做好优化,确保安全限制始终生效,所以你不用担心这些表达式会影响组件整体的安全性和性能表现。合理利用这些特性,你的代码会变得更简洁更有力。 好了,这一小节的要点就是这些,大家练习的时候可以多尝试用箭头函数和迭代器组合,感受一下在模板里直接处理数据的便捷。
今天我们来聊聊 LWC 里一个非常实用的小技巧——怎么用模板表达式直接格式化用户输入,而不用写任何 DOM 操作代码。 想象一下,你界面上有一个输入框,用户输入名字,你想实时显示它,同时自动去掉首尾空格、统计字符数,如果为空就显示一条占位文字。在传统的写法里,你可能会在 JavaScript 里监听输入事件,然后手动去更新某个 DOM 元素的文本。但在 LWC 里,我们只需要把输入框绑定到一个属性上,比如 `name`。 当用户在输入框里打字时,`onchange` 事件会拿到输入值,我们只需要在事件处理函数里更新 `this.name` 就行了,根本不需要去 `querySelector` 或操作 innerHTML。这是关键:组件模型会自动追踪属性变化,一旦 `this.name` 变了,模板里所有用到 `name` 的表达式都会重新计算,然后视图就会自动更新。 比如模板里可以这样写: ``` <input value={name} onchange={handleChange} /> <p>{name.trim()} — 字符数:{name.length}</p> <p if:false={name}>请输入您的姓名</p> ``` 这里用到了复合表达式:`name.trim()` 会去掉空格,`name.length` 实时显示字符数量,而 `if:false={name}` 则会在 `name` 为空时展示占位消息。这些表达式直接在模板里计算,不需要我们在 JS 里再写一个 getter 来专门格式化显示内容。 这种模式的好处是,它把显示逻辑直接放在了模板里,让代码更直观,也消除了创建多余计算属性的需要。整个流程就是:用户输入 → 更新属性 → 自动重新渲染 → 表达式重新求值 → UI 即时更新。完全摈弃了手动 DOM 操作,这也正是 LWC 响应式系统的魅力。 所以总结一下:通过模板表达式,你可以轻松实现实时格式化,代码更干净,维护起来也更容易。下次你遇到类似需求时,不妨试试这种简洁的方式。
好,我们来聊聊处理列表的两个核心指令:for:each和迭代器。 如果你只需要把一个数组的数据简简单单地显示出来,那用for:each是最省事的,它就是为了基本的重复渲染准备的。但当你想玩出点花样,比如给列表的第一项或最后一项加个不一样的样式,或者你想知道当前是第几个元素,这时候就需要换用更强大的迭代器。迭代器会提供给你first、last和index这些现成的小帮手,省得你自己去判断。 不过啊,有一条铁律一定要记住:不管你是用for:each还是迭代器,都必须给它配上那个key指令。这个key的值必须是字符串或者数字,千万别用对象或者数组索引。因为框架是靠这个key来精准识别每一个数据项的,只有发现哪个项的数据变了,它才会去重新渲染那一个地方,这样性能才会蹭蹭地上去。 那用迭代器的时候,有个小陷阱你们要注意:要拿到当前项真正的数据值,你得通过it.value点儿属性名,对,就是中间要多写一个value,不能直接写it点儿属性名,一偷懒就容易出错。 最后一点,在迭代器的模板里头,你可以放心大胆地写各种复杂的表达式,比如动态绑定的内联样式、if:true这样的条件显示,或者根据数据切换不同的CSS类。这些花活儿,在这里面全部支持,让列表渲染变得既灵活又省心。
同学们,我们接下来深入看看模板表达式更复杂、也更实用的用法。这些例子几乎涵盖了我们日常开发组件时,绝大多数需要展示数据的场景。 首先,你可能会遇到需要根据某个状态动态切换 CSS 类名的需求。在模板里,我们可以直接用三目运算符来完成,比如 `class={isActive ? 'active' : 'inactive'}`,非常直观。条件渲染也是一样,用逻辑与 `&&` 或逻辑或 `||` 就能决定某块内容是否显示,完全不用写额外的 if 块。 接着,像货币、日期这样的数据,直接显示原始值肯定不行。这时你可以在模板里调用专门负责格式化的函数,比如 `{formatCurrency(price)}`。当然,函数要定义在 JavaScript 类里。如果你觉得一个属性不够用,还可以把多个 getter 组合起来,进行一些更复杂的计算,再把结果展示出来。 数字方面,模板表达式完全支持二进制、八进制和十六进制字面量。你直接写 `0b1010`、`0o17` 或者 `0xFF`,模板会正确解析。字符串处理也很方便,直接在花括号里用 `join` 拼接数组、用 `toUpperCase` 转大写,甚至能使用模板字面量来组合字符串。 处理列表数据时,我们经常需要过滤或者求和。模板里可以直接写 `list.filter(item => item.active).length` 来计算活跃项数量,或者用 `reduce` 算平均值。访问对象或者数组的深层属性时,生怕遇到 null 出错?可选链操作符 `?.` 直接帮你优雅地搞定,比如 `{obj?.deep?.property}`。 关于事件,你甚至可以直接在模板里定义一个内联的箭头函数作为事件处理器,比如 `onclick={() => this.doSomething()}`。虽然要小心不要滥用,但在一些简单的场景下非常灵活。 最后,别忘了类型检查和空值判断。`typeof` 操作符可以直接在表达式中使用,而 `== null` 这个神奇的比较能同时检测 `null` 和 `undefined`,帮你简化很多判断逻辑。 你看,这些模式是不是把组件要做的显示逻辑基本都覆盖全了?掌握好它们,你就能轻松应对绝大多数的界面需求了。
同学们,我们今天聊一个在实际开发中特别实用的话题——,怎么在复杂模板里写出干净、好维护的表达式,。你在写 Lightning Web Components 模板的时候,经常会遇到一小段 HTML 里夹着不少计算逻辑,比如数据过滤、格式化之类。如果写得太乱,后期自己都看不懂,性能也容易出问题。所以我们有七条黄金法则,一条一条过。 首先,,保持简单,。模板引擎每次重新渲染都会重新执行表达式,所以别把大段多行逻辑直接怼在 HTML 属性里。遇到多行逻辑,请果断放到 JavaScript 的 getter 函数里。Getter 就像一个属性,模板里直接写 `{propertyName}` 就行,这样模板清清爽爽,逻辑全在 JS 文件里,一眼就能看懂。 第二,,复杂计算一定用 getter,。这不光是为了好看,更重要的是好测试。你可以给这个 getter 写单元测试,模拟各种输入,确保返回正确。如果把它写在模板里,几乎没法单独测。 第三,,重用逻辑就抽成 API 模块,。一个工具函数好几个组件都要用?别复制粘贴,把它放到一个独立的 JavaScript 模块里,导出成公共方法。这样改一处,所有组件受益,而且单独测这个模块也很方便。 第四,,测,往狠了测,。特别是边缘情况,你别光测理想数据,空数组、undefined、非法格式都得覆盖。还要注意 HTML 合规性和浏览器兼容性,比如有些特殊字符在模板里要转义,否则渲染会崩。好代码是测出来的。 第五,,别嵌套太深,。如果你的模板里 div 套 div 超过三层,就说明该拆组件了。深层嵌套不仅让代码像千层饼一样难啃,还降低可读性,甚至影响性能。拉平结构,该抽子组件就抽。 第六,,给箭头函数起个好名字,。模板里遍历数组经常用箭头函数,比如 `list.map(item => ...)`。千万别用 `x`、`i` 这种无意义的名字,起个见名知意的变量名,比如 `order => ...`,别人一看就知道你处理的是什么。 第七,,记得引号规则和 HTML 合规,。复杂表达式用在属性里,一定要用引号包起来,简单绑定才不用。另外,模板里如果用到大于、小于号,由于 HTML 的转义规则,在文本节点里你该写 `>` 而不是 `>`,避免被浏览器当成标签解析错。 最后,,监控性能,。因为每次组件重绘,这些表达式都会重新跑一遍。如果你在模板里做了数组的复杂过滤或者大量计算,每次重绘都来一遍,交互一多就会卡。所以遇到重复计算的情况,在 JS 里给它缓存起来,或者只在数据变化时重新算一次。大型数组操作也要小心,先分析一下数据量,实在太大就在 JS 里做分页或者懒加载。 简单总结:模板保持瘦,逻辑放 JS,能测就测,能抽就抽,注意性能。这样写出来的组件,你自己看舒服,同事接手不骂街,用户用着也顺滑。 下次做复杂展示的时候,把这七条翻出来对着看,保证你的代码质量上一个台阶。好了,下课。
同学们,今天我们来聊聊Lightning Web Components开发中,一些特别需要注意的关键限制。我知道规则听起来可能有点吓人,但别担心,我慢慢解释,你就明白了。这些限制主要是为了确保你的组件性能最优、代码清晰,而且能在Salesforce平台上稳定运行。 首先,第一条是,API版本要求,。你的组件必须使用至少66.0以上的API版本。这就像咱们用手机系统一样,老版本可能不支持最新功能。在Salesforce里,API版本决定了你可以使用哪些特性,66.0以上才能使用这些新规则和新能力。写代码的时候,记得检查一下组件配置文件里的apiVersion,别低于66.0就行。 第二条,,禁止使用“this”关键字来直接访问属性,。什么意思呢?在传统的JavaScript类里,我们习惯用this.myProperty去读或改数据。但现在不允许了,你必须直接使用属性名。比如,如果你有一个属性叫name,在组件方法里就直接写name,而不是this.name。这样可以让代码更干净,也强迫你更清楚地定义作用域,减少因为this指向混乱导致的bug。不过注意,这里指的直接访问属性,像this.template这种还是可以用的。 接下来,,不支持传统的函数声明和一些特定箭头函数写法,。你不能在组件类里写function myFunc(){}这样的函数声明。但是方法还是可以有,你可以在类里直接定义方法,写法是 方法名(){},这个没问题。另外,你不能写带花括号和return的块体箭头函数,比如 () => { return something; } 是被禁止的。还有纯粹的await表达式也不能独立出现。那怎么处理异步呢?别急,后面有专门的解决方式。 ,赋值运算符和更新操作符的使用也有限制,。像=、+=,还有自增++、自减--这些操作符,只能放在箭头函数里面使用。举个例子,如果你在模板里有个按钮点击处理onclick,你可以在onclick处理函数里面去修改属性值,比如 count += 1。但是你不能直接在组件的一个叫renderedCallback这样的生命周期方法里,独立写一句 count++。这样限制是为了避免在渲染循环中意外修改状态,引起性能问题或难以追踪的错误。 最后,,对于异步Deliverc操作,请使用javascript类里的linkedCallback()和deliverc/await,。这里可能有个发音上的小误会,应该是 `connectedCallback()` 和 `async/await`。也就是说,当组件连接到DOM时,如果你需要进行数据加载等异步工作,就可以在connectedCallback函数前面加上async,然后在里面用await等待数据返回。这样写出来的异步代码又清晰又安全,不会因为过早渲染导致组件出错。 总结一下,其实这些限制是帮你写出更稳健、更现代的Lightning Web Components。刚开始可能会觉得有点别扭,但慢慢习惯后你会发现,代码结构更清爽,问题也更少。下次你自己动手写组件时,把这些规则贴在旁边,一条条对照,很快就会上手啦。
同学们,我们来看一下,在Lightning Web Components的模板里,写表达式的时候,有些地方是有限制的。这些限制看起来有点多,但其实理解了背后的原因,就很容易记住,而且也有固定的办法去应对。 首先,在模板的表达式里面,有一串保留字和语法是完全不能用的,比如 `new`、`select`、`throw`、`yield`、`super`,还有什么类表达式、正则表达式的字面量、BigInt 的字面量,甚至包括表达式里面写注释,还有那个很少用的逗号运算符,这些统统不受支持。你可能会想,为什么不能用呢?主要是因为LWC的模板表达式不是完整的JavaScript,它会被编译成一种安全的、高效的代码,为了防止复杂的逻辑和副作用,所以干脆就不让你在里面用这些可能引起混乱或者性能问题的语法。那遇到真的需要用这些功能的时候怎么办?很简单,就在你的JavaScript类里面,把这些逻辑封装成一个属性或者方法,然后在模板里面只引用这个现成的结果。比如你要创建一个新的对象,就别在模板里写 `new MyClass()`,而是在JS文件里定义一个getter,返回那个对象,模板里直接写成 `{myComputedObject}` 就可以了。 然后呢,有一个很容易踩坑的点,就是属性绑定里面,复杂表达式必须要用引号。什么意思?比如你要动态拼一个class,写成 `class={computedClass}`,没问题,因为 `computedClass` 是一个简单的属性绑定。但如果你想写成 `class={ 'active' + someCondition }` 这样的复杂表达式,LWC就要求你必须把整个表达式的外层用引号包起来,写成 `class="{'active' + someCondition}"`。注意,这里的引号是放在花括号外面的。反过来,如果只是简单的属性绑定,比如 `value={simpleProp}`,这个引号就不需要,写不写都行,但一般我们习惯不加,因为它更简洁。你可以这样记:只要花括号里面不是干干净净的一个属性名或变量名,而是一个需要计算的表达式,那外面就老老实实套上双引号。 最后,我再说一遍应对所有限制的万能方法:一旦你发现模板里面直接写某个操作不支持,别纠结,直接回到JavaScript类里面去准备好数据或者逻辑,然后模板就只是负责展示。比如你要用正则表达式匹配,那就把正则结果存在一个属性里;你想抛出错误,抛错误的动作当然应该写在方法里,而不是模板里。记住,模板保持干净,逻辑放在JS里,这样你的组件既好维护,性能也好。 好了,这个小节就是这些限制和注意事项,大家先有个印象,实际写代码的时候遇到报错,再回头对照一下,慢慢就熟悉了。
同学们,今天我们来说一说 Lightning Web Components 里 HTML 合规性的一个关键点。听起来有点专业,但其实就是在写组件模板时,得守的一些规矩。如果没遵守,页面可能就报错,甚至白屏。所以这节课,我会用大白话,帮大家把这些容易踩的坑都理清楚。 先看第一个要点:在 HTML 模板的文字内容里——也就是文本节点里,千万别直接写“<”这个符号。因为 LWC 的模板解析器会把“<”当成 HTML 标签的开始,你一写,它就去后面找标签,结果找不到,就解析错误了。那需要表示小于的时候怎么办呢?直接用“>=”和“>”就行,它们在文本节点里完全没问题。记住,“<”这个符号,只能出现在引用属性里,比如你绑定一个属性的时候,表达式里面用“<”是可以的。比方说 `{a < b ? c : d}`,这种写在属性值的引号内就没问题。 第二个容易出错的,是属性里的复杂表达式。咱们在属性上用动态值,很多时候要写表达式。比如 `title={someValue}` 这个简单绑定,直接用花括号,引号都不需要。但一旦表达式中包含了计算,像加减乘除、三元运算,或者有空格,就必须给整个属性值加上引号。比如 `title="{obj.name + ' is here'}"`,如果漏了引号,解析器就懵了。所以呢,大家记住:简单的属性绑定,花括号就够了;复杂一点的,一定老老实实加引号。 再一个,HTML 实体,像 `&`、`<` 这些,在 LWC 模板的花括号表达式里是不会自动解码的。也就是说,你写 `{ '&' }` 输出的是字面上的 `&` 这几个字符,并不会变成 `&`。这一点和原生 HTML 不一样,得小心。 还有,要尽量避免在模板里写出看起来像 HTML 标签的文本,尤其是包含 “</” 组合的。比如你变量里存了一段文字是 `“</div>”`,解析器可能会误以为你要关闭标签,导致结构混乱。所以这类字符串最好处理一下再显示。 接下来我们总结一下常见错误,大家写代码的时候对照着检查。第一个高频错误:复杂属性表达式缺少引号。就像刚才说的,`data="{a: b}"` 如果忘写外面那层双引号,那就错了。第二个,文本节点里直接用了“<”,比如 `<p>5 < 10</p>`,应该改成 `5 < 10` 或者用 `>=` 和 `>` 来换一个方式表达。第三个,模板表达式里用了不该用的东西,比如 `this`、`new` 关键字,或者函数声明、块级箭头函数(就是带花括号的那种箭头函数),甚至是在箭头函数外面做赋值或者自增自减操作。LWC 模板表达式有自己的一套限制,它只允许很少量的运算逻辑,你不能在里面定义变量或执行多条语句。比如 `{ this.someMethod() }` 不行,直接写 `{someMethod()}` 就好。`{ items.map(item => {return item.name}) }` 也不行,得改成不带花括号的箭头函数:`{ items.map(item => item.name) }`。还有赋值,像 `{ count = 5 }` 或者 `{ count++ }`,这些统统都不允许。 最后,当表达式里少了括号、大括号,或者用错了运算符,LWC 会给出特定的错误信息。这些信息通常会直接提示你 “缺少括号” 或者 “意外的运算符”,所以遇到报错,仔细看看控制台,往往就能定位到问题。 好了,上面这些就是 LWC HTML 合规性的核心要点。简单回顾一下:文本里别用 `<`,用 `>=` 和 `>`;复杂属性要加引号;实体不解码;避免写 `</` 那样的文本;表达式里别用 `this`、`new`,别写函数体和赋值操作。记住这几点,你的模板就能规规矩矩,少走弯路。下节课,我们接着聊 LWC 的其他开发技巧。
今天我们来讲一下Lightning Web Components里面的条件渲染,这个非常实用。 以前我们可能用过if:true和if:false这种写法,但现在官方已经不再推荐了,建议大家都迁移到新的指令:lwc:if、lwc:elseif和lwc:else。 它们的用法很简单,就是把指令直接绑定到一个属性上。比如lwc:if={isVisible},当isVisible这个属性的值是“真”的时候,对应的那部分界面就会显示出来;变成“假”的时候,这些元素就会从页面上直接移除掉,而不是简单隐藏。这样做的好处是,不会留下多余的DOM节点。 你可以把这些指令用在任何地方,不管是在<template>标签里,还是在普通的HTML元素上,或者是自定义组件、基础组件都行,而且支持嵌套使用。 但要特别注意一点:lwc:elseif和lwc:else必须紧跟在lwc:if或者另一个lwc:elseif的后面,中间不能插入任何其他元素,否则就会报错。 在JavaScript里,你完全不用直接去操作DOM,就像刚才说的,只需要改变那个属性的值就行。比如把this.isVisible改成true或false,界面就会自动更新,非常方便。 还有一个小的最佳实践:如果你用来控制显示的属性是布尔类型,最好给它一个默认值false,这样一开始不显示,后面需要时再打开,切换起来很干净,也不容易出现未定义的情况。 简单总结一下就是:用新的lwc:if系列指令来替代旧的if:true,绑定属性,靠值的变化来控制元素的插入和移除,记住else/elseif必须紧跟前一个条件块,JS里只改数据不动DOM。这样写出来的代码更清晰也更高效。
同学们,咱们现在来看看在Lightning Web Components里怎么渲染列表。有两个核心指令,你一定要记住。 第一个叫“for:each”,它更简单直接。在模板里,你通过“for:item”来访问列表里的每一个项目,很方便,就像普通的循环一样。 第二个是“迭代器”,也就是“iterator:iteratorName”。它功能更强,能让你拿到更多信息。比如,你可以通过“iteratorName.value.某个属性名”来访问当前项的值,注意,这里不是直接写“iteratorName.属性名”,一定要加上“.value”才行。同时,它还能提供索引(index)、是不是第一个(first)、是不是最后一个(last)这些属性。 但不管用哪个指令,都必须搭配一个“key”指令。这个键用来唯一标识每一项,必须是唯一的字符串或者数字,不能直接用对象,也不能用索引。因为框架靠这个键来精准识别哪一项发生了变化,然后只重新渲染变化的部分,这样效率才高。而且这个键在运行时会被优化,不会出现在最终的HTML结构里,也就是DOM里看不到它。 怎么选呢?很简单:当你只是做普通的列表遍历,就用“for:each”。但如果你需要给第一项或最后一项加特殊样式,或者要使用索引,那就选迭代器。最后别忘了,这两种指令都支持在模板里写复杂的表达式,灵活度很高。 好了,列表渲染就讲到这里,是不是挺清晰的?接下来我们看看其他特性。
同学们好,咱们今天聊聊Lightning Web Components里一个挺实用的技巧——如何让一个组件根据不同的状态,渲染出完全不同的界面结构。这就要用到多模板渲染。 首先,组件是可以导入多个HTML文件的。你可以在组件的JavaScript里,把这些HTML文件都导入进来当做模板引用。然后呢,重写一下组件自带的 `render()` 方法。在这个方法里,根据当前组件的某个状态值,比如一个叫 `isEditMode` 的属性,来决定返回哪一个模板。这样一来,当 `isEditMode` 是 true 时,组件就显示编辑界面;是 false 时,就显示查看界面,两个界面完全可以长得不一样。每个额外的模板也都允许拥有自己的CSS文件,文件名和模板保持一致就行,这样样式也能独立控制,不会有冲突。 默认情况下,如果你不重写 `render()`,它会自动去找和组件同名的HTML模板来渲染,这是最常规的用法。 但是,这里要敲一下黑板。在真实的项目中,Salesforce其实更加推荐咱们用另一种更简单的方式:在单个模板文件里直接使用 `lwc:if`、`lwc:elseif` 和 `lwc:else` 这些指令,来切换显示不同的区块。这样做代码集中,维护起来也方便。那什么时候才用导入多个模板的招数呢?只有当不同状态需要的标记结构是真真正正完全不同,比如说骨架屏和完整内容区的HTML结构差别巨大,那用多模板就会很合适。这种用法,有点像 JavaScript 框架里的代码拆分,按需加载不同的视图结构。 简单总结一下:如果你只是几块内容的显示和隐藏,用 `lwc:if` 就足够;如果整个组件的结构都因为状态变了而彻底不同,那你就可以考虑导入多个HTML模板,重写 `render` 方法来实现。记好这一点,以后写组件就能游刃有余了。