[JavaScript]编写一份会动的简历

编写会动的简历

今天跟着方老师作了一个会动的简历,思路就是经过 JavaScript 代码,利用定时器每次同时在 HTML 和 CSS 中输入固定的字符达到实时代码预览的效果,其中用到了 prism.js 库给代码添加高亮,用了 marked.js 库把 markdown 转换成 HTML ,并在页面中展现出来。javascript

效果预览:Git Pagescss

代码连接:GitHubhtml

是否是看上去以为效果挺炫的~下面我就来整理一下这个项目的流程,思路以及踩过的坑。感受好长好多涉及的点要记...应该分几篇写仍是合成一篇?...算了先写着先吧。java


分别设置 HTML 和 CSS

先写个 demo,可让代码出如今页面上:git

输出

能够看到,咱们指定的字符串已经出如今页面上了,可是,出现了两个问题:github

1.页面背景色并无发生变化面试

2.输出字符串中的空格被压缩了npm

解决方法:markdown

1.固然没有啊,咱们只是把字符串写进 HTML 中,CSS 中仍是没有这些设置app

2.咱们使用 pre 包裹住字符串,让他的空格得以保留

修改一下:把字符串写入 HTML 中的同时,把字符串也写进 CSS 中;使用 pre 标签。

输出正确


使用 setInterval 和 substring 进行逐个字符输出

思路:使用 substring 获取字符串的某个部分,使用 setInterval 每次输入固定字符,并作判断,当获取的字符串下标超过字符串长度时,setInterval 中止。

输出成功


使用 prism.js 设置 CSS 高亮

因为 JSbin 不能上传文件,因此这里往下就不用 JSbin 演示了。

使用 prism.js 库给字体作高亮(没错,仍是使用 CRM 大法~):

1.下载 prism.js 的 CSS 和 JS 文件

2.引入文件到项目中

3.copy.run.modify

var result = `
body{
    background-color: red;
}
`
var n = 0
var timer = setInterval(()=>{
  n+=1
  code.innerHTML =  Prism.highlight(result.substring(0,n), Prism.languages.css)
  styleTag.innerHTML = result.substring(0,n)
  if(n>=result.length){
    window.clearInterval(timer)
  }
},100)

more style

给代码设置更多的样式,包括经过使用 animation 营造呼吸效果,调整代码框大小等等:

var result = `
/*
 * 面试官你好,我是XXX
 * 只用文字做作我介绍太单调了
 * 我就用代码来介绍吧
 * 首先准备一些样式
 *
*/
* {
    transition: all 1s;
}
html {
    font-size: 16px;
}
.code-wrapper {
    width: 50%;
    left: 0;
    position: fixed;
    height: 100%;
}
/* 调整一下代码框大小 */
#code {
    border:1px solid transparent;
    padding: 16px;
    overflow: hidden;
}
#code {
    left: 0;
    width: 100%;
    height:100%;
}
/* 让代码呼吸起来 */
#code{
  animation: breathe 1s infinite alternate-reverse;
}
/* 给代码加上一点点高亮 */
.token.comment {
    color: slategray;
}
.token.property {
    color: #f92672;
}
.token.selector {
    color: #a6e22e;
}
`

另外,设置代码高亮有一个小窍门,即咱们先设置一个 default.css,把高亮的 CSS 隐藏起来(放到 prism.css 后面),而后再经过 setInterval 把高亮代码设置回来,起到更好的视觉效果。


建立白板

左边是负责代码输出展现,右边是咱们最后要写入 Markdown 的地方,因此咱们要建立一个函数,建立一块白板出来:

function createPaper(fn){
    var paper = document.createElement('div')
    paper.id = "paper"
    var content = document.createElement('pre')
    content.className = "content"
    paper.appendChild(content)
    document.body.appendChild(paper)
    fn.call()
}

回调初现

在建立白板的时候,输入字符串的任务要停下来,以后再继续输入字符串的任务。

如今封装一下以前的函数:

function writeCode(prefix,code){
    let domCode = document.querySelector('#code')
    domCode.innerHTML = prefix || ''
    let n = 0
    let timer = setInterval(()=>{
        n = n+1
        domCode.innerHTML = Prism.highlight(prefix + code.substring(0,n), Prism.languages.css)

        //这句话的做用是:当代码在被输入到HTML中时,代码框的滚动条能一直保持在最下方
        domCode.scrollTop = domCode.scrollHeight
        styleTag.innerHTML = prefix + code.substring(0,n)
        if(n >= code.length){
            window.clearInterval(timer)
        }
    },20)
}

prefix 和 code 分别对应第一次须要输入的字符串和本次须要输入的字符串,若是没有 prefix,则以前的 innerHTML 则会被新的字符串取代,而不是连起来。

