前言

首先,向大家说声抱歉。由于之前的井底之蛙,误认为Vue.js还远没有覆盖到二三线城市的互联网小厂里。现在我错了,从我司的前端技术选型之路便可见端倪。以太原为例,已经有不少公司陆续开始采用Vue.js作为他们公司前端的技术栈,前后端分离正搞得热火朝天,还有更多的公司正在来时的路上。所以说,还在校的童鞋和仍在培训的萌新们,Vue已经成为现在前端的标配技能之一,为防止掉队,跟着闰土大叔学起来吧。

接下来,正文从这开始~

先来了解下当前的行业背景:

随着SPA、前后端分离的技术架构在业界越来越流行,前端的业务复杂度也越来越高,导致前端开发者需要管理的内容,承担的职责越来越多,这一切,使得业界对前端开发方案的思考多了很多,以react、vue等框架为代表推动的组件化开发模式越来越被开发者认可,这种模式极大的降低了我们开发与维护的成本。

最近一段时间,我也在研究Vue,在网上看了那么多基于Vue的组件,何不自己也来造个小轮子,有了这个想法后,撸子袖子就是干。本文提供代码仅仅是提供而已,重要的是思路。

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>用Vue造个组件轮子吧-闰土大叔</title>
 </head>
 <body>
     <div id="app">
         <input-number v-model="value" :max="20" :min="0"></input-number>
     </div>
 <script src="js/vue.js"></script>
 <script>
 function isValueNumber(value){
     return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value + '');
 }

 Vue.component('input-number', {
     template:`
                  <div class="input-number">
                      <input type="text" 
                   :value="currentValue"
                   @change="handleChange"
                   ref="input"
                   @keydown="show($event)"/> <button @click="handleDown" :disabled="currentValue <= min">-</button> <button @click="handleUp" :disabled="currentValue >= max">+</button> </div> `, props:{ max:{ type:Number, default:Infinity }, min:{ type:Number, default:-Infinity }, value:{ type:Number, default:0 }, step:{ type:Number, default:5 } }, data: function(){ return { currentValue: this.value } }, watch:{ currentValue:function(val){ this.$emit('input',val); }, value:function(val){ this.updateValue(val); } }, methods:{ handleDown: function(){ if(this.currentValue <= this.min) return; this.currentValue -= this.step; }, handleUp: function(){ if(this.currentValue >= this.max) return; this.currentValue += this.step; }, updateValue:function(val){ if(val > this.max) val = this.max; if(val < this.min) val = this.min; this.currentValue = val; }, handleChange:function(event){ var val = event.target.value.trim(); var max = this.max; var min = this.min; if(isValueNumber(val)){ val = Number(val); this.currentValue = val; if(val > max){ this.currentValue = max; }else if(val < min){ this.currentValue = min; } }else{ event.target.value = this.currentValue; } }, show:function(ev){ console.log(ev.keyCode) if(ev.keyCode == 38){ this.handleUp(); }else if(ev.keyCode == 40){ this.handleDown(); } } }, mounted:function(){ this.updateValue(this.value); this.$refs['input'].focus(); } }) var app = new Vue({ el:'#app', data:{ value:5 } }) </script> </body> </html>

如果你掌握了Vue的组件知识,相关的指令、事件,花点时间你也可以造出这么个入门级的小轮子。如果这篇文章只是单纯的贴出组件轮子代码那也太easy了。接下来,抛出造轮子实践背后带来的一些思考。

第一问:

vue 已经挂载的组件怎么初始化里面的data?

能问出这个问题的童鞋,说明你已经迷上了Vue。按照源码里讲的,vue将数据绑定到组件的原理分为三个步骤: 当实例化一个Vue构造函数,会执行 Vue 的 init 方法,在 init 方法中主要执行三部分内容,一是初始化环境变量,二是处理 Vue 组件数据,三是解析挂载组件。以上三部分内容构成了 Vue 的整个执行过程。

第二问:

vue 注册组件为什么要必须发生在根实例初始化前?

可能你已经熟读Vue官方API文档,但是这个问题你考虑过么。如果在Vue根实例初始化之后才注册组件会发生什么?如果你有兴趣,我可以等你实践30秒再说我的想法。

30秒时间到了,在等你的时候,我又实践了一遍。是的,报错了。大意是,未知的自定义元素:<input-number> - 你是否正确注册了组件?对于递归组件,请确保提供name选项。

我曾翻阅过官网API文档,也曾阅览过相关的书籍,但里面都是简单的提了一句:

这个问题无解么,不是的。其实你仔细想想报错信息,你应该会泯然一笑,说的通俗点,这就像坐高铁,买了票才能上。因为实例化的时候会尝试找这个组件,你不提前注册就找不到了。如果硬要深究,只能去看源码了。

第三问:

这个数字输入框组件网上很常见,在此基础上你有做什么扩展么?

是的,与网上的数字输入框组件不同的,我做了两个扩展。

第一个扩展:input框自动获取焦点,在输入框聚焦时,监听键盘上下按键的操作,相当于加1或者减1。

