Lightning Web Components 组合(五)
使用组合我们可以用来设计复杂的组件。
组合一些比较小的组件,可以增加组件的重新性以及可维护性。
通过以下一个简单的demo,将会展示关于owner
以及container
的概念,在实际的项目中
example-todo-item
一般是通过for:each
循环动态填充的
<!-- todoApp.html -->
<template>
<example-todo-wrapper>
<example-todo-item item-name="Milk"></example-todo-item>
<example-todo-item item-name="Bread"></example-todo-item>
</example-todo-wrapper>
<template>
owner
onwer 是拥有该模版的组件,在以上的demo中onwer 是example-todo-app
onwer 控制所有他包含的组合组件,onwer 可以
- 在组合组件中设置public 属性
- 调用组合组件中的public 方法
- 监听通过组合组件分发的事件
container
container包含其他组件,但它本身包含在所有者组件中,在以上的demo 中example-todo-wrapper
是一个container,container 不如onwer 强大,container 可以
- 读取,但是不能修改包含的组件的public 属性
- 调用组合组件的额public 方法
- 监听由它包含的组件冒出的一些事件,但不一定是所有事件
父子
父组件可以包含子组件,父组合可以是一个onwer 或者containerr
在子组件设置属性
要将包含层次结构从所有者传递到子项,所有者可以在子组件上设置属性或属性。
HTML中的属性变为JavaScript中的属性赋值
- 参考demo
todoApp.js
import { LightningElement, api } from 'lwc';
export default class TodoApp extends LightningElement {}
todoApp.html
<template>
<example-todo-item item-name="Milk"></example-todo-item>
<example-todo-item item-name="Bread"></example-todo-item>
</template>
todoitems.js
import { LightningElement, api } from 'lwc';
export default class TodoItem extends LightningElement {
@api itemName;
}
todoitems.html
<template>
<div>{itemName}</div>
</template>
- 说明
JavaScript中的属性名称是驼峰大小写,而HTML属性名称是kebab大小写(以破折号分隔)
以匹配HTML标准。在todoApp.html,item-name标记中的属性映射到的itemName
JavaScript
属性todoItem.js。
调用子组件的方法
对于public 的方法可以通过@api 装饰器进行配置
以下是一个简单的demo
- 组件class
// videoPlayer.js
import { LightningElement, api } from 'lwc';
export default class VideoPlayer extends LightningElement {
@api videoUrl;
@api
get isPlaying() {
const player = this.template.querySelector('video');
return player !== null && player.paused === false;
}
@api
play() {
const player = this.template.querySelector('video');
// the player might not be in the DOM just yet
if (player) {
player.play();
}
}
@api
pause() {
const player = this.template.querySelector('video');
if (player) {
// the player might not be in the DOM just yet
player.pause();
}
}
// private method for computed value
get videoType() {
return 'video/' + this.videoUrl.split('.').pop();
}
}
- 组件模版
<!-- videoPlayer.html -->
<template>
<div class="fancy-border">
<video autoplay>
<source src={videoUrl} type={videoType} />
</video>
</div>
</template>
- 创建调用组件方法的cnotainer
<!-- methodCaller.html -->
<template>
<div>
<example-video-player video-url={video}></example-video-player>
<button onclick={handlePlay}>Play</button>
<button onclick={handlePause}>Pause</button>
</div>
</template>
- container 组件class
// methodCaller.js
import { LightningElement } from 'lwc';
export default class MethodCaller extends LightningElement {
video = "https://www.w3schools.com/tags/movie.mp4";
handlePlay() {
this.template.querySelector('example-video-player').play();
}
handlePause() {
this.template.querySelector('example-video-player').pause();
}
}
- 返回值
对于返回值的处理,我们通过getter
参考
@api get isPlaying() {
const player = this.template.querySelector('video');
return player !== null && player.paused === false;
}
- 方法参数
@api play(speed) { … }
传递标记到slots
slot 是一个占位符,我们可以传递数据到组件体中,slot 是web components 的一部分
slot 包含命名以及非命名类型,同时对于slot 内容的变动,我们可以通过事件进行操作
- 非命名slot
子组件模版
<template>
<h1>Content in Slot Demo</h1>
<div>
<slot></slot>
</div>
</template>
slot 占位符填充
<example-slot-wrapper>
<example-slot-demo>
<h1>Content in Slot Demo</h1>
<div>
<slot><p>Content from Slot Wrapper</p></slot>
</div>
</example-slot-demo>
</example-slot-wrapper>
- 命名slot
参考格式
<!-- namedSlots.html -->
<template>
<p>First Name: <slot name="firstName">Default first name</slot></p>
<p>Last Name: <slot name="lastName">Default last name</slot></p>
<p>Description: <slot>Default description</slot></p>
</template>
slot 内容填充
<!-- slotsWrapper.html -->
<template>
<example-named-slots>
<span slot="firstName">Willy</span>
<span slot="lastName">Wonka</span>
<span>Chocolatier</span>
</example-named-slots>
</template>
- slotchange 事件
格式
<!-- container.html -->
<template>
<slot onslotchange={handleSlotChange}></slot>
</template>
代码处理
//container.js
handleSlotChange (e) {
console.log("New slotted content has been added or removed!");
}
query selector
querySelector() 以及 querySelectorAll() 是标准的dom 操作api,通过此api 我们可以操作组件的dom元素
- 参考模版
<!-- example.html -->
<template>
<div>First <slot name="task1">Task 1</slot></div>
<div>Second <slot name="task2">Task 2</slot></div>
</template>
- 操作api
// example.js
import { LightningElement } from 'lwc';
export default class Example extends LightningElement {
renderedCallback() {
this.template.querySelector('div'); // <div>First</div>
this.template.querySelector('span'); // null
this.template.querySelectorAll('div'); // [<div>First</div>, <div>Second</div>]
}
}
- 访问slot 中的元素
组件不包含通过slot 传递的参数,如果我们需要访问可以通过this.querySelector() 以及 this.querySelectorAll()
参考代码
// namedSlots.js
import { LightningElement } from 'lwc';
export default class NamedSlots extends LightningElement {
renderedCallback() {
this.querySelector('span'); // <span>push the green button.</span>
this.querySelectorAll('span'); // [<span>push the green button</span>, <span>push the red button</span>]
}
}
通过slot 以及data 进行组件组合
- 通过slot 组合组件
参考组件模版
<example-parent>
<example-custom-child></example-custom-child>
<example-custom-child></example-custom-child>
</example-parent>
为了支持这种模式,组件作者使用slot 元素,但是组件作者必须管理通过slot 传递元素的
生命周期,解决方法,通过通知事件,父组件需要知道子组件可以进行
通信,可以在父组件通过附加在slot 元素上的事件handler
参考代码
组件模版
<!-- parent.html -->
<template>
<div onprivateitemregister={handleChildRegister}>
<!– Other markup here -->
<slot></slot>
</div>
</template>
代码
handleChildRegister(event) {
// Suppress event if it’s not part of the public API
event.stopPropagation();
const item = event.detail;
const guid = item.guid;
this.privateChildrenRecord[guid] = item;
}
处理事件通知自组件的父级,父组件需要使用全局唯一的id 才能使用组件,所以我们看到以上代码使用了guid
要从子组件分发事件,需要使用connectedCallback
参考
connectedCallback() {
const itemregister = new CustomEvent('privateitemregister', {
bubbles: true,
detail: {
callbacks: {
select: this.select,
},
guid: this.guid,
}
});
this.dispatchEvent(itemregister);
}
要通知父组件,自组件不可用,我们需要再父子组件之间建立双向通信
在注册期间子组件发送回调到父组件
父组件通过回调调用子组件,将两一个回调做为参数传递
子组件在取消注册的时候调用父组件的回调
参考处理:
父组件模版
<!-- parent.html -->
<template>
<slot onprivateitemregister={handleChildRegister}>
</slot>
</template>
处理通知子组件不可用的事件
// parent.js
handleChildRegister(event) {
const item = event.detail;
const guid = item.guid;
this.privateChildrenRecord[guid] = item;
// Add a callback that
// notifies the parent when child is unregistered
item.registerDisconnectCallback(this.handleChildUnregister);
}
handleChildUnregister(event) {
const item = event.detail;
const guid = item.guid;
this.privateChildrenRecord[guid] = undefined;
}
自组件在取消注册时调用的组组件回调
// child.js
connectedCallback() {
const itemregister = new CustomEvent('privateitemregister', {
bubbles: true,
detail: {
callbacks: {
registerDisconnectCallback: this.registerDisconnectCallback
},
guid: this.guid,
}
});
this.dispatchEvent(itemregister);
}
// Store the parent's callback so we can invoke later
registerDisconnectCallback(callback) {
this.disconnectFromParent = callback;
}
子组件通知父组件自生不可用
disconnectedCallback() {
this.disconnectFromParent(this.guid);
}
将数据传递给子组件
一般组件注册已经完成,我们可以通过暴露的回调方法进行父子之间的数据通信
参考:
this.privateChildrenRecord[guid].callbacks.select();
父组件可以传递数据到子组件,如下
this.privateChildrenRecord[guid].callbacks.setAriaLabelledBy('my-custom-id');
子组件对应暴露的属性
@track ariaLabelledby;
setAriaLabelledBy(id) {
this.ariaLabelledby = id;
}
- 通过数据组合组件
参考如下,一个通过数据驱动组合的组件
<template>
<div class="example-parent">
<template for:each={itemsData} for:item="itemData">
<example-child
onclick={onItemSelect}
id={itemData.id}
key={itemData.id}>
</example-child>
</template>
</div>
</template>
传递的数据格式如下:
itemsData = [
{
label : 'custom label 1',
id : 'custom-id-1'
selected : false
},
{
label : 'custom label 2',
id : 'custom-id-2'
selected : false
}
]
参考资料
https://lwc.dev/guide/composition#pass-markup-into-slots
Lightning Web Components 组合(五)的更多相关文章
- Lightning Web Components html_templates(三)
Lightning Web Components 强大之处在于模版系统,使用了虚拟dom 进行智能高效的组件渲染. 使用简单语法以声明方式将组件的模板绑定到组件的JavaScript类中的数据 数据绑 ...
- Lightning Web Components 开发指南(二)
Lightning Web Components 是自定义元素使用html 以及现代javascript进行构建. Lightning Web Components UI 框架使用web compon ...
- Lightning Web Components 安装试用(一)
Lightning Web Components 简称(lwc) 是一个快速企业级的web 组件化解决方案,同时官方文档很全,我们可以完整的 学习lwc 项目结构 使用npx 官方提供了一个creat ...
- Lightning Web Components 来自salesforce 的web 组件化解决方案
Lightning Web Components 是一个轻量,快速,企业级别的web 组件化解决方案,官方网站也提供了很全的文档 对于我们学习使用还是很方便的,同时我们也可以方便的学习了解salesf ...
- lightning & web components & templates & slots
lightning & web components & templates & slots Web components, Custom elements, Template ...
- Lightning Web Components 组件生命周期(六)
组件创建以及渲染流程 组件移除dom 处理流程 组件从dom 移除 组件中的disconnectedCallback() 方法被调用 子组件从dom 移除 每个子组件的disconnectedCall ...
- Lightning Web Components 组件样式(四)
要将样式与组件进行绑定,需要创建一个同名的样式文件,这样样式将会自动应用到组件 在组件中定义的样式的作用域是属于组件的,这样允许组件可以在不同的上下文中可以复用, 可以阻止其他组件的样式的复写 css ...
- Web API之Web Components
本文参考<你的前端框架要被web组件替代了>. 于2011年面世的Web Components是一套功能组件,让开发者可以使用 HTML.CSS 和 JavaScript 创建可复用的组件 ...
- Web Components
Web Components是不是Web的未来 今天 ,Web 组件已经从本质上改变了HTML.初次接触时,它看起来像一个全新的技术.Web组件最初的目的是使开发人员拥有扩展浏览器标签的能力,可以 ...
随机推荐
- MySQL学习一:建表
目标:创建三张表,学生表student(sid,name,gender), 课程表course(cid,name), 分数mark(mid, sid, cid, gender); 要求sid, cid ...
- 【题解】Luogu P5341 [TJOI2019]甲苯先生和大中锋的字符串
原题传送门 实际按照题意模拟就行 我们先求出字符串的sa 因为要在字符串中出现k次,所以我们枚举\(l,r(r-l+1=k)\)看一共有多少种合法的方案 合法方案的长度下界\(lb\)为\(Max(h ...
- 如何配置这个maven仓库的源http://mvnrepository.com/repos
http://mvnrepository.com/repos 主要是ID .mirrorof.name 怎么配置,这个网站上有spring5.0的,别的仓库没有,我需要这个源. 原文地址:https: ...
- mysql修改后启动my.cnf报错Starting MySQL... ERROR! The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid).
mysql中文乱码解决 mysql修改my.cnf后启动报错Starting MySQL... ERROR! The server quit without updating PID file (/v ...
- 【代码优化】C#遍历所有控件(Control方法)
直接上代码: /// <summary> /// 判断价格是否可以购买技能的方法 /// </summary> /// <param name="btnBuyA ...
- c#利用定时器自动备份数据库(mysql)
1:引用dll MySql.Data.dll, MySqlbackup.dll 2:建一个数据连接静态类 public static class mysql{public static strin ...
- 在Centos中安装.net core SDK
在Linux中运行.net core 项目必须要有.net core SDK 环境.之前配置过几次,但由于没有做总结.过了几天又配置的时候 感觉特别陌生,今天就记录一次.net core SDK 的安 ...
- C#设计模式之11:命令模式
C#设计模式之11:命令模式 命令模式 命令模式用来解决一些复杂业务逻辑的时候会很有用,比如,你的一个方法中到处充斥着if else 这种结构的时候,用命令模式来解决这种问题就会让事情变得简单很多. ...
- P1108 低价购买 (DP)
题目 P1108 低价购买 解析 这题做的我身心俱惫,差点自闭. 当我WA了N发后,终于明白了这句话的意思 当二种方案"看起来一样"时(就是说它们构成的价格队列一样的时候),这2种 ...
- Java之路---Day07
2019-10-21-23:30:24 ArrayList类[集合] What:java.util.ArrayList是大小可变的数组的实现,存储在内的数据称为元元素,此类提供一些方法来操作内部存储的 ...