每日思考(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>
结构
- 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 */
相关推荐
Vue和React是数据驱动视图,如何有效控制DOM操作?能不能把计算,更多的转移为js计算?因为js执行速度很快。patch函数-->patch,对比tag,对比tag与key,对比children