自定义你的前端组件(shadow-DOM)二

书接上文,上一篇博客。让我们对影子模型有了大致的了解并且可以修改其样式!现在,我们自己去写一个自己的组件!

同样是利用shadow-DOM。首先,我们准备基本的html,也就是我们前面说的 shadow-host

<div id="host">
    Sorry! Your browser does not support the shadow-DOM!!!
</div>  //我是宿主

为了友好提示!我们加一句 “Sorry! Your browser does not support the shadow-DOM!!!”

接下来就是javascript了

if(document.body.createShadowRoot){
    var host = document.querySelector('#host');
    var root = host.createShadowRoot();
    root.innerHTML = '<h1 class="h1" pseudo="test">Shadow-DOM!!!</h1>'
}

让我们看看效果: 上面是chrome浏览器支持shadow-DOM显示效果。底下是不支持的safari显示效果。

这里写图片描述

试想如果我们如何去改变h1的颜色呢?

.h1{
    background: red;
}
#host::test{
    background: red;
}

无论是利用类名选择器这样是行不通的。还是借鉴浏览器自带的伪类选择器的方法,都是行不通的。

注意了:因为影子宿主和影子根之间存在影子边界(shadow boundary)所以,主DOM的样式是不会影响到shadow-DOM,同样shadow-DOM的样式也不能影响到主DOM。
在这里顺便扯一句: 我感觉有点想vue里面的 给组件的css加上scope一样。

那我们要怎么才能自定义影子模型的样式呢?

我们需要借助contenttemplate 为了直观,还是先上代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>shadowDOM</title>
</head>
<body>
  <div id="host">
    <h1 class="title">I am title</h1>
    <p class="subtitle">I am subtitle</p>
  </div>
  <template id="temp">
    <style>
      span{
        color: red;
      }
    </style>
    <p>shadowDOM</p>
    <span>I'm the span tag of template</span>
    <!-- 绑定h1的内容 -->
    <content select=".title"></content> 
    <!-- 如果需要渲染p的内容需要再写一个content并指定他的select属性 --> 
    <!-- <content select=".subtitle"></content> -->
  </template>

  <script>
    var host = document.querySelector('#host');
    var root = host.createShadowRoot();

    var temp = document.querySelector('#temp');
    var clone = document.importNode(temp.content, true);

    root.appendChild(clone);
  </script>
</body> 

步骤:

  • 在宿主下面,我们可以自定义一些带有类名的div。
  • 利用template 可以继续定义一些div。
  • 如果我们想对template里面的元素进行样式的修改。可以如同正常写css一样。
  • 如果我们想在template里面对 content标签内容进行选择修改的话。可以如下:
    ::content h1{
        background: red;
    }
    ::content p{
        background: green;
    }
    /*对宿主对象进行css设置*/
    :host{
        border: 2px solid #ccc;
        transition:  200ms;
    }
    /*定义宿主的hover*/
    :host(:hover){
        padding: 20px;
    }  
  • content具有贪婪的属性。如果你写的时候,没有指定select的话,那么在宿主下面定义的元素 将全部显示出来。所以指定select的值,还是有必要的!
  • 如果你觉的在template标签里面写css样式不够好的话!我没可以借助 ::shadow(只能作用于shadow-root下面的内容) /deep/(可以作用于shadow-root下面的content里面的内容)

     #host::shadow p{
        color: pink;
    }
    /*只能穿透一层*/
    
    #host  /deep/  p{
    
        color: blue;
    }

    至此!关于shadow-dom的自定义shadow-dom的样式就告一段落了。接下来我们再来学习关于他的事件。

document.addEventListener('click', function(e) {
    console.log(e.target.innerHTML + ' click!');
});

这里写图片描述

可以看出shadow-DOM的事件全部绑定到了宿主对象上面。避免破坏主DOM的事件。
至于content里面的内容,因为他在文档中有真实的DOM节点。所以没有没有重定向到宿主上面。

细心的童鞋,不难发现宿主的事件没有发生冒泡!以下是代码,大家可以分别点击红色的div和宿主看看弹出内容的所弹出的次数。如果你嫌弃麻烦请看图:
这里写图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>shadowDOM</title>
</head>
<body>
  <style>
    #pop{
      width: 200px;
      height: 200px;
      background-color: red;
    }
  </style>
  <div id="pop">点我会冒泡 出现2次click</div>
  <div id="host">
    <h1 class="title">I am title</h1>
    <p class="subtitle">I am subtitle</p>
  </div>
  <template id="temp">
    <style>
      span{
        color: red;
      }
    </style>
    <p>shadowDOM</p>
    <span>I'm the span tag of template</span>
    <!-- 绑定h1的内容 -->
    <content select=".title"></content> 
    <!-- 如果需要渲染p的内容需要再写一个content并指定他的select属性 --> 
    <!-- <content select=".subtitle"></content> -->
  </template>

  <script>
    var host = document.querySelector('#host');
    var pop = document.querySelector('#pop');
    var root = host.createShadowRoot();

    var temp = document.querySelector('#temp');
    var clone = document.importNode(temp.content, true);

    root.appendChild(clone);

    document.addEventListener('click', function(e) {
      console.log(e.target.innerHTML + ' click!');
    });
    pop.addEventListener('click', function(e) {
      console.log(e.target.innerHTML + ' click!');
    });
  </script>
</body> 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值