1. 树靶:从入门到精通?
伴随着计算机技术的发展,我们总是能听到或看到《n天从入门到精通》系列丛书,精通一词总能给人带来一阵兴奋,好像找到了武功秘籍,练后就登峰造极。
但这多半只是换来脑中一热,只是精通招式,还是不能为我所用创造出令自己满意的效果。
这篇文章必然不属于该系列,”一天”这个限制并不想蒙蔽读者,而只是为了创造一个极限条件,时间有限不能全部照顾到,逼迫我们去思考什么才是最重要的。
打蛇打七寸,当真屡试不爽。但是每个人都有自己的学习方式,并不一定对所有人都有效。不以为然者尽可以把这当作另一种思路借鉴。
下面我们就来看看,一天时间,能把哪些重要的东西学到手。
2. 探路:我眼中的vuejs是怎样的?
首先,我要做些铺垫,来说明一下我眼中的vuejs是个什么工具,用以解决什么问题。
计算机语言发展史,在我看来就是一个抽象层次不断升级的历史。
最开始的面向过程编程,比如c语言,实际上是将功能逻辑封闭到了函数,是对过程的抽象。这是第一层。
但是过程虽然做了抽象,数据却还是游离在代码中,面向对象编程即是再将数据跟逻辑一起封装为一个整体,即对象。这是第二层。
这两者都是代码层面,复用程度也还是有限。于是出现了一些第三方模块,复用程度较面向对象又高了一个层次。这是第三层。
再上一层就涉及到具体功能设计了,比如django的contrib.admin,即是django将整个功能以插件方式使用的极好例子,这些代码已可以完整提供功能模块了。这是第四层。
当然,上面还有更高明的设计,IaaS、SaaS、PaaS更是提供了整个运行时的能力,直接申请运行时即可使用,简单方便,程度又高了一层。这是第五层。
vuejs的设计介于第三层和第四层之间,虽说提供了某种层次的抽象,类似第三方模块,但是它更提供了抽象的解决方案。这正是它跟jQuery这类 js库 的差别所在。
更具体得说,vuejs实现了一个叫做component的前端复用粒度,并提供了一整套框架来使component足够灵活以满足绝大多数需求。
我们下面便来看一下vuejs中的component是如何达到抽象复用的。
3. 观详:vuejs中的component设计
这里的标题是component设计,而不是”component如何编写”,如何编写并不十分重要,我们想要知道的是,它是怎么设计来满足我们目标的。
为什么是它满足我们的目标而不是我们去学习它的使用?因为我们的思考是第一位的,否则很容易在这纷繁的世界中迷失,人云易云。
那我们就先设计一个框架,让vuejs实现这个框架(奇怪,竟然是vuejs来贴合我们的思考,而不是我们去学习了)。
那我们现在就来思考,如何设计一个可以复用的component,满足我们复用的需求。
。。。
经过了几分钟的思考,我认为一个可复用的组件,要满足以下几个条件:
- 属性:我们可以利用属性来定义一个组件的外观,或者交互方式
- 输出:component不光好看(或不好看),可能还能输出某种状态或数据,比如一个获取输入的组件,我们需要从组件中获取输入的内容
- 控制:component需要提供一些对外接口,以便我们对它进行控制
- 感知:有时component需要主动将自己的内部状态通知出来。跟被动控制不同的是,感知是component主动通知外部的行为
现在,我们只需要拿着这份药方去vuejs抓药就可以了。下面是我们找到的药品的位置:
- 属性:vuejs中明显地提供了属性的定义及访问方式,component中使用
props
来指定其支持哪些属性,使用方可以通过:prop="config.prop"
传入属性 - 输出:输出的实现有些技巧,后面我们专列一个小节来说明
- 控制:想要控制某个component,必先获取它对应的句柄(与之对应的某个变量)。vuejs为组件的使用提供了一个
ref
属性,可通过this.refs
变量引用到,直接调用其函数 - 感知:主动通知的实现方式,一般为信号(linux进程)和事件(js),但本质是相同的,都是底层提供一种通信方式。vuejs提供了
$emit()
函数,用以向component使用方发送通知
4. 试剑:不跑起来不算验收通过
上面的实现描述不够直观,还是要看到代码才能更清楚明白。下面我们就创建一个项目来验证上面的设计。
这里我们先编写一个简单的用例,一个用以显示文本的component,同时可通过一个api来修改字体大小。
我们先安装vue命令行工具,并用其创建一个脚手架项目:
1 | npm install -g @vue/cli |
然后我们创建一个component,该component可定义显示一行文本,可通过一个属性来设置文本颜色。同时,我们提供两个接口以供使用方调整字体大小。
先看使用方的代码:
1 | <!-- src/App.vue --> |
下面是component的定义:
1 | <!-- src/components/Label.vue --> |
5. 转锋:同步数据给父component
上面的组件已可以很好的工作了,但是它并没有覆盖到我们上面给出的四个条件,我对比了一下,缺少 输出
和 感知
两个条件,这两个条件实现的技术实际是同一个。
vuejs提供了一种通信方式,可以向父component发送数据,原型为 $emit( eventName, […args] )
,eventName为事件名,是一个字符串,可为该事件提供参数 args。
如果我们是直接看vuejs的官方教程,官方指出v-model可以实现数据的双向绑定(数据显示<=>数据变量这两个方向)。官方也给出了v-model背后的诀窍:
你可以用 v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
text 和 textarea 元素使用 value property 和 input 事件;
下面的代码更直白一些:
1 | <input type="text" v-model="data"> |
即是如此,我们便可以通过包装一个input,并给上层上送input事件来通知上层更新数据了。下面是一个片段:
1 | <!--父component--> |
当然,框架里还提供了一个model属性,可以修改v-model绑定的属性(这里默认为value)和事件(这里默认为input)。这算是个彩蛋了。
如果要更细致的使用,还需要了解一下生命周期的概念,不过这对于使用来说并不是最核心最要紧的。
6. 回首:再来看n天精通系列
我相信n天精通是存在的,但是这不是必然的。比起精通,能够产生有实际价值的产品,才是更令人兴奋的。
所以,n天能精通也罢,不能精通也罢,并不是那么重要。
网上看到一个朋友的说法,我觉得说得挺好:工具是帮助我们解决问题的,而不是让人成为大牛的。
精通和有效,必然有先后。我觉得大可先让学习有效,真正到了一定程度,自然便精通了。
有了上面的学习,我们就可以触类旁通,继续学习相关知识,一边学习、一边享受学习的成果,不也是一件很快乐的事吗?