在网上看到一个这样的网站,STRML 它的效果看着十分有趣,如下图所示:
这个网站是用 react.js 来写的,于是,我就想着用 vue.js 也来写一版,开始撸代码。
首先要分析打字的原理实现,假设我们定义一个字符串 str ,它等于一长串注释加 CSS 代码,并且我们看到,当 css 代码写完一个分号的时候,它写的样式就会生效。我们知道要想让一段 CSS 代码在页面生效,只需要将其放在一对 <style> 标签对中即可。比如:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width"> <title>JS Bin</title> </head> <body> 红色字体 <style> body{ color:#f00; } </style> </body> </html>
你可以狠狠点击此处 查看效果。
当看到打字效果的时候,我们不难想到,这是要使用 间歇调用(定时函数:setInterval()) 或 超时调用(延迟函数:setTimeout()) 加 递归 去模拟实现 间歇调用 。一个包含一长串代码的字符串,它是一个个截取出来,然后分别写入页面中,在这里,我们需要用到字符串的截取方法,如 slice(),substr(),substring() 等,选择用哪个截取看个人,不过需要注意它们之间的区别。好了,让我们来实现一个简单的这样打字的效果,如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width"> <title>JS Bin</title> </head> <body> <div></div> <script> var r = document.getElementById('result'); var c = 0; var code = 'body{background-color:#f00;color:#fff};' var timer = setInterval(function(){ c++; r.innerHTML = code.substr(0,c); if(c >= code.length){ clearTimeout(timer); } },50) </script> </body> </html>
你可以狠狠点击此处查看效果。好的,让我们来分析一下以上代码的原理,首先放一个用于包含代码显示的标签,然后定义一个包含代码的字符串,接着定义一个初始值为 0 的变量,为什么要定义这样一个变量呢?我们从实际效果中看到,它是一个字一个字的写入到页面中的。初始值是没有一个字符的,所以,我们就从第 0 个开始写入, c 一个字一个字的加,然后不停的截取字符串,最后渲染到标签的内容当中去,当 c 的值大于等于了字符串的长度之后,我们需要清除定时器。定时函数看着有些不太好,让我们用超时调用结合递归来实现。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width"> <title>JS Bin</title> </head> <body> <div></div> <script> var r = document.getElementById('result'); var c = 0; var code = 'body{background-color:#f00;color:#fff};'; var timer; function write(){ c++; r.innerHTML = code.substr(0,c); if(c >= code.length && timer){ clearTimeout(timer) }else{ setTimeout(write,50); } } write(); </script> </body> </html>
你可以狠狠点击此处 查看效果。
好了,到此为止,算是实现了第一步,让我们继续,接下来,我们要让代码保持空白和缩进,这可以使用 <pre> 标签来实现,但其实我们还可以使用css代码的 white-space 属性来让一个普通的 div 标签保持这样的效果,为什么要这样做呢,因为我们还要实现一个功能,就是编辑它里面的代码,可以让它生效。更改一下代码,如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width"> <title>JS Bin</title> <style> #result{ white-space:pre-wrap; oveflow:auto; } </style> </head> <body> <div></div> <script> var r = document.getElementById('result'); var c = 0; var code = ` body{ background-color:#f00; color:#fff; } ` var timer; function write(){ c++; r.innerHTML = code.substr(0,c); if(c >= code.length && timer){ clearTimeout(timer) }else{ setTimeout(write,50); } } write(); </script> </body> </html>
你可以狠狠点击此处 查看效果。
接下来,我们还要让样式生效,这很简单,将代码在 style 标签中写一次即可,请看:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width"> <title>JS Bin</title> <style> #result{ white-space:pre-wrap; overflow:auto; } </style> </head> <body> <div></div> <style></style> <script> var r = document.getElementById('result'), t = document.getElementById('myStyle'); var c = 0; var code = ` body{ background-color:#f00; color:#fff; } `; var timer; function write(){ c++; r.innerHTML = code.substr(0,c); t.innerHTML = code.substr(0,c); if(c >= code.length){ clearTimeout(timer); }else{ setTimeout(write,50); } } write(); </script> </body> </html>
你可以狠狠点击此处 查看效果。
我们看到代码还会有高亮效果,这可以用正则表达式来实现,比如以下一个 demo :