云中的神啊,雾中的仙,神姿仙态桂林的山。这首诗是小时候背过的《桂林山水歌》。
前情回顾
上篇文章聊了下vue源码中的生命周期。有时候我觉的看源码其实是在浪费时间,今天聊一下css中的BFC和今天看的Vue里的一个比较有意思的函数。
BFC(block format context) 块儿格式化上下文
块元素布局过程的区域,也是浮动元素与其他元素交互的区域。可以理解为设置块元素属性的过程。从如何创建bfc来看,bfc的过程主要发生在块元素布局的过程。
什么样的操作会创建BFC?
- 根元素
html - 使用浮动
float - 使用绝对定位
position:absuote|fixed - 使用行内块
display:inline-block - 使用
overflow - 使用
display:flow-root - 弹性布局
display:flex|inline-flex - 网格布局
display:grid|inline-grid - 表格布局
display:table|table-cell
BFC相关的Bug
-
浮动元的父元素高度塌陷处理这个问题通常是给父元素加一个overflow。overflow会创建一个新的BFC,将子元素包含进去。另外一个方法是使用
display:flow-root。它可以创建无副作用的BFC,中的所有内容都会参与 BFC,浮动的内容不会从底部溢出。 -
外边距重合
CSS如何工作?
- 浏览器载入HTML
- html转为DOM,DOM是文件在计算机内存中的表现形式。
- 浏览器会拉取该HTML相关的大部分资源,比如嵌入到页面的图片、视频和CSS样式。
- 拉取到css之后进行解析。基于选择器规则
- 渲染树进行布局
- 展示到网页上
当css遇到无法解析的属性或值时,会忽略并继续执行下一个解析。
CSS shape 形状
css 其实是可以直接设置形状的。这个有一篇文章写得非常好。回头我找一下看看。
隐藏元素的六种方法
display:nonevusibility:hiddenopacity:0clip-path:inset(100%)- html的
hidden属性 - html的
aria-hidden属性
/*******************************************************************************\
* *
* Visually hide any element (mostly text) accessibly. *
* Support includes IE9+ *
* Source: https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html *
* *
*******************************************************************************/
.sr-only {
clip: rect(0 0 0 0);
clip-path: inset(100%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
display:none和vusibility:hidden会将元素从dom中移除,尽量不使用。
那个有意思的函数generateCodeFrame
src/complier/codeframe.js
const range = 2
export function generateCodeFrame (
source: string,
start: number = 0,
end: number = source.length
): string {
const lines = source.split(/\r?\n/)
let count = 0
const res = []
for (let i = 0; i < lines.length; i++) {
count += lines[i].length + 1
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length) continue
res.push(`${j + 1}${repeat(` `, 3 - String(j + 1).length)}| ${lines[j]}`)
const lineLength = lines[j].length
if (j === i) {
// push underline
const pad = start - (count - lineLength) + 1
const length = end > count ? lineLength - pad : end - start
res.push(` | ` + repeat(` `, pad) + repeat(`^`, length))
} else if (j > i) {
if (end > count) {
const length = Math.min(end - count, lineLength)
res.push(` | ` + repeat(`^`, length))
}
count += lineLength + 1
}
}
break
}
}
return res.join('\n')
}
function repeat (str, n) {
let result = ''
if (n > 0) {
while (true) { // eslint-disable-line
if (n & 1) result += str
n >>>= 1
if (n <= 0) break
str += str
}
}
return result
}
这个函数会将接受到的source字符串按照回车键及换行符分割。然后生成一个字符串模板。比如你在文件里写的代码是:
<template>
<div>测试</div>
</template>
它会返回一个类似的
1 | <template>
| ^^^^^^^^^^
2 | <div>测试</div>
| ^^^^^^^^^^^^^^^^^^^^^
3 | </template>
| ^^^^^^^^^^^^^^^^^
如果你写的是js代码:
function test() {
console.log('test')
}
它会返回一个类似的:
1 | function test() {
| ^^^^^^^^^^^^^^^^^
2 | console.log('test')
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | }
| ^^^^^^^
刚开始我一直在想找个函数有什么用,似乎确实是没啥用。然后我找到了如下代码:
// check compilation errors/tips
if (process.env.NODE_ENV !== 'production') {
if (compiled.errors && compiled.errors.length) {
if (options.outputSourceRange) {
compiled.errors.forEach(e => {
warn(
`Error compiling template:\n\n${e.msg}\n\n` +
generateCodeFrame(template, e.start, e.end),
vm
)
})
} else {
warn(
`Error compiling template:\n\n${template}\n\n` +
compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
vm
)
}
}
}
说明这个generateCodeFrame是为了在编译出错的时候给出相应的提示。
总结
BFC块儿格式化上下文,其实是块儿元素尤其是块元素在布局过程中衍生出来的一个概念。而重点是元素布局的常见方法,浮动、定位、弹性、网格。
而对于这个函数,在我们的代码编译出错时,控制台及页面上的错误信息就是这个函数的返回结果。
最后说两句
- 动一动您发财的小手,
「点个赞吧」 - 动一动您发财的小手,
「点个在看」 - 都看到这里了,不妨
「加个关注」 - 不妨
「转发一下」,好东西要记得分享
公众号:JavaScript高级程序设计