杂谈 Web 前端编程范式

1,430 阅读5分钟

前言

放假在家的时间里稍微研究了一下 Polymer,这算是第一次正式体验 Web Components 技术了。它给我我的第一印象很好,开发体验很不错,我觉得前端开发就应该是这样。所以这篇文章我就随便谈谈我对前端几种技术的看法。

近年来前端技术应该算是爆发式地增长,从 Node.js 开始,前端似乎像是被玩坏了,各种框架,各种开发模式……很多人甚至羞于谈 jQuery,他们认为一个前端项目不使用 React、Angular 都不算搞开发。在接触 Polymer 之前,所有前端框架中,我最喜欢的是 React,它一方面不像 Angular 那样做到一站式的“捆绑销售”,让我能对技术栈有自己的选择;另一方面,Virtual DOM 的引入使得其渲染性能相比其他框架确实有很大的提升。

以 React 为代表的 Functional Programming

虽然 React 官方并没有强制开发者使用函数式范式来做开发,但不管是从实际应用还是 React 的低层实现来讲,函数式是 React 的最佳食用方法,React 是典型的数据驱动视图,就拿下面的例子来讲:

const Greeting = (props) => {
  return (
    <div>
      <h1>Hello, {props.name}</h1>
    </div>
  );
}

React 的每个组件说白了就是一个函数,从参数中获取数据,一级一级完成全部的渲染,有的复杂一些的组件可能会有自己的 state,不过如果项目中使用了 Redux 等 FLUX 模式的库,state 也可以完全省略。但从根本上,React 就是做了一件高效地将数据转换为视图这样的工作,视图就是数据的一种体现。包括 Facebook 官方推荐使用 Immutable.js 来管理数据,目的就是辅助 React 更高效的渲染,通过 Immutable 的幂等检测来决定究竟 DOM 树中的哪些节点需要被重新渲染。同时 Immutable 也是函数式的重要基础,每次操作都会产生一个新的、完全独立的 state 对象,用这个 state 来渲染 DOM 树,并且还能轻松获得 Undo-Redo 和时间旅行的功能加成。Redux 作为状态管理的一种解决方案,很好地协调了 Action、Store、Reducer 之间的关系,很多人问 Redux 到底是什么,它其实就是一个函数:

function Redux(initialState, reducer) {
  var store = { state: initialState };
  store.dispatch = (action) => {
    store.state = reducer(store.state, action);
    // notify subscribers...
  }
  return store;
}

你的任务就是确保 state 的不可变性就可以了,reducer 每次必须要产生一个不同的 state 对象,刚才提到的 Immutable.js 是一种途径,ES6 也有很好的语法糖可以做到这一点。

讲起来 ClojureScript 更适合这种开发模式:

(defn lister [items]
  [:ul
   (for [item items]
     ^{:key item} [:li "Item " item])])

(defn lister-user []
  [:div
   "Here is a list:"
   [lister (range 3)]])

语言自身的特性使得我们也不用为对象的 Immutability 而烦恼。

但是用函数式的观点去构建用户界面我一直不太赞同,随着项目的不断扩大,应用状态的管理就会愈发困难,并不是所有人都只需要把应用做到一个 Todo List 那么简单,很多庞大的系统,应用状态都十分的分散,集中起来用函数去解决实在不能称为上策。况且,用户界面中有很多控件可能会有一些很复杂的状态,这些控件的状态又怎么去管理呢?除了 OO,我很难想到其他更好的办法。

Web Components 解决了什么问题?

Web Components 是 W3C 官方正在实行的标准,具有更广泛的使用前景,也许将来所有的浏览器都可以不使用任何 polyfill 就能享受完整的 Web Components 支持。

所以它到底给我们带来了什么?我认为它是前端组件化的最好的体现形式,以自定义标签为载体,开发者可以将常用的功能或视图封装为一个新的标签,得益于 Shadow DOM 的支持,自定义标签内外可以做到互不干扰。最重要的是,自定义标签真正具有自己的属性、方法,你可以真的像在操作一个对象一样去操作这个标签,去控制其状态,让它执行相应的操作,而不用像 React 那样,通过改变状态去触发组件的行为变化。熟悉 Native 开发的童鞋也应该知道,Native 的组件其实就是一个个类实例化的对象,它们有属性,有方法,可以响应事件等等,通过 Web Components,在前端中也可以做到这一点。

举个简单的例子,Polymer 的 Paper 元素类别中有一个 paper-listbox 元素,具体效果可以看这个 Demo,它就具有一系列方法,比如你可以对它执行 select 方法,来做到选中列表中的一项,你也可以响应它所发出的一系列事件,非常地符合直觉。

更多的 Polymer 元素可以看这个 Gallery。谷歌官方实现了很多实用的组件,诸如 Ajax、Form、Input Validator 还有一些 Material Design 的控件,直接拿来用很方便。

Polymer 同时支持双向绑定,我认为一些轻量级的数据,通过 Polymer 的数据绑定机制就足够了,自定义标签不限于 DOM 元素,你也可以只封装 CSS,或者只封装逻辑,将 Model 封装成一个标签也是完全可以的,然后通过数据绑定,将 Model 标签的数据和响应的 View 绑定在一起,这样,我们就可以用 OO 的方式操作 Model 标签,数据的变化就能立刻反应在 View 上,十分地优雅。

当然了,Polymer 目前也还处于开发过程中,生产环境是否适合我也并不清楚,毕竟不是做前端的,但是业余拿来研究我认为它还是非常有前景的,我也十分期待 Web Components 正式成为所有浏览器的标准后,Web 前端将是一个怎样的美好景象。