每日思考(2020/01/03)

题目概览

  • 对影子(Shadow)DOM的了解
  • 怎样修改自动填充表单的黄色背景?
  • 对arguments的理解

题目解答

对影子(Shadow)DOM的了解

  • 概念:是浏览器的一种能力,它允许在浏览器渲染文档(document)的时候向其中的 Dom 结构中插入一棵 DOM 元素子树,但是特殊的是,这棵子树(shadow-dom)并不在主 DOM 树中。可以想象成我们在 Vue 或者 React 中使用的一个个组件,是一种将 HTML 结构、Style 封装起来的结构。

    <!--> 浏览器开发者设置里打开shodow DOM ,可以查看到video的shodow DOM<-->
    <video src="test"></video>

    每日思考(2020/01/03)

  • 结构
    每日思考(2020/01/03)

    • document:就是我们的正常文档 document
    • shadow host:对于一个内部有 shadow-dom 的元素而言,它必然需要一个宿主元素,对于上面的例子而言, video 标签,就是 shadow-dom 的宿主元素
    • shadow-root:通过 createShadowRoot(下文会提及) 返回的文档片段被称为 shadow-root 。它和它的后代元素,都将对用户隐藏,但是它们是实际存在的,在 chrome 中,我们可以通常审查元素去查看它们的具体 DOM 实现。在 video 中,例如暂停,播放,音量控制,全屏按钮,进度条等都是 shadow-root 的后代。它们工作时会显示在屏幕上,但他们的 DOM 结构对用户是不可见的。
    • contents:就是上述所说的 `` 中各子组件的 DOM 的具体实现
  • 目的:Shadow-dom 是游离在 DOM 树之外的节点树,但是他的创建基于普通 DOM 元素(非 document),并且创建后的 Shadow-dom 节点可以从界面上直观的看到。更重要的是,Shadow-dom 具有良好的密封性。这是浏览器提供的一种“封装”功能,提供了一种强大的技术去隐藏一些实现细节。

  • 控制:通过伪元素,我们可以控制 shadow-dom 中 DOM 结构的样式。在 chrome 下,查看 shadow-dom 结构(如果无法看到shadow-dom需要手动打开),可以看到每个结点都加上了一个 pesudo 属性,有了这些属性,我们可以通过伪元素的方式控制

    <div pseudo="-webkit-media-controls-overlay-enclosure">
      <input pseudo="-internal-media-controls-overlay-cast-button" type="button" aria-label="在远程设备上播放" style="display: none;">
    </div>
  • 创建:在线示例

    //定义一个叫做 PopUpInfo的类,它继承自HTMLElement
    class PopUpInfo extends HTMLElement {
      constructor() {
        // 必须首先调用 super方法
        super();
        //创建 shadow root
        var shadow = this.attachShadow({mode: 'open'});
        // 创建 span
        var wrapper = document.createElement('span');
        wrapper.setAttribute('class','wrapper');
        var icon = document.createElement('span');
        icon.setAttribute('class','icon');
        icon.setAttribute('tabindex', 0);
        var info = document.createElement('span');
        info.setAttribute('class','info');
        // 获取属性的内容并将内容添加到 info元素内
        var text = this.getAttribute('text');
        info.textContent = text;
        // 插入 icon
        var imgUrl;
        if(this.hasAttribute('img')) {
          imgUrl = this.getAttribute('img');
        } else {
          imgUrl = 'img/default.png';
        }
        var img = document.createElement('img');
        img.src = imgUrl;
        icon.appendChild(img);
        // 为 shadow dom添加一些 CSS样式
        var style = document.createElement('style');
        style.textContent = '.wrapper {' +
                                   'position: relative;' +
                                '}' +
    
                                 '.info {' +
                                    'font-size: 0.8rem;' +
                                    'width: 200px;' +
                                    'display: inline-block;' +
                                    'border: 1px solid black;' +
                                    'padding: 10px;' +
                                    'background: white;' +
                                    'border-radius: 10px;' +
                                    'opacity: 0;' +
                                    'transition: 0.6s all;' +
                                    'position: absolute;' +
                                    'bottom: 20px;' +
                                    'left: 10px;' +
                                    'z-index: 3;' +
                                  '}' +
    
                                  'img {' +
                                    'width: 1.2rem' +
                                  '}' +
    
                                  '.icon:hover + .info, .icon:focus + .info {' +
                                    'opacity: 1;' +
                                  '}';
        // 将所创建的元素添加到 Shadow DOM上
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
        wrapper.appendChild(icon);
        wrapper.appendChild(info);
      }
    }
    // 定义新的元素
    window.customElements.define('popup-info', PopUpInfo)

怎样修改自动填充表单的黄色背景

  • 现象:当浏览器遇到type="text"与type="password"的input标签紧邻时,会触发浏览器自动填充行为。默认为黄色背景

  • 使用-webkit-autofill属性

    input:-webkit-autofill {
      -webkit-box-shadow: 0 0 3px 100px #eee inset; //改变填充背景色
    }
  • 关闭浏览器自带填充表单功能

    <!-- 对整个表单设置 -->
    <form autocomplete="off" method=".." action="..">
    <!-- 或对单一元素设置 -->
    <input type="text" name="textboxname" autocomplete="off">

对arguments的理解

  • 定义:是一个对应于传递给函数的参数的类数组对象。是所有(非箭头)函数中都可用的局部变量。可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处

    //如果一个函数传递了三个参数,可以以如下方式引用他们
    arguments[0]
    arguments[1]
    arguments[2]
    //参数也可以被设置
    arguments[1] = 'new value';
  • 属性:如果调用的参数多于正式声明接受的参数,则可以使用arguments对象。这种技术对于可以传递可变数量的参数的函数很有用。使用 arguments.length来确定传递给函数参数的个数,然后使用arguments对象来处理每个参数。要确定函数签名中(输入)参数的数量,请使用Function.length属性

    // arguments.callee:指向当前执行的函数
    //arguments.caller :指向调用当前函数的函数。
    // arguments.length:指向传递给当前函数的参数数量。
    // arguments[@@iterator]:返回一个新的Array迭代器对象,该对象包含参数中每个索引的值
    function test(x,y,z){
        console.log(arguments.callee); //[Function: test]
        console.log(arguments.caller); //undefined
        console.log(arguments.length);//2
      console.log(Function.length);//1
        console.log(arguments[0], arguments[1], arguments[3]); // 1 2 undefined
    }
    test(1,2)
  • arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。可以将参数转换为真实数组。

    var args = Array.prototype.slice.call(arguments);
    var args = [].slice.call(arguments);
    
    // ES2015
    const args = Array.from(arguments);
    const args = [...arguments];
  • 对参数使用 typeof

    console.log(typeof arguments);    // 'object'
    // arguments 对象只能在函数内使用
    function test(a){
        console.log(a,Object.prototype.toString.call(arguments));
        console.log(arguments[0],arguments[1]);
        console.log(typeof arguments[0]);
    }
    test(1);
    /*
    1 "[object Arguments]"
    1 undefined
    number
    */

dom

相关推荐