如何用css实现瀑布流布局
利用column-count和break-inside这两个CSS3属性即可,复制如下代码即可察看效果
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body { margin: 0; } .waterfall-container { /*分几列*/ column-count: 2; width: 100%; /* 列间距 */ column-gap: 10px; } .waterfall-item { break-inside: avoid; width: 100%; height: 100px; margin-bottom: 10px; background: #ddd; column-gap: 0; text-align: center; color: #fff; font-size: 40px; } </style> </head> <body> <div class="waterfall-container"> <div class="waterfall-item" style="height: 100px">1</div> <div class="waterfall-item" style="height: 300px">2</div> <div class="waterfall-item" style="height: 400px">3</div> <div class="waterfall-item" style="height: 100px">4</div> <div class="waterfall-item" style="height: 300px">5</div> <div class="waterfall-item" style="height: 600px">6</div> <div class="waterfall-item" style="height: 400px">7</div> <div class="waterfall-item" style="height: 300px">8</div> <div class="waterfall-item" style="height: 700px">9</div> <div class="waterfall-item" style="height: 100px">10</div> </div> </body> </html>
文本超出部分显示省略号
单行
overflow: hidden; text-overflow:ellipsis; white-space: nowrap;
多行
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; // 最多显示几行 overflow: hidden;
利用伪元素画三角
.info-tab { position: relative; } .info-tab::after { content: ''; border: 4px solid transparent; border-top-color: #2c8ac2; position: absolute; top: 0; }
已知父级盒子的宽高,子级img宽高未知,想让img铺满父级盒子且图片不能变形
需要用到css
的object-fit
属性
div { width: 200px; height: 200px; } img { object-fit: cover; width: 100%; height: 100%; } MDN
iframe的作用
iframe是用来在网页中插入第三方页面,早期的页面使用iframe主要是用于导航栏这种很多页面都相同的部分,这样在切换页面的时候避免重复下载。
优点
- 便于修改,模拟分离,像一些信息管理系统会用到。
- 但现在基本不推荐使用。除非特殊需要,一般不推荐使用。
缺点
- iframe的创建比一般的DOM元素慢了1-2个数量级
- iframe标签会阻塞页面的的加载,如果页面的onload事件不能及时触发,会让用户觉得网页加载很慢,用户体验不好,在Safari和Chrome中可以通过js动态设置iframe的src属性来避免阻塞。
- iframe对于SEO不友好,替换方案一般就是动态语言的Incude机制和ajax动态填充内容等。
css hack是什么
由于不同的浏览器,比如Internet Explorer 6,Internet Explorer 7,Mozilla Firefox等,对CSS的解析认识不一样,因此会导致生成的页面效果不一样,得不到我们所需要的页面效果。
这个时候我们就需要针对不同的浏览器去写不同的CSS,让它能够同时兼容不同的浏览器,能在不同的浏览器中也能得到我们想要的页面效果。
这个针对不同的浏览器写不同的CSS code的过程,就叫CSS hack,也叫写CSS hack。
具体请看:
http://www.cnblogs.com/Renyi-...
过渡与动画的区别是什么
- transition
可以在一定的时间内实现元素的状态过渡为最终状态,用于模拟以一种过渡动画效果,但是功能有限,只能用于制作简单的动画效果而动画属性
- animation
可以制作类似Flash动画,通过关键帧控制动画的每一步,控制更为精确,从而可以制作更为复杂的动画。
什么是外边距合并
外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。
合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
去除inline-block元素间间距的方法
- 移除空格
- 使用margin负值
- 使用font-size:0
- letter-spacing
- word-spacing
更详细的介绍请看:去除inline-block元素间间距的N种方法
JavaScript问题
同源策略
同源策略可防止 JavaScript 发起跨域请求。源被定义为 URI、主机名和端口号的组合。此策略可防止页面上的恶意脚本通过该页面的文档对象模型,访问另一个网页上的敏感数据。
跨域
- 原因
浏览器的同源策略导致了跨域
- 作用
用于隔离潜在恶意文件的重要安全机制
- 解决
- jsonp ,允许 script 加载第三方资源
- 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
- cors 前后端协作设置请求头部,Access-Control-Allow-Origin 等头部信息
- iframe 嵌套通讯,postmessage
https://zhuanlan.zhihu.com/p/...
JSONP
这是我认为写得比较通俗易懂的一篇文章 直接转载过来
https://blog.csdn.net/hansexp...
域名收敛
PC 时代为了突破浏览器的域名并发限制。有了域名发散。
浏览器有并发限制,是为了防止DDOS攻击。
域名收敛:就是将静态资源放在一个域名下。减少DNS解析的开销。
域名发散:是将静态资源放在多个子域名下,就可以多线程下载,提高并行度,使客户端加载静态资源更加迅速。
域名发散是pc端为了利用浏览器的多线程并行下载能力。而域名收敛多用与移动端,提高性能,因为dns解析是是从后向前迭代解析,如果域名过多性能会下降,增加DNS的解析开销。
事件绑定的方式
- 嵌入dom
<button onclick="func()">按钮</button>
- 直接绑定
btn.onclick = function(){}
- 事件监听
btn.addEventListener('click',function(){})
事件委托
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。所有用到按钮的事件(多数鼠标事件和键盘事件)都适合采用事件委托技术,
使用事件委托可以节省内存。
<li>苹果li> <li>香蕉li> <li>凤梨li> // good document.querySelector('ul').onclick = (event) => { let target = event.target if (target.nodeName === 'LI') { console.log(target.innerHTML) } } // bad document.querySelectorAll('li').forEach((e) => { e.onclick = function() { console.log(this.innerHTML) } })
事件循环
事件循环是一个单线程循环,用于监视调用堆栈并检查是否有工作即将在任务队列中完成。如果调用堆栈为空并且任务队列中有回调函数,则将回调函数出队并推送到调用堆栈中执行。
事件模型
- DOM0
直接绑定
<input onclick="sayHi()"/> btn.onclick = function() {} btn.onclick = null
- DOM2
DOM2级事件可以冒泡和捕获
通过addEventListener绑定
通过removeEventListener解绑
// 绑定 btn.addEventListener('click', sayHi) // 解绑 btn.removeEventListener('click', sayHi)
- DOM3
DOM3具有更多事件类型
DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,全部类型如下:
UI事件,当用户与页面上的元素交互时触发,如:load、scroll 焦点事件,当元素获得或失去焦点时触发,如:blur、focus 鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup 滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel 文本事件,当在文档中输入文本时触发,如:textInput 键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress 合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart 变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified
https://www.jianshu.com/p/3ac...
如何自定义事件
- 原生提供了3个方法实现自定义事件
- createEvent,设置事件类型,是 html 事件还是 鼠标事件
- initEvent 初始化事件,事件名称,是否允许冒泡,是否阻止自定义事件
- dispatchEvent 触发事件
target和currentTarget区别
- event.target
返回触发事件的元素
- event.currentTarget
返回绑定事件的元素
prototype和__proto__的关系是什么
先说结论:
prototype
用于访问函数的原型对象。__proto__
用于访问对象实例的原型对象(或者使用Object.getPrototypeOf()
)。
function Test() {} const test = new Test() test.__proto__ == Test.prototype // true
也就是说,函数拥有 prototype
属性,对象实例拥有 __proto__
属性,它们都是用来访问原型对象的。
函数有点特别,它不仅是个函数,还是个对象。所以它也有 __proto__
属性。
为什么会这样呢?因为函数是内置构造函数 Function
的实例:
const test = new Function('function Test(){}') test.__proto__ == Function.prototype // true
所以函数能通过 __proto__
访问它的原型对象。
由于 prototype
是一个对象,所以它也可以通过 __proto__
访问它的原型对象。对象的原型对象,那自然是 Object.prototype
了。
function Test() {} Test.prototype.__proto__ == Object.prototype // true
这样看起来好像有点复杂,我们可以换个角度来看。Object
其实也是内置构造函数:
const obj = new Object() // 我们可以把这个 obj 想象成原型对象 prototype obj.__proto__ == Object.prototype // true 换个角度来看,相当于 prototype.__proto__ == Object.prototype
从这一点来看,是不是更好理解一点。
为了防止无休止的循环下去,所以 Object.prototype.__proto__
是指向 null
的,null
是万物的终点。
Object.prototype.__proto__ == null // true
既然 null
是万物的终点,那使用 Object.create(null)
创建的对象是没有 __proto__
属性的,也没有 prototype
属性。
原型继承
所有的 JS 对象(JS 函数是 prototype)都有一个 __proto__
属性,指向它的原型对象。当试图访问一个对象的属性时,如果没有在该对象上找到,它还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
继承
JS高程第3版 第6章 继承
寄生组合式继承
function SuperType(name) { this.name = name this.colors = ['red'] } SuperType.prototype.sayName = function() { console.log(this.name) } // 继承实例属性 function SubType(name, age) { SuperType.call(this, name) this.age = age } function inheritPrototype(subType, superType) { let prototype = Object.create(superType.prototype) prototype.constructor = subType subType.prototype = prototype } // 继承原型方法 inheritPrototype(SubType, SuperType) // 定义自己的原型方法 SubType.prototype.sayAge = function() { console.log(this.age) }
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
function sayHi(name) { return () => { console.log(`Hi! ${name}`) } } const test = sayHi('xiaoming') test() // Hi! xiaoming
虽然sayHi函数已经执行完毕,但是其活动对象也不会被销毁,因为test函数仍然引用着sayHi函数中的变量name,这就是闭包。
但也因为闭包引用着另一个函数的变量,导致另一个函数已经不使用了也无法销毁,所以闭包使用过多,会占用较多的内存,这也是一个副作用。
有一个函数,参数是一个函数,返回值也是一个函数,返回的函数功能和入参的函数相似,但这个函数只能执行3次,再次执行无效,如何实现
这个题目是考察闭包的使用
function sayHi() { console.log('hi') } function threeTimes(fn) { let times = 0 return () => { if (times++ < 3) { fn() } } } const newFn = threeTimes(sayHi) newFn() newFn() newFn() newFn() newFn() // 后面两次执行都无任何反应
通过闭包变量 times
来控制函数的执行
实现add函数,让add(a)(b)和add(a,b)两种调用结果相同
function add(a, b) { if (b === undefined) { return function(x) { return a + x } } return a + b }
Ajax
Ajax(asynchronous JavaScript and XML)是使用客户端上的许多 Web 技术,创建异步 Web 应用的一种 Web 开发技术。借助 Ajax,Web 应用可以异步(在后台)向服务器发送数据和从服务器检索数据,而不会干扰现有页面的显示和行为。通过将数据交换层与表示层分离,Ajax 允许网页和扩展 Web 应用程序动态更改内容,而无需重新加载整个页面。实际上,现在通常将 JSON 替换为 XML,因为 JavaScript 对 JSON 有原生支持优势。
XMLHttpRequest API 经常用于异步通信。此外还有最近流行的fetch API。
let xmlhttp if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp = new XMLHttpRequest() } else { // IE6, IE5 浏览器执行代码 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP") } xmlhttp.onreadystatechange = () => { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { document.getElementById("myDiv").innerHTML = xmlhttp.responseText } } xmlhttp.open("GET", "/ajax/test.txt", true) xmlhttp.send()