带你走进->影子元素(Shadow DOM)&浏览器原生组件开发(Web Components API )

带你走进->影子元素(Shadow DOM)&浏览器原生组件开发(Web Components API )

image.png

本篇介绍

    习惯了使用vuereact等框架来开发组件, 但其实我们可以不依赖任何框架, 直接原生开发组件, 所以这个原生api的一大优点就是可以不依赖任何的框架。

    浏览器本身支持组件是大趋势, 但是目前使用起来并不够好, 但这并不能阻挡我们学习的脚步与对知识的好奇心, 而且我也相信原生组件几年后会成为一种主流的组件编写方式, 现在就让我们一起来学习它吧。

1. 兼容性

Chrome 54 Safari 10.1 Firefox 63

MDN上显示:
image.png

    不建议直接上生产环境。

2. 影子元素

     还记得是我第一次用qiankun.js框架的时候看到的这个概念(接下来的文章会写微前端相关实战), 这个技术可以实现一部分的css样式隔离, 之所以说只是实现一部分样式隔离, 学完这篇文章你就懂了。

第一步: 生成影子元素

    我们新建一个html5页面, 写上如下结构




  


  
我是内部元素

    奇怪的一幕出现了, 内部元素不可见并且在查看结构的控制台里出现了特殊的结构定义。
image.png

  1. attachShadow方法给指定的元素挂载一个Shadow DOM
  2. mode: open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM。
  3. mode: open针对是dom.shadowRoot方法, 直接getElementsByClassName获取还是可以获取到的(这条很重要, 有的文章都说错了)。
  4. mode: open对应的是mode: close
  5. 注意: 不可以先开后关这种操作
第二步: 往里面注入元素
 const link = document.createElement("a");
    link.href = 'xxxxxxxxxxxx';
    link.innerHTML =  '点我跳转';
    shadow`.appendChild(link);
  1. 注意这里使用的是shadow, 而不是dom本身。
第三步: 往里面注入样式
 const styles = document.createElement("style");
 styles.textContent = `* { color:red  } `
 shadow.appendChild(styles);
  1. 通过上面可以看出, 创建了一个style标签插入了进去。
  2. 与此类似我们可以创建一个link标签插入进来效果也是一样的。

效果如下:
image.png

第四步: 样式隔离实验
 styles.textContent = `
       * { color:red  } 
       body {
         background-color: red;
       }
    `

    这里我们在影子元素内部改变了body的样式, 而这个样式没有作用到外面的body身上。
image.png

第五步: 样式渗透实验

    通过上面操作你是不是感觉这个沙盒能完美隔离css了? 那我们现在对最外层的style标签里面加上字体大小的样式, 因为影子元素无法隔离可继承的样式。

* {
    font-size: 40px;
  }

效果如下:
image.png

总结一下:

     影子元素确实可以防止样式泄露到外面污染全局, 但是也没法避免被全局的样式渗透污染, 这里的渗透指的是可继承的样式, 比如你外面style用id获取影子里面的元素改变border属性那就是无效的, 所以qiankun.js暂时无法完美隔离样式, 比如想要改变全局样式就需要靠js帮忙。
     有了上述的知识储备, 就让我们来迎接下一位主角原生组件

完整代码(来复制玩玩吧):




  
  
  Document
  


  
我是内部元素

3. 原生组件的使用

    下图是我做的一个原生组件, 并且附上了使用方法。
image.png

 
 

上面组件的使用看起来与vue等框架里面的组件差不多, 但是它可是很娇气的!

注意事项
  1. 自定义元素的名称必须包含连词线,用与区别原生的 HTML 元素。所以,不能写成
  2. 如果如下方式书写去掉结尾闭合标签, 只会显示第一个, 第二个没有被渲染(这个真的好奇怪), 第二个组件会默认被插到第一个组件中, 由于被插入影子元素所以不显示了。

    
    

    image.png

    奇奇怪怪的现象不是这次的主题, 我们继续研究干货。

4. 编写组件第一步template

template里面的dom结构就相当于影子元素的结构内部。

  

知识点逐一解释:

第一个: dom定义

    上面代码我们拉倒最下面, 在这里我们可以正常的定义dom, 放心书写吧与外面写法一样。

第二个: 定义id