我用Vanilla JS重写了一遍项目,结果……

964

背景

上次听Dan大师的Live嘛,然后其中他提到怎么提高自己的技术,使用原生JS做东西,比如游戏之类的,那我不玩游戏,就很奇葩地想到用原生JS重写一下我的一个项目……然后我整个人就不好了😅

构思

如果要开启一个新的项目,那么准备阶段要做些啥呢?可能是要想想实现哪些功能了,我现在主要目的是练习JS以及代码设计,那么对于浏览器兼容,如何打包这些话题没有在我考虑的范围内,那我一开始能想到的如下List,如果有后续的补充,再慢慢添加(当然我并没有做完!😔):

  • multiple env
  • local open index.html file and nginx proxy for dev/prod
  • layout
  • with flex css
  • fetch to communicate with server side
  • router
  • toggle left navigation
  • menus on the left navigation
  • etc

学习

我虽然有自己大概的一个想法,但也想看看别人是如何使用纯JS来做一个应用的,有的人就真的是标题党,看着是Venila JS,内容却用了bootstrap, jQuery等等的工具。找了一些,但基本上都是非常简单的小项目,从创建main.js和index.html开始,没有一个系统的工程的例子,还是得靠自己摸索。

搭建

因为是纯JS,所以搭建起来比较容易,可参考一下步骤:

  1. 创建一个index.html文件,用于写静态页面;
  2. 创建一个main.js文件,用来写JS代码,并引入到已创建好的index.html文件中;
  3. 全局安装live-server,用于hot reload页面;
  4. OK,到这里基本就搭建完成,那么第一步我想到的是先做一个布局,包括navigator、header和content三个部分,并且navigator支持收缩。

Layout

想看下效果吧:

venilla-js.gif

其实是一个非常简单的布局,闭着眼睛都能实现的那种,看下我的代码片段:

<div id='root'>
    <nav class="left">
      <div class="logo"><i class="fab fa-vine"></i></div>
      <div class="menu">
        <script src="../components/menu.js" type="module"></script>
      </div>
    </nav>
    <div class="right">
      <header class="header">
        <img src="../assets/dedent.svg" alt="dedent" class="dedent-icon" />
        <div class="user">user</div>
      </header>
      <main id="content" class="content"></main>
    </div>
  </div>

由于用到的font-icon图标,需要在header里面引入响应的cdn链接。从这一小段代码里面我学到了哪些呢:

  • svg通过网络请求和inline的方式还不大一样,我在inline的时候可以正常显示svg,但是抽出去用使用网络加载就无法显示,是因为xmlns属性,需要赋值 xmlns="http://www.w3.org/2000/svg",因为svg需要被解析为svg+xml格式。

  • 原生css是可以使用变量的,在设置颜色的时候,总会重复地设置,以前总以为变量是Less或Sass的特有的,原来原生也可以直接使用,全局样式变量的声明,@import之后便可以使用了:

    :root {
      --nav-bg: rgb(69, 72, 73);
    }
    
  • css 中的&符号是Sass/Less的高级语法,原生css不能用。

  • 想用import/export嘛,在script标签中加入type="module"就好啦。

  • 另外我学到的很有意思的知识是原生的classList有toggle这样一个方法,帮助我们很好地添加元素的类,具体的使用场景是上面navigation里面的箭头图标,我使用了transform来旋转图标,那如何将有transform的类动态地添加到元素上面呢:

      let div = document.querySelector('#content');
      div.classList.toggle('visible');
    

    对了,就这个toggle方法很方便地解决了旋转的问题。

Router

路由的实现基本上是使用了history这个方法,核心代码如下:

const onNavigate = pathname => {
  const contentDiv = document.getElementById('content');
  window.history.pushState(
    {},
    pathname,
    window.location.origin + pathname
  )
  contentDiv.innerHTML = routes[pathname]
}

简单来说,就是将路由对应的页面嵌入到id为content的div(在index.html)中。

实现了路由之后,我已经要放弃了,太繁琐了,全部的功能都要手动撸出来,要说收获嘛,那肯定是有的,readme里面解释了我的一些笔记以、源码和相关参考资料。感兴趣的前往这里👉:github.com/fayeah/veni…

感谢大家阅读,欢迎交流😃。