从 click 的三种不同写法开始

184 阅读3分钟

事情是这样的,之前实习小姑娘在学习前端,告诉我快被这么的疯了,她只想写一个 button 的 click 事件,但是,却有很多中不同写法,实在是记不住:

  • HTML 的 click 事件
<button onclick="myFunction()">Click me</button>
  • Angular 中的 click
<button (click)="myFunction()">Click me</button>
  • JSX 中的 click
<div onClick={this.myFunction}></div>

当然,你可以说,如果你了解了背后的原理,就不难记住在那种情况下该怎么用。

但是,不管是 JSX 还是各种框架的模版语言,都在创造新的方式和语法,让初学者很容易迷惑。我们似乎过于依赖某一种框架,而导致初学者无法离开框架,「自由」编程。

我们虽然曾经十分诟病的,jQuery。假设,你在维护一个老的项目,都是通过 jQuery 完成的,你完全可以很方便的在新功能中不用 jQuery 因为它是一个插件而非框架,但是对于一个框架而言,却很难,不是不行,很难。

有没有可能,我们继续使用 web 插件而非 web 框架?

Web 开发,长久以来都存在的无法避免的问题,比如:

  • HTTP 请求数的限制让我们不得不考虑把前端文件组合到一起,而非像后端代码一样按照逻辑拆分成不同的文件。
  • ES6 以前没有模块化,导致 JS 的代码柔和到一起。
  • 浏览器的差异使得我们必须借助 babel
  • 框架本省对于语法的修改,Vue 的 vue 文件,React 的 JSX 这一切的理由,让我们不得不借助于第三方工具 webpack 来对前端代码进行编译。让我们能够开发时可以分模块,可以使用 ES6,可以使用 .vue 或者 JSX。

但是付出的代价,就是 JS 需要编辑。对于一个解释型语言,需要编译,并且编译速度比大多数编译语言还慢,这是可耻的。有没有可能不使用 webpack,前端代码所见即所得。

得益于浏览器的支持,在一些,不考虑过多浏览器支持的条件下,其实我们可以尝试用更加「原生」的方式来写逻辑:

将 JS 的入口文件指定为 module,这样我们就不需要把所有的代码 bundle 到入口文件中了。

<script type="module" src='./main.js'></script>

浏览器会读懂import,并且按照相对路径转换为对应的 URL。比如说,main.js 中存在: import './src/index.js'; 它就会被转换为: http://localhost/src/index.js。 这样你只需要保证,所有的 JS 文件都按照它原来的文件路径被 host 在服务器上,就能保证他们能够在浏览器里正确的被请求。

其实这里有一个问题,就是 node_module 中的文件,因为我们实际上都是用 npm 来管理前端的第三方库,虽然 npm 代表着 node package manager。对于第三方库,我们都是:import xxx from xxxxYYY,因为 node 默认如果不是以 .或者/ 开头的话,就直接从 node_module中查找,这对于通过 webpack 编译的代码当然没有问题。但是,正常的非 . 或者 / 开头代表的其实是根目录。这里,本质上,是 node 设计上的一个 hack,Deno 中其实也修正了这一点。

解决方案也不外乎两点:

  • 参考 deno, 直接使用全路径。优点是我们可以甚至抛弃 npm,还可以与 deno 保持一致。缺点是,未必能有 npm 那么全的库。
  • 使用第三方库,将请求 proxy 到对应的 node_module 下面,有 es-dev-server 或者 snowpack。这可能是既可以不使用 webpack 又能正常在最新浏览器上开发最合适的方式了吧。

从长远来看,我更倾向于使用 deno 替代 node 作本地校验,全路径的开发方式更加「原生」,更加符合 web 的语法吧。