[Day09] - 未知网址的弹跳视窗 - is 属性

早上查看文章时 , 发现贴到昨天的资料 /images/emoticon/emoticon04.gif
本鲁立马作文章修改 , 如造成 邦友 的不便 , 请各位海涵 /images/emoticon/emoticon41.gif

有时 客制化元件时 , 我们只是想在 HTML 基础 Tag 上加一个小功能

那我们可以使用 is 这个属性来处理

下面我们来将 <a> 这个 HTML Tag 追加一个询问是否离开页面的 popup 吧 !


实作开始

one 找出对应的 HTML Class 名称

由於我们是要延伸基础的 HTML 元素 , 因此需要 extend 的对象不是 HTMLElement , 而是 Tag 对应的那个 DOM interface

我们可以到 MDN 文件 去查出来

以今天要用的 <a> 为例 , 对应的 DOM interface 是 HTMLAnchorElement

下方表列一些常用的 Tag 跟其对应的 DOM interface

Tag Name Class Name
<a> HTMLAnchorElement
<span> HTMLSpanElement
<div> HTMLDivElement
<ul> HTMLUListElement
<li> HTMLLIElement

two 在 defined 元件时 , 补上要 extend 的 DOM interface

window.customElements.define('wavy-link', WavyLink, {extends: 'a'});

three 参考昨天的 Modal 设定 , 将其加到 wavy-link 上面

window.addEventListener('DOMContentLoaded', (event) => {

  /*
 'beforebegin': 在 element 之前。
 'afterbegin': 在 element 里面,第一个子元素之前。
 'beforeend': 在 element 里面,最後一个子元素之後。
 'afterend': 在 element 之後。
  */

  const head = document.querySelector('head')

  head.insertAdjacentHTML('beforeend', `<link rel="stylesheet" href="./modal.css">`);
  head.insertAdjacentHTML('beforeend', `
        <style>
         .wave-link{
            display: inline-block;
            position:relative;
            background: url(http://i.imgur.com/HlfA2is.gif) bottom repeat-x;
         }
       </style>
    `);

});

function createElementFromHTML(htmlString) {
  var div = document.createElement('div');
  div.innerHTML = htmlString.trim();

  // Change this to div.childNodes to support multiple top-level nodes
  return div.firstChild;
}

class WavyLink extends HTMLAnchorElement {

  connectedCallback() {

    this.classList.add('wave-link')

    this.addEventListener('click', event => {

      event.preventDefault() // 停止 <a> 的预设行为 "跳转页面" 
      this._open()
    })

  }

  _open() {

    // append popupbox to body

    const href = this.getAttribute('href')

    const htmlStr = `
        <div class="pop-up-container">
          <div class="pop-up-container-root">
            <div class="pop-up-box">
              <div class="pop-up-title flex justifyContent">
                <h3 class="mr-30">您要离开此页吗 ?</h3>
                <img class='close' src="./close.svg" />
              </div>
              <div class="pop-up-content">
                你将会前往 <span class="wave-link url">${href}</span>
              </div>
              <div class="pop-up-action flex justifyContent">
               <slot name="modal-action">
                  <button class='close'>取消</button>
                  <button class='confirm'>确定</button>
                </slot>
              </div>
            </div>
          </div>
        </div>
    `

    const popupEl = createElementFromHTML(htmlStr)
    popupEl.querySelector('.pop-up-action .close').addEventListener('click', () => this._close())
    popupEl.querySelector('.pop-up-title .close').addEventListener('click', () => this._close())
    popupEl.querySelector('.pop-up-action .confirm').addEventListener('click', () => this._confirm())
    this._popupEl = popupEl

    document.querySelector('body').appendChild(popupEl);
  }

  _close() {

    const popup = this._popupEl.querySelector('.pop-up-container .pop-up-box');
    popup.style.transform = 'scale(0)';

    setTimeout(() => this._popupEl.remove(), 300)
  }

  _confirm() {

    this._close()
    setTimeout(() => location.href = this.getAttribute('href'), 400)
  }
}

window.customElements.define('wavy-link', WavyLink, {extends: 'a'});

完成 !!

成果

如果想直接体验成果 , 请到 web-component-modal.html 查看

参考资料 :


<<:  应用 LINE Front-end Framework 轻松建立互动 (1)

>>:  【Day13】运算子(Operator)

[NestJS 带你飞!] DAY29 - 实战演练 (上)

这个系列文即将进入尾声,是时候来验收一下前面所学到的东西了,虽然不会所有的功能都在此次实战演练中使用...

Recursion

接下来我们要来学习很重要的递回,接下来让我们了解吧 函式呼叫自己 使用到Stack Fibonacc...

Day 05:到底有多坏?演算法的最坏情况执行时间

讨论演算法的执行时间到现在,我们只提最糟糕的情况,好像不断在强调演算法的效能可以有多差。 你可能会想...

打造你专属的仓颉输入法

我是仓颉输入法的使用者,在 windows 10 之前,微软仓颉输入法是可以选择只显示 big5 字...

Vue.js 从零开始:emit 元件的沟通

上一篇已经学会如何把外部元件的资料传到内部元件,如果是内部传到外部,就需要透过emit来达成。 Pr...