LitElement ——快速、轻量级的Web Components——H5组件下拉刷新,上拉加载更多

7,788 阅读2分钟

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。后续会持续更新。