为什么需要指令
这其实是一直困扰很多人包括我在内的一个问题。为什么我们有了组件还要指令呢?为什么Vue中有指令而React就没有呢?
要回答这个问题,其实并不容易。最近看到大漠的一个视频为什么需要指令,他是这么回答的:因为指令可以拓展HTML的功能(在Angular中)。我认为他说的观点没错误,但是其实没有抓住最根本的原因,拓展HTML的功能只是表面现象。
比如我可以继续问:难道我不能通过组件,或者直接操作VDOM来拓展HTML功能么?另外为什么React中没有指令,难道React就不需要拓展HTML功能么?
如果你也有这些疑问,那么请带着这些疑问继续阅读本文。
Vue vs React
先说我的结论:根本原因是Vue是数据驱动,而React是函数式编程。
这里我们从一个例子来看,比如我们要遍历输出一组用户的名字。
在Vue中是这样实现的:
<li v-for="(user, index) in users">{{user.name}}</li>
而在 React 中我们是这么实现的:
const userItems = users.map((user) => {
return <li>{user.name}</li>
})
我们会发现,React 可以通过map函数很好的实现一个列表的遍历,而Vue中不用 v-for 指令就会很麻烦。根本原因是React和Vue不同的设计理念,决定了对DOM的操作方式的差异。
在 Vue 中,我们一般不会直接操作DOM(当然你愿意的话可以这么做),而是通过把当前组件的一个Context,一般包含 data, props, methods,在模板中我们其实是和这个Context交互的。这个Context本质就是一个数据,因此我们如何把数据渲染到HTML上呢?我们需要指令来把上下文的数据渲染到DOM上。(注:并不是说Vue中真的有context这个东西,只是一个概念)
而在React中完全是另一种实现,React直接在JS代码中混入了HTML(VDOM)代码,因此我们直接用JS操作VDOM,而不需要一个上下文作为中间的媒介,因此也不需要用指令来渲染VDOM。所以,React并不需要指令。
我们如果把一个组件,分为 JS 部分和 VDOM 部分,那么我可以画一张图来说明异同。
如上图所示,可以很清楚的看到Vue和React设计上的差异,以及指令存在的地方。
指令优点与缺点
上面我们解释了为什么Vue中需要指令。那么,指令的存在到底有什么优缺点呢?
我认为,指令存在的一个明显的优点是,可以把对DOM的一些通过逻辑进行封装,从而使代码逻辑更加规范。即,组件只负责处理数据,而指令负责处理DOM。
但是对于部分人来说,指令的存在会污染 HTML 代码,他们希望保持HTML的纯净,而把所有的逻辑都通过组件的方式来组织。
单说指令的优缺点其实意义不大,更多的应该说Vue的数据驱动和React的函数式编程的优缺点。这是一个仁者见仁智者见智的问题,不在这篇文章里面做过多的阐述,我这里只简单说下我的看法。
我本人对Vue更加熟悉,理解也更加透彻,绝大部分项目也是Vue写的,可以参见我的github仓库中的一些Vue项目,所以绝不存在贬低Vue的任何动机。但是其实从设计理念上来说,我更喜欢的是React的函数式编程而不是Vue的数据驱动。
我认为 Vue 通过指令来渲染模板,远不如React通过函数来渲染来的优雅。在Vue中,模板其实单纯从语法上说是一个大的字符串,无论是原生的HTML还是里面指令数据。而在React中,他们都是语法上的JS对象。字符串其实没有语法,而JS代码是有规范的语法的,也更容易进行语法检查。
由于Vue中的模板是个字符串,所以里面的写法其实更多是一种约定, 比如 v-bind v-on 等都是一种约定, 或者说是Vue自己发明的一种语法。而 React 中 绝大部分都是原生的JS语法。显然,我们更应该使用JS语法而不是自己去发明一种新的语法。
以上就是我对指令,以及Vue和React的异同的一些看法。