Web Components尝鲜——polymer组件封装之date组件

1,694 阅读4分钟

先来说个题外话。很多技术开发可能只知道php和python。polymer是个什么鬼!话不多说,进入正题。


Web Components是什么?

首先我们需要知道,Web Components 包括了四个部分:

Custom Elements 顾名思义,是提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。


HTML Imports 是一种在 HTMLs 中引用以及复用其他的 HTML 文档的方式。这个 Import 很漂亮,可以简单理解为我们常见的模板中的 include 之类的作用。

我们最常见的引入一个 css 文件的方式是:

<link rel="stylesheet" href="/css/master.css">复制代码

Web Components 现在提供多了一个这个:

<link rel="import" href="/components/date.html">


可以理解为渲染模版。


shadow dom提出了很久,最本质的需求是需要一个隔离组件代码作用域的东西,例如我组件代码的 CSS 不能影响其他组件之类的,而 iframe 又太重并且可能有各种奇怪问题。

可以这么说,Shadow DOM 旨在提供一种更好地组织页面元素的方式,来为日趋复杂的页面应用提供强大支持,避免代码间的相互影响。


polymer组件开发——date组件开发

polymer常用周期函数

  • created 

在创建元素时调用,且在设置属性值并初始化本地dom之前调用。

在设置属性值之前用于一次在调用。

  • ready

在设置属性值初始化本地dom之后调用。

初始化shadow dom树之后,用于组件的一次性配置。(配置属性最好使用观察者)

  • attached

元素附加(挂载)到dom后调用。相当于原生的connectedCallback。

主要用于添加文档级事件监听器,例如带注释的事件监听器。

  • detached

元素从dom中分离(卸载)后调用。相当于disconnectedCallback。

主要用途包括删除添加的事件监听器。

  • attributeChanged

在元素属性发生变更时调用。相当于原生的attributeChangedCallback。

用于处理与声明的属性对应的属性更改(对于声明的属性,Polymer会自动处理属性更改)。


date组件开发

  • 先看一波效果图


  • 组件开发时的疑难杂症

  1. 布局问题
  2. 数据都是通过动态获取的但是数据结构该怎样才能便于遍历呢!

    最开始我想到了双层循环,数据结构为[[27,28,29,30,31,1,2],[3,4,5,6,7,8,9]...]。这样数据处理非常麻烦,但是基本可以实现遍历后上图效果。

    后来我想到了最近自己了解到到,display:grid。决定选用它作为布局实现上图效果。遍历和数据处理也不用那么麻烦了。数据就可以直接用一维数组[27,28,29,30,31,...1,2,3,4,5,6,7]遍历了。主要样式如下:

    给除年月所在行除外到日期及星期单独使用一个容器,该容器样式

    display: grid;    grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;

    grid具体参考以下网址:

    css-tricks.com/snippets/cs…


    • 每个月数据获取问题,那一号对应星期几。
    • 一开始想到的是是不是要分平年闰年什么的,后来发现了new Date的妙用。大概实现如下:

      getDayList() { 
        // this.year为面板显示年份,this.month为面板显示月份。
        
        // totalDays为面板所在月份最后一天为多少号
        const totalDays = new Date(this.year, this.month, 0).getDate();
        
        // min表示遍历时需显示上月多少天数据,最多7天。
        // new Date其实就是为了获取改月第一天星期几。如第一天星期五,则需补上周日到周四五天数据
        const min = 1 - (new Date(this.year, this.month - 1, 1).getDay() || 7);
        
        // 面板总共显示42天数据,出去显示上月和本月的,剩余为下月数据
        const max = min + 42;  
      
        // this.dayList为面板展示的数据
        this.dayList = [];  
      
        // 遍历时获取的obj为某一天日期对象,截图中min为-4。总共补了上个月五天数据
        for (let i = min; i < max; i++) {    
          const obj = new Date(this.year, this.month - 1, i); 
      
          // 记录判断是否为当前月数据
          const currMonth = i > 0 && i <= totalDays;
      
          // 记录是否为选中日期
          const select = obj === this.timestamp;
      
          this.push('dayList', {
            date: obj.getDate(),
            currMonth,     
            select,
            disabled: minTimestamp > obj.getTime() || maxTimestamp < obj.getTime()
          })
        }