粘性布局之粘底效果(position sticky, bottom 0)

粘性布局之粘底效果(position sticky, bottom 0)

经常在查资料时访问各种 CSDN 博客会发现,当 屏幕高度 < 左边栏的高度 < 内容的高度 时,滚动屏幕,左边栏会随着内容一同滚动,当滚动到左边栏底部时,左边栏会停止滚动,而内容会继续滚动。

这种设计的优势在于,用户既能够滚动左边栏,又不会在左边栏不够长时,造成页面左侧大片空白的尴尬,这种布局模式,叫做 粘性布局(sticky)

粘性布局在元素满足显示条件时,表现与普通布局没什么不同,但当元素随着页面滚动而无法显示时,会转为 fixed 布局效果,主流浏览器已经全部支持粘性布局(IE不支持)。

通俗一点讲,类似于 Excel 中的“冻结窗格”。

绝大多数网上的教程材料都用 position: sticky; top: 0; 这样的组合来举例,但为了实现 CSDN 左边栏效果,position: sticky; bottom: 0; 似乎不能和想象一样的起作用。

先说结论吧

  1. sticky 的确是无法直接粘底的……
  2. CSDN 使用 JS 动态计算实现,当计算到左边栏底部即将滚上屏幕时,立即对左边栏添加 position: fixed; bottom: 0; 样式,把左边栏定死,延时较为明显,快速上下滚动时能看到闪烁
  3. 我使用 position: sticky; 实现,通过 JS 计算 屏幕高度 - 左边栏高度 得到 top 的值,快速滚动时没有闪烁
阅读更多

Chrome 各版本地址栏显示完整地址(https 和 www)

效果

由于谷歌最近对 Chrome 地址栏改来改去,不同的版本需要对应不同的方法。

Chrome 版本<78

在浏览器输入 chrome://flags/ 回车,找到 Omnibox UI Hide Steady-State URL Scheme and Trivial Subdomains,设置为 Disabled,然后重启浏览器。

Chrome 版本=78

谷歌从 flag 页面砍掉了这个设置,但 flag 还是存在的。

打开 chrome://flags/,78版本已经找不到 omnibox-ui-hide-steady-state-url-schemeomnibox-ui-hide-steady-state-url-trivial-subdomains 了。
按 F12 打开 Console,执行以下命令,然后重启 Chrome。

Console
1
2
3
4
5
6
7
[
'omnibox-ui-hide-steady-state-url-path-query-and-ref',
'omnibox-ui-hide-steady-state-url-scheme',
'omnibox-ui-hide-steady-state-url-trivial-subdomains'
].forEach((f) => {
chrome.send('enableExperimentalFeature', [`${f}@2`, 'true']);
})

代码中 @2 对应的是 Disabled。@0@1 分别对应 Default 和 Enabled。

测试有效的版本:78.0.3904.97
方法来源:ysc3839(https://www.v2ex.com/t/613776

Chrome 版本>78

谷歌彻底砍掉了这两个 flag……

现在安装插件是唯一方法,如果你能够访问 Chrome 网上应用店的话,安装这个插件,无需配置即可显示完整地址:
https://chrome.google.com/webstore/detail/suspicious-site-reporter/jknemblkbdhdcpllfgbfekkdciegfboi
方法来源:MaiKuraki(https://www.v2ex.com/t/588136

如果是 Windows 系统,也可以换用 Chromium 内核的 Edge 浏览器,我已经完全爱上 Edge 啦!

Chromium

IT之家报导,谷歌决定“使URL更易于阅读和理解,并消除对可注册域的干扰”,在Chromium Gerrit中新提交了一个flag标志,未来可在 chrome://flags#context-menu-show-full-urls 中设置开启,届时Chrome浏览器地址栏便可显示完整URL。

嗯,砍了再加回来,绝世好活!

我并没有下载 Chromium 测试这个 flag,未来推出有这个 flag 的正式版后,我可能会会更新这篇博文。

JS 原生对象与数组拷贝

浅拷贝单层对象

1
2
let obj = { id: 1, title: "1" }
let copyOfObj = Object.assign({}, obj)

深拷贝多层对象

1
2
3
4
5
6
7
let obj = {
id: 1,
title: "1",
tag: ['js', 'javascript'],
category: { id: 1001, title: 'frontend' }
}
let copyOfObj = JSON.parse(JSON.stringify(obj))

浅拷贝简单类型数组

1
2
let arr = [1, 2, 3]
let copyOfArr = [...arr]

深拷贝单层对象组成的数组

1
2
3
4
5
6
7
let arr = [
{ id: 1, title: "1" },
{ id: 2, title: "2" },
{ id: 3, title: "3" }
]
let copyOfArr1 = arr.map((item) => Object.assign({}, item))
let copyOfArr2 = JSON.parse(JSON.stringify(arr))

深拷贝多层对象组成的数组

1
2
3
4
5
6
7
let arr = [
{ id: 1, title: "1", subObj: { name: 'subObj1' } },
{ id: 2, title: "2", subObj: { name: 'subObj2' } },
{ id: 3, title: "3", subObj: { name: 'subObj3' } }
]
let copyOfArr1 = arr.map((item) => JSON.parse(JSON.stringify(item)))
let copyOfArr2 = JSON.parse(JSON.stringify(arr))

总结

不考虑性能的情况下,JSON.parse(JSON.stringify(value))是最简最万能的拷贝。

直接操作 Vue data 中不存在的属性导致的 v-model 绑定异常问题

直接操作 Vue data 中不存在的属性导致的 v-model 绑定异常问题

初学Vue遇到的问题,尝试了几个小时才搞明白,大佬应该一眼就能看出什么问题吧……

需要注意,不要直接在JS中操作一个Vue data对象中不存在的属性,如果同时有通过v-model绑定到该对象的不存在的属性时,会出现诡异的行为表现,console中不会报出任何 warnerror

需求是,实现三个复选框,第一个复选框初始为选中状态,一开始写出来是这样的——

HTML
1
2
3
4
5
<div id="app" style="margin: 10px;">
<van-checkbox v-for="box in checkboxes" :key="box.id" v-model="box.selected">
复选框 {{ box.title }}
</van-checkbox>
</div>
JS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el: '#app',
data () {
return {
checkboxes: [
{ id: 1, title: 'a' },
{ id: 2, title: 'b' },
{ id: 3, title: 'c' }
]
}
},
created () {
this.checkboxes[0].selected = true
}
})