因此咱们这里的流程应该是:writeCode('',result) -> 添加白板 createPaper() -> 设置白板样式 -> 在白板添加 Markdown

那咱们这样写行不行呢:

writeCode('',result)
createPaper()
writeMarkdown()

很遗憾,这样是不行的,由于 writeCode() 中有 setInterval 计时器,因此他是一个异步函数,实际上流程就变成了这样:

添加白板 createPaper() ? writeCode('',result) ? 设置白板样式 ? 在白板添加 Markdown

下面先插播一下我对于 异步与回调 的理解。


异步与回调

  • 异步就是不等待结果的函数/事件

如:

function setTime(fn){
    setTimeout(()=>{
        console.log(2)
        fn.call()
    },1000)
}
function cb(){
    console.log(3)
}
setTime(cb)
console.log(1)

按照代码顺序原本是先执行 setTime(cb),再执行 console.log(1),但因为 setTime(cb) 是异步事件,不用等待他执行完成以后才执行后续代码,因此 console.log(1) 就先执行了,1S 后才执行setTime(cb) 的内容。

  • 回调是拿到异步结果的一种方式。
function setTime(fn){
    setTimeout(()=>{
        console.log(2)
        fn.call()
    },1000)
}
function cb(){
    console.log(‘异步任务执行完成,回调结束’)
}
setTime(cb)

如这段代码中,函数 cb() 就被当作 回调函数 传入 setTime() 中,当 setTime() 中的内容执行完以后,就执行函数 cb() 。

注意
同步事件/函数 也可使用回调


回到正题

因此咱们应该使用回调函数,在writeCode() 结束的时候执行 createPaper()

function writeCode(prefix,code,fn){
    let domCode = document.querySelector('#code')
    domCode.innerHTML = prefix || ''
    let n = 0
    let timer = setInterval(()=>{
        n = n+1
        domCode.innerHTML = Prism.highlight(prefix + code.substring(0,n), Prism.languages.css)
        domCode.scrollTop = domCode.scrollHeight
        styleTag.innerHTML = prefix + code.substring(0,n)
        if(n >= code.length){
            window.clearInterval(timer)
            fn.call()
        }
    },20)
}
writeCode('',result,()=>{
    createPaper()
})

输入 Markdown

由于所要输入的地方不一样,因此另写一个函数,输入 markdown:

function writeMarkdown(markdown,fn){
    let domMarkdown = document.querySelector('#paper .content')
    let n = 0
    let timer = setInterval(()=>{
        n = n+1
        domMarkdown.innerHTML = markdown.substring(0,n)
        domMarkdown.scrollTop = domMarkdown.scrollHeight
        if(n >= markdown.length){
            window.clearInterval(timer)
            fn.call()
        }
    },20)
}
var result4 = `
/* 还差一点点 */
.markdown-body {
    padding: 16px;
    background-color: white;
    overflow: auto;
}

/* Done~ 简历完成啦~ */
`
var md = `
# 简历
我的简历

...

`
// 实际上就变成了:
writeCode('',result,()=>{
    createPaper(()=>{
        writeMarkdown(md)
    })
})

最后把 Markdown 转换成 HTML

咱们选用了比较讨巧的方法:新建一个 div,而后把 div 的样式设置好(主要用了github-markdown-css),div 内容设置成通过 marked.js 库(怎么使用在此不赘述了)处理后的 HTML,最后用这个 div 替换掉以前的白板。

function convertMarkdownToHtml(fn){
    var div = document.createElement('div')  
    div.className = 'html markdown-body'
    div.innerHTML = marked(md)
    let markdownContainer = document.querySelector('#paper > .content')
    markdownContainer.style = 'background-color:white'
    markdownContainer.replaceWith(div)
    fn && fn.call()
}
// 实际上最后的流程就变成了:
writeCode('',result,()=>{
    createPaper(()=>{
        writeCode(result,result2,()=>{
            writeMarkdown(md,()=>{
                writeCode(result + result2,result3,()=>{
                    convertMarkdownToHtml(()=>{
                        writeCode(result + result2 + result3,result4,()=>{
                            console.log('Done')
                        })
                    })
                })
            })
        })
    })
})
// 哈哈,恐怖吧?传说中的回调地狱

总结

纵观整个项目下来,感受异步和回调不难,反而在 CSS 方面耗费了点时间...

行文不顺畅,这个..这个..这个我也在慢慢改进,我以前还在想着,是把作这个东西的整个流程都记录下来,仍是只挑其中比较重要的知识点,写着写着,仍是写下了含糊不清的这篇东西...不过也算是有所收获,多总结总结仍是不亏的~

相关文章
相关标签/搜索