LitElement简介
轻松创建快速轻量级的web组件
LitElement可以轻松定义Web组件——非常适合在整个组织中共享元素或构建UI设计系统。在使用html的任何地方使用您的组件:在document、CMS、Markdown或react或vue等框架中都可以使用它。以下为示例:
import { LitElement, html, property, customElement } from 'lit-element';
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
@property() name = 'World';
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
<simple-greeting name="Everyone"></simple-greeting>
为什么使用LitElement
- 令人愉快的声明
Lit-element简单,熟悉的开发模型使构建web组件变得前所未有的简单。
以声明的方式表达UI,作为状态的函数。不用学习web-components语言,可以在模版中使用javascript的全部功能。element元素更改时会自动更新 - 快而轻
无论是在哪里工作的人,都会欣赏Lit-element的速度非常快。
它使用lit-html定义和呈现html只会重新刷新组件样式动态变更部分 - 无缝互操作
Lit-element遵循web组件标准。因此组件将适用于任何框架。Lit-element使用自定义元素轻松包含在网页中。使用shadow DOM进行封装。
LitElement浏览器兼容性
它适用于所有主流浏览器(Chrome,Firefox,IE,Edge,Safari和Opera)
LitElement与polymer异同
相同点
可自定义元素,组件语法基本都是偏向原生javascript可以很方便大操作dom及bom不同点
- LitElements更轻量级,使用它无需安装任何内容,polymer相对而已重一点,但最新polymer3有一定优化
- polymer支持双向数据绑定,是典型但MVVM框架,而LitElement并不是MVVM框架,它只能算是MVC框架
LitElement使用
- 引入
npm install lit-element
- 定义自定义组件(元素)
// 引入lit-element
import { LitElement, html } from 'lit-element';
// 定义MyElement元素类
class MyElement extends LitElement {
render() {
return html`<p>your template here</p>`;
}
}
// 注册MyElement元素
customElements.define('my-element', MyElement);
- 自定义组件元素的使用
import { MyElement } from 'my-element.js';
然后就可以在html部分像用div、span等这些标签一样任意使用MyElement标签
文章暂时写到这里,以上为本人使用lit-element一点个人见解及总结。原文链接lit-element.polymer-project.org。该地址为官方文档地址,需翻墙才可查看具体内容。下篇文章为会写到本人用lit-element开发H5页面,利用web-view让其完美运行与小程序但心得体会,以及自己造轮子(自定义组件元素)写项目的体验。
H5下拉刷新及上拉加载更多组件封装
以下为下拉刷新及上拉加载更多组件css及html
<style>
// 页面视窗大小
#page-content {
height: 100%;
position: relative;
padding: 0.2rem;
box-sizing: border-box;
}
// 滚动视窗大小
#page-scroll {
overflow-x: hidden;
overflow-y: auto;
height: 100%;
-webkit-overflow-scrolling: touch;
}
// 去掉默认滚动条样式
#page-scroll::-webkit-scrollbar {
width: 0 !important
}
// 放置滚动时的loading,默认隐藏
#pullDown, #pullUp {
position: absolute;
left: 0;
text-align: center;
width: 100%;
background-color: var(--color-second);
display: none;
height: 5vh;
line-height: 5vh;
z-index: 2;
}
#pullDown {
top: 0.05rem;
}
#pullUp {
bottom: 0.1rem;
}
.hidden {
display: none!important;
}
#pagePool {
transition: all 0.2s ease-in-out;
}
</style>
<div id="page-content">
// 下拉刷新的盒子及元素
<div id="pullDown" class="${this.type === 'pullDown' || this.type === 'pull' ? '': 'hidden'}">
<img src="src/images/loading.svg" alt=""/>
</div>
// 滚动盒子及预留插槽
<div id="page-scroll">
<div id="pagePool">
<slot></slot>
</div>
</div>
// 上拉加载更多的盒子及元素
<div id="pullUp" class="${this.type === 'pullUp' || this.type === 'pull' ? '': 'hidden'}">
<img src="src/images/loading.svg" alt=""/>
</div>
</div>
- 下拉刷新实现及逻辑
// 获取可以滚动盒子dom
this.pageScroll = this.shadowRoot.getElementById('page-scroll'); // H5事件,当手指触摸屏幕时触发,触发后拿到当前Y坐标
this.pageScroll.addEventListener('touchstart', e => {
startY = e.touches[0].pageY;
}, false);
// H5事件,当手指触摸屏幕滑动时触发,触发后拿到当前Y坐标与开始触摸坐标差值differ
// 若差值大于30则显示loading,touchAction设置为pullDown(即触发下拉刷新)
this.pageScroll.addEventListener('touchmove', e => {
let differY:number = e.touches[0].pageY - startY;
if (this.touchAction === 'pullDown' || !this.type) return;
if (this.pageScroll.scrollTop <= 0 && differY >= 0) this.pagePool.style['margin-top'] = differY + 'px';
if (this.pageScroll.scrollTop === 0 && differY >= 0 && this.type !== 'pullUp') {
if (differY > 30) {
this.pullDown.style['display'] = 'block';
this.touchAction = 'pullDown';
}
} else {
this.touchAction = 'scroll'
}
}, false);
// 滑动结束触发事件,抛出刷新事件,供于父组件使用
this.pageScroll.addEventListener('touchend', e => {
if (this.touchAction === 'pullDown') {
this.pagePool.style['margin-top'] = '5vh';
if (this.isRequest === true) return;
this.isRequest = true;
this.dispatchEvent(new CustomEvent('refresh', {detail: {action: 'refresh'}}));
} else if (this.touchAction === 'scroll') {
this.pagePool.style['margin-top'] = 0;
}
}, false);
// 父组件刷新数据成功后调用还原下拉刷新样式
private pullDownHidden() {
setTimeout(_ => {
this.isRequest = false;
this.touchAction = 'scroll';
this.pagePool.style['margin-top'] = 0;
this.pageScroll.scrollTop = 0;
this.pullDown.style['display'] = 'none';
}, 500)
};
- 上拉加载更多实现及逻辑
// 滚动组件滚动时,判断滚动距离和内容的值,滚动到离底部5px时,显示loading样式等,同时抛出事件给父组件
this.pageScroll.addEventListener('scroll', e => {
if (this.pullUp.style['display'] === 'block' || this.type === 'pullDown' || !this.type || this.touchAction === 'pullUp') return;
if (this.pagePool.offsetHeight - 5 <= this.pageScroll.scrollTop + this.pageScroll.offsetHeight) {
if (this.isRequest === true) return;
this.pullUp.style['display'] = 'block';
this.pagePool.style['margin-bottom'] = '5vh';
this.touchAction = 'pullUp';
this.isRequest = true;
this.dispatchEvent(new CustomEvent('refresh', {detail: {action: 'upload'}}));
} else { this.touchAction = 'scroll' }
});
// 父组件数据加载完后,调用该方法还原loading样式
private pullUpHidden() {
setTimeout(_ => {
this.isRequest = false;
this.touchAction = 'scroll';
this.pagePool.style['margin-bottom'] = '0';
this.pullUp.style['display'] = 'none';
}, 500)
}
以上为个人H5组件封装逻辑。后续会整理到github。后续会持续更新。