试下效果:

See the Pen vue-v-model-not-work by iMaeGoo (@iMaeGoo) on CodePen.

复选框a的表现显然是异常的,点击不能成功地切换选中状态,而在点击之后再点击其他复选框,才会“有延迟地”切换状态。

阅读更多
CSS 类似 iOS 的毛玻璃动态模糊效果

CSS 类似 iOS 的毛玻璃动态模糊效果

提到网页毛玻璃效果,总结下来有以下2种:

  1. 模糊元素本身
  2. 模糊元素后面的内容

早在之前,1就已经可以通过 CSS3 filter 属性实现,而2一直没有一个好的解决方案。对1的运用,也可以达到2的效果,通过模糊图片的一部分,就可以实现类似 bilibili 导航栏的模糊背景效果 ↓

这样实现的前提是,我们的背景是一个静态的,单一的图片,那么如果我们需要模糊的背景比较复杂呢?仔细观察QQ右栏的标题栏,和下方的应用 Dock,都是 iOS 常见的毛玻璃叠加层效果 ↓

显然模糊元素本身并不能解决所有场景的问题。

阅读更多
XSS, CSRF, CRLF, SQL注入学习笔记

XSS, CSRF, CRLF, SQL注入学习笔记

XSS, CSRF, CRLF, SQL注入都是历史悠久的四种攻击方式,因为参数化查询已经成了普遍用法,我们已经离SQL注入很远了,但是,XSS,CSRF,CRLF却没有远离我们。

本文以初学者角度探讨四种Web攻击以及预防方式,是个人基于对多种Web漏洞的学习总结,不承诺内容规范。

阅读更多

AngularJS 给 directive scope 绑定的 function 传参

如果我们想要给directive的scope中绑定的方法传递参数,需要传递对象,而不是直接传值。

举个栗子,这里的clickOutside是从用的地方传入的一个方法,debug时我们会发现绑进来的clickOutside并不是我们传的clickOutSideAction

1
2
3
4
5
6
7
8
9
10
11
12
13
app.directive('clickOutSide', ['$document', function($document) {
return {
restrict: 'A',
scope: {
clickOutside: '&'
},
link: function (scope, el) {
$document.on('click', function (e) {
scope.clickOutside();
});
}
}
}]);
1
<div data-click-out-side click-Outside="$ctrl.clickOutSideAction()"></div>

如果需要在这里给clickOutSideAction传参数,应该这样改:

1
2
3
4
5
6
7
8
9
10
app.directive('clickOutSide', ['$document', function($document) {
return {
...
link: function (scope, el) {
...
scope.clickOutside({event: e});
...
}
}
}]);
1
<div data-click-out-side click-Outside="$ctrl.clickOutSideAction(event)"></div>

好处是在实际使用directive的地方,不需要考虑参数列表顺序,只需要保证参数名称正确。

AngularJS <input> 输入框自适应内容宽度

在Gist上找到的一个directive,用来让input输入框的宽度自适应内容宽度。
https://gist.github.com/mbenford/8016984

原理是生成一个相同样式的,隐藏的span,通过span的宽度动态改变input的宽度。
同时兼顾了input有placeholder的情况。

如果是在比较大的系统中,可以用throttle节流阀包装一下resize方法,避免性能问题。

如果是textarea,对应的directive在这里:
https://github.com/monospaced/angular-elastic

阅读更多

CSS鼠标悬浮改变相邻元素样式

效果:

Hover me! X

源码:

1
2
3
4
<div class="chip">
<span class="name">Hover me!</span>
<span class="close-bth">X</span>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.chip {
display: flex;
width: fit-content;
font-size: 20px;
text-align: center;
background-color: #ccc;
}

.chip .name { width: 120px; }
.chip .close-bth { width: 30px; }

.chip .name:hover,
.chip .name:hover + .close-bth,
.chip .close-bth:hover {
color: white;
background-color: #888;
}

CodePen link:
https://codepen.io/iMaeGoo/pen/jRqYRJ

hmmmm…这种实现也没什么难的,其实是想试试在博文中插入HTML啦。

AngularJS Material制作气泡弹出效果