事件的原由是朋友给我发的一个微信javascript
当时就奇怪字体跟数据绑定有啥关系,处于好奇我让他写个 demo 给我看看 ,而后他发来一个代码文件css
代码精简以下:html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style> body { font-size: 40px; } .time1 { display: inline-block; background: linear-gradient(to right, #a6ffcb, #1fa2ff); -webkit-background-clip: text; color: transparent; } </style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
<script> new Vue({ el: "#app", data: { time: new Date().toLocaleString() }, methods: { updateTime() { this.time = new Date().toLocaleString(); } }, mounted() { setInterval(this.updateTime, 1000); } }); </script>
asdasd
</body>
</html>
复制代码
发如今浏览器下时间并不会改变 ,当我在控制台把颜色注释掉后,发现数据是改变的,这就奇怪了呀! 这里我就试了下 另外一种渐变样式写法java
这种我不细说了 也很好理解 能够看上面代码实现方式web
<style> .time2 { position: relative; color: #a6ffcb; } .time2:before { content: attr(time); position: absolute; z-index: 10; color: #1fa2ff; -webkit-mask: linear-gradient(to left, #1fa2ff, transparent); } </style>
<div class="time2" time="time">我是渐变文字</div>
复制代码
选择器:before
向选定的元素前插入内容,使用 content
属性来指定要插入的内容。mask
属性让元素的某一部分显示或隐藏npm
content 取值 attr 就是用来获取属性值的,content:attr(属性名)浏览器
content: attr(time)
; 能获取到元素的 time
属性,这里的这个 time
属性是本身自定义的一个属性,随便写微信
<h1 date="我是渐变文字">我是渐变文字</h1>
复制代码
而后content
属性 这样写,content: attr(date)
; 一样是能够起做用的。app
mask 属性 容许使用者经过部分或者彻底隐藏一个元素的可见区域。这种效果能够经过遮罩或者裁切特定区域的图片。
咱们试试另外一种状况会不会出现不渲染状况
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style> body { font-size: 40px; } .time1 { display: inline-block; } .time1 { background: linear-gradient(to right, #a6ffcb, #1fa2ff); -webkit-background-clip: text; color: transparent; } .time2 { position: relative; color: #a6ffcb; } .time2:before { content: attr(time); position: absolute; z-index: 10; color: #1fa2ff; -webkit-mask: linear-gradient(to left, #1fa2ff, transparent); } </style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
<script> new Vue({ el: "#app", data: { time: new Date().toLocaleString() }, methods: { updateTime() { this.time = new Date().toLocaleString(); } }, mounted() { setInterval(this.updateTime, 1000); } }); </script>
</body>
</html>
复制代码
看下效果
我当时的表情
我想到了是否是浏览器重排和重绘的问题
咱们了解下重排和重绘
浏览器编译页面分为 5 步
当 DOM 变化影响了元素的几何属性(宽、高改变等等),浏览器此时须要从新计算元素几何属性,而且页面中其余元素的几何属性可能会受影响,这样渲染树就发生了改变,也就是从新构造 RenderTree 渲染树,这个过程叫作重排(reflow)
若是 DOM 变化仅仅影响的了背景色等等非几何属性,此时就发生了重绘(repaint)而不是重排,由于布局没有发生改变
页面布局和元素几何属性的改变就会致使重排
下列状况会发生重排:
这边时间文字改变了,但文字大小没变,我感受按道理应该没有触发重排从而使背景色没有改变 ,那我试试改变文字大长度试试
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style> body { font-size: 40px; } .time1 { display: inline-block; } .time1 { background: linear-gradient(to right, #a6ffcb, #1fa2ff); -webkit-background-clip: text; color: transparent; } .time2 { position: relative; color: #a6ffcb; } .time2:before { content: attr(time); position: absolute; z-index: 10; color: #1fa2ff; -webkit-mask: linear-gradient(to left, #1fa2ff, transparent); } </style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
<script> new Vue({ el: "#app", data: { time: new Date().toLocaleString(), arr: [ "奥术大师大所大所", "噶事发傻手法十分", "按时间大胜靠德德", "奥斯卡拉家带口拉丝机迪卡龙" ] }, methods: { updateTime() { // this.time = new Date().toLocaleString(); this.time = this.arr[Math.floor(Math.random() * this.arr.length)]; } }, mounted() { setInterval(this.updateTime, 1000); } }); </script>
</body>
</html>
复制代码
效果以下
发现确实,文字长度没变,第一个不会从新渲染,长度一旦发生改变,第一个才会改变渲染,而第二个一直在渲染
问题好像忽然找到缘由了,但我又无心发现新的问题
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style> body { font-size: 40px; } .time1 { display: inline-block; } .time1, .time3 { background: linear-gradient(to right, #a6ffcb, #1fa2ff); -webkit-background-clip: text; color: transparent; } .time2 { position: relative; color: #a6ffcb; } .time2:before { content: attr(time); position: absolute; z-index: 10; color: #1fa2ff; -webkit-mask: linear-gradient(to left, #1fa2ff, transparent); } </style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
<div>
<span class="time3">{{ time }}</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
<script> new Vue({ el: "#app", data: { msg: "Hello", time: new Date().toLocaleString() }, methods: { updateTime() { this.time = new Date().toLocaleString(); } }, mounted() { setInterval(this.updateTime, 1000); } }); </script>
</body>
</html>
复制代码
当我改变 dom 结构发现又好了
效果以下
好了 我完全呆了
最后我也没搞明白,但愿知道的大佬帮忙解答。
不过为了保险起见之后相似这种仍是用第二种渐变样式吧!