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


    编写会动的简历

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

    效果预览:Git Pages

    代码链接:GitHub

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


    分别设置 HTML 和 CSS

    先写个 demo,可以让代码出现在页面上:

    输出

    可以看到,我们指定的字符串已经出现在页面上了,但是,出现了两个问题:

    1.页面背景色并没有发生变化

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

    解决方法:

    1.当然没有啊,我们只是把字符串写进 HTML 中,CSS 中还是没有这些设置

    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 {
         50%;
        left: 0;
        position: fixed;
        height: 100%;
    }
    /* 调整一下代码框大小 */
    #code {
        border:1px solid transparent;
        padding: 16px;
        overflow: hidden;
    }
    #code {
        left: 0;
         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 方面耗费了点时间...

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

  • 相关阅读:
    内容收缩伸展
    分页浏览的导航栏Bootstrap和js两种方法
    Bootstrap-缩略图
    Bootstrap-进度条
    Bootstrap-点击“×”,可以关闭页面
    Bootstrap页头
    Bootstrap分页
    Bootstrap--面包屑路径导航
    Bootstrap--标签和徽章<新闻后面的new hot等>
    NSLog 去除上线版本
  • 原文地址:https://www.cnblogs.com/No-harm/p/9707182.html
Copyright © 2020-2023  润新知