实现的思路,在input输入框上定义一个ref为input引用,然后在模板渲染完毕之后,在mounted钩子里,通过$refs查找到对应的ID:input,然后focus。获取完焦点之后,接下来就是如何监听键盘上下按键的操作。首先,我们通过keydown事件绑定一个show()方法,里面传一个$event参数,然后在子组件的methods选项内创建一个show方法。我们都知道,键盘上的上键对应的keyCode码是38,下键对应的是40。 有了这个之后,我们做一个条件判断(上加下减),如果event的keyCode码为38,就调用handleUp()方法,如果是40,就调用handleDown()方法。至此,监听键盘上下键的按下进而操作input数值的扩展完成。

第二个扩展:给组件增加一个控制步伐的prop——step,比如设置为10,点击加号按钮,一次增加10。

继续说说我的思路,这个就相对来说比较简单了,首先在props选项内定义一个step对象,类型设置为Number,默认值设置为5。然后将methods里面的handleDown和handleUp里面将 this.currentValue +/-= (具体的数值)替换为 this.step。相当于进一步封装了它的可用性。至此,所有扩展完成。

后记

自己曾经求职面试前端,因不会Vue框架而被淘汰,而且不止一次,也曾因此赋闲半年在家。所以,事不过三,我要抓紧时间学会它,以及它的全家桶。有原则有危机感的人,往往都是之前吃过大亏的人。他们知道犯错误的代价,所以不敢触碰这个红线。愿我走过的路踩过的坑,你们不会再踩一遍,才会哭着鼻子记住这个教训。以铜为镜,可以正衣冠;以人为镜,可以明得失。在之后的日子里,我还会继续更新vue相关的文章,愿我们都做一个爱思考的孩子。前端路上,we are not alone。

用Vue自己造个组件轮子,以及实践背后带来的思考的更多相关文章

  1. vue.js组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...

  2. vue组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了一下的内容.首先会对使用Vue进行开发的一些前期需要的技术储备进行简单 ...

  3. Vue.js——60分钟组件快速入门(上篇)

    组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HTML ...

  4. Vue.js——60分钟组件快速入门(下篇)

    概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开 ...

  5. 转: Vue.js——60分钟组件快速入门(上篇)

    转自: http://www.cnblogs.com/keepfool/p/5625583.html Vue.js——60分钟组件快速入门(上篇)   组件简介 组件系统是Vue.js其中一个重要的概 ...

  6. Vue.js学习 Item11 – 组件与组件间的通信

    什么是组件? 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有 ...

  7. vue实现简单表格组件

    本来想这一周做一个关于vuex的总结的,但是由于朋友反应说还不知道如何用vue去写一个组件,所以在此写写一篇文章来说明下如何去写vue页面或者组件.vue的核心思想就是组件,什么是组件呢?按照我的理解 ...

  8. 浅谈Vue不同场景下组件间的数据交流

    浅谈Vue不同场景下组件间的数据“交流”   Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...

  9. vue.js学习之组件(下篇)

    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星! https://github.com/zwl-jasmine95/Vue_test 以下所有知 ...

随机推荐

  1. Express4.x API (二):Request (译)

    写在前面 最近学习express想要系统的过一遍API,www.expressjs.com是express英文官网(进入www.epxressjs.com.cn发现也是只有前几句话是中文呀~~),所以 ...

  2. CSS clear 清除浮动,兼容各浏览器

    .clear:after{content:".";display:block;height:0;clear:both;visibility:hidden;} .clear{zoom ...

  3. google protocol buffer的原理和使用(四)

    有个电子商务的系统(如果用C++实现).当中的模块A须要发送大量的订单信息给模块B.通讯的方式使用socket. 如果订单包含例如以下属性: ----------------------------- ...

  4. 关于系统首页绘制问题(ext布局+c#后台加入数据)经html输出流输出响应client

    关于系统首页绘制问题,业务需求 TODO 绘制系统首页(Main.aspx) 採用的技术:functioncharts+jquery+ext布局+c#+html 解说篇:1,服务端aspx,2,服务端 ...

  5. 【蓝牙低功耗BLE】控制GPIO来点亮LED

    这节讲一下最简单的,也是最基础的东西.CC2540的IO操作,把PORT口当做GPIO来用,废话不多说,往下看. 1.硬件电路 硬件电路时最简单的,用一根GPIO去控制LED灯.因为GPIO作为out ...

  6. check the manual that corresponds to your MySQL server version for the right syntax处理方案

    check the manual that corresponds to your MySQL server version for the right syntax:代码出现这样的bug,就要注意你 ...

  7. navicat创建存储过程、触发器和使用游标

    创建存储过程和触发器 1.建表 首先先建两张表(users表和number表),具体设计如下图: 2.存储过程 写一个存储过程,往users表中插入数据,创建过程如下: 代码如下: BEGIN #Ro ...

  8. .NET 实现DES加密解密处理

    .NET 实现DES加密解密处理 using System; using System.Text; using System.Security.Cryptography; using System.I ...

  9. git 设置和取消代理

    # 设置ss git config --global http.proxy 'socks5://127.0.0.1:1080' git config --global https.proxy 'soc ...

  10. 【批处理】IF ERRORLEVER语句顺序注意

    @echo off dir d:\dddddd if errorlevel 1 goto 1 if errorlevel 0 goto 0 rem 两行if语句不可交换位置,否则失败了也会显示成功. ...