热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

Vue全家桶实践项目总结(推荐)

从前端的角度看,Vue可以说是目前最理想的前端MVVM框架,一切为界面服务,上手难度低,本文就将记录使用Vue全家桶(Vue+Vue-rou

从前端的角度看,Vue可以说是目前最理想的前端MVVM框架,一切为界面服务,上手难度低,本文就将记录使用Vue全家桶(Vue+Vue-router+Vuex)重构一个jQuery+template项目的过程,以及期间的收获。

入门

Vue的官方文档就是学习Vue的最佳教程,没有之一,可能因为框架作者是设计出身,没有后端背景,因此各种抽象概念在Vue里都得以用最容易理解的方式被恰到好处的阐述,这里只简单介绍Vue、Vue-router、Vuex的概念,要全面学习建议去官方文档。

Vue

Vue的核心功能是双向绑定,可以自动实现界面驱动数据变化和数据驱动界面变化,这能极大降低前端富交互应用的开发成本。同类框架不止Vue一个,但Vue的实现借助ES5原生特性,在性能方面有一定优势。

Vue-router

Vue-router是官方路由,用来组织url和组件间的映射关系,并自动将url的变化响应到组件中去,使开发者只需将关注点放在组件开发上,路由帮你解决相关的琐碎问题。

Vuex

Vuex提供一种集中式的数据管理模式,用以应对数据流向复杂的情况,比如多个组件共用数据却各自为营,可能导致该同步的数据没有同步,或者由于js中Object对象的钩子在内存里指向同一实例,导致一旦操作原数据就会污染到其他组件,这时就需要一套更有条理的数据操作模式,那就是Vuex。

技术选型

跟jQuery对比

在了解了Vue的基本概念之后,肯定会不自觉的拿他们跟jQuery技术栈做对比,想知道这些东西对我的业务是否真的有必要。

首先MVVM解决的问题能不能用jQuery解决?答案是肯定的,还记得最初做表单提交时用jQuery从一个一个的input里取值吗?这就是界面驱动数据;如果做过任何异步交互功能的话,应该都有过用jQuery将Ajax数据填充到界面中各个元素里的经验,这就是数据驱动界面。虽然能做,但有点繁琐,即便用上表单验证插件和前端模板引擎,也仍然需要在各个运行节点手动调用验证方法和渲染方法,做个网站页面还好,可当需求复杂到一定程度时,这将是很大的负担。

然后是路由,路由的本质是通过操作url实现界面切换和界面保持,单页面应用必备,这个其实跟技术栈没关系,只要产生了路由需求,即使是基于jQuery的项目也不过是再造了一个路由而已,只不过jQuery时代很少做单页面应用。

Vuex完全是基于双向绑定延伸出来的东西,相当于在数据和组件之间加了一个经纪人,组件不能直接操作数据,只能像经纪人提交操作需求,由经纪人去实施操作,以此解决人多手杂造成的各种不可预料的问题,并且数据被从应用中挪了出去,专门建立了一个Store,这样就杜绝了组件之间数据污染的问题。jQuery应该说不太会有这个需求,因为jQuery完全是手动操作数据,根本没有意料之外的情况。

适用场景

经过跟jQuery的对比之后,Vue的适用场景就很明显了,从开发角度讲交互越复杂的项目越适合,单页面最适合,内容类网站最不适合,如果网站中个别页面有需求也可以局部使用,例如购物车页面。

当然,这一切都要建立在不兼容IE8的前提下,对于这一点我有点疑惑,因为见到有些2C的站点都在使用Vue,这些前端er是怎么把老板忽悠瘸的?

项目分析

项目背景

这次重构的项目是为上一家公司开发的前端组件管理系统,选择重构这个项目是因为对需求比较熟悉,这是一个典型的单页面应用,而且复杂度适中,比较适合用作上手练习。

项目背景是外包类建站公司里,设计环节沉淀了大量可复用组件,设计师往往只需要微调组件就拼凑出页面,交付给前端,理论上这些组件在前端也可以复用,但实际上前端每次都要重新实现整个页面,浪费很多人力。

功能需求

这个项目的思路是,将所有组件开发出来,统一录入到一个平台上管理,设计师可以到平台上挑选组件,并实时预览和调整组件,整个过程所见即所得,平台会将调整结果生成一串代码,只要将代码交给前端,就可以用这串代码在平台上重现设计师修改后的组件,并能一键复制组件的html/css/js代码,快速应用到项目中去,使组件部分的前端开发成本接近于零。平台需要实现以下几个功能:

  1. 管理组件,支持分类、搜索、排序
  2. 展示组件,支持组件在线预览/编辑
  3. 组件交接,支持生成组件代码和基于代码重现组件
  4. 使用统计,支持统计组件的使用情况,便于进一步优化组件

功能分析

第一版是用jQuery+template实现的,这个技术栈太灵活了,优点是什么需求都好做,缺点是怎么做都行,不利于理清思路,往往伴随着边做边改。

组件被统一放在一个widgets/文件夹里,被称作组件库,因为是纯前端项目没有文件操作能力,因此组件的读取依赖一个静态json文件,这个文件充当组件库的目录,其中包括组件分类、标签、名称、日期等所有信息,数据结构大概是这样:

[{
 "title": "导航类",
 "list": [{
 "widget": "bread-1",
 "title": "图标面包屑",
 "tag": "面包屑/图标",
 "author": "UI",
 "date": "2015-06-04"
 }, 
 ...]
},
...]

组件在组件库中以栏目/编号二级文件夹的形式存放,同时约定用存放目录作为组件代号,例如组件bread-1意味着该组件存放地址是widgets/bread/1/文件夹。

当然组件的内部文件结构也必须约定下来,如下:

widgets
  |-bread
    |-1
      |-album.jpg   //缩略图
      |-config.json  //配置文件
      |-script.js   //脚本模板
      |-style.css   //样式模板
      `-temp.htm   //界面模板

有了这些约定,程序就可以通过目录文件得到所有组件的信息,组件的获取、展示、检索也就可以实现了。

组件里最关键的是config.json文件,这里面包含该组件的可配置项及其默认值,平台在展示组件时会读取这个配置文件,根据配置信息生成配置面板,这里面可以定义组件界面、样式、脚本中的所有变量,配置文件大概长这样:

{
 "cssConfig": {
 "fontSize": {
  "name": "字号",
  "value": "12px",
  "type": "text"
 },
 ...
 },
 "jsConfig": {
    ...
 },
 "showConfig": {
 "viewWidth": {
  "name": "栅格宽度",
  "value": 12,
  "type": "number"
 },
 ...
 }
}

配置文件里的cssConfig、showConfig、jsConfig三个分支,就是组件中所有可以修改的变量集合,想将这些变量应用到组件上,需要借助前端模板引擎,所以组件的三大件在开发的时候是用模板语法写的,经过模板引擎的解析,就能得到配置后的实际html/css/js内容,例如样式模板大概是这样的:

.widget-bread-1 {
  font-size: ${fontSize.value}; 
  color: ${textColor.value}; 
}
.widget-bread-1 a { 
  color: ${textColor.value};
}
.widget-bread-1 a:hover{
  color:${hoverColor.value};
}
.widget-bread-1 .ion { 
  font-size: ${iconSize.value}; 
  margin: 0 ${iconMargin.value};
}

在得到组件实际代码后,只要将结果插入页面中并适时更新就行了,其中HTML和css可以直接替换文本内容,js因为是模块化引入的,只替换模块内容不会重载模块,必须将整个模块重命名后进行整体替换,因此js模块的名称是随机的。

这里会有一个问题,有的组件需要在页面里多次使用,那么这个组件的js选择器就会发生冲突,这个问题的解决正好可以借助js模块的那个随机名称,我们约定在组件开发中id作为保留变量,由平台自动赋值一个随机字符串,这个字符串在组件实例内部相同,多次调用则不同,这样只要将${id}作为组件父节点的id或class,就解决了选择器冲突问题,同时也可以作为组件的css命名空间,使可能发生的css命名冲突也解决于无形。

以上是项目核心功能。

此外还用localStorage作为存储方式实现了单机版的数据统计,可以收集当前浏览器的组件使用记录,以及每个使用时的配置情况,这里主要是对本地存储的操作,但是项目自身的开发也用到了前端模板,加上组件的模板,都会在第一次加载后用localStorage缓存起来,这些内容的缓存策略不同,用户数据应该是永久存储,项目模板应该可以手动更新,组件模板需要视情况而定,存储的内容多了就需要清理,清理的时候一条一条的去删除就不现实了,全部删除可能误伤其他应用的存储,这里的做法是将localStorage操作封装,存储方法会在在key前加上一个特殊前缀,删除时只要遍历本地存储的key并且判断是否匹配前缀就知道是否是应用内的存储了,对应的取值方法也要逆向的先给key加上前缀再去取值。

另外localStorage是只支持字符串存取的,为了方便我们存取对象类型,封装方法还支持自动转换,但这个转换还不能是盲目的遇到对象就转字符,取值的时候匹配到可以转对象就自动转了对象,因为有时候用户可能真的就存了一个对象字符串进去,取出的时候也希望原样拿回来,要解决这个问题需要做一个小hack,当存储方法检测到值为对象时,会转成字符串然后在前面拼上一个标识字符串,取值方法只有在检测到这个标识后才会将后面的字符串还原成对象,这种方式虽然可以满足需求,但不是很保险,因为这个前缀是固定的,理论上总是有可能遇到中奖的,不知道这个问题还有没有其他的更优解。

项目的主要功能点就是这些。

重构

一次重构

第一次重构只用了Vue,重构过程中首先体会到的是各种便捷,本来要调用模板引擎做的事框架顺便就做了,本来要在js里绑定事件现在模板里直接可以绑定,还有其他各种语法糖。

当然,最重要的还是双向绑定,基于双向绑定可以让界面和数据自动的关联起来,让人感觉程序具有了一定的自主能动性,但为了让这种自主性正常运转,开发者必须事先规划好每一步路,这相对jQuery来说就会显得不那么自由。拿搬砖头举例,jQuery好比一个特别灵活的起重机,可以举重若轻,可以花式搬砖;Vue则像一个万能遥控器,你告诉他你要把砖头从某地搬到某地,期间发生什么情况要如何处理,按动按钮就可以自动搬砖了。

两种方式各有优劣,起重机开的好可以很灵活,路上遇到坑容易躲避,缺点是你要一趟一趟的开它;按钮可以一次编程自动运行,缺点是你必须事先把路上的坑实地考察好,把别的车全部调度好,所有的情况说清楚,否则就会翻车或撞车,从jQuery转到Vue一定会感觉到这种束缚感,逼的你必须”谋而后动”,不能先上车再说。

重构期间很大一部分工作就是建立Vue实例,将散布在js各个角落的数据收集到data中去,将操作数据的过程一点一点的集中到methods中去,将数据的筛选过程集中到computed中去,这整个过程可以清晰的回顾每一个实现细节,反思每一个实现方式是不是合理,其实也就是将原来开起重机的过程归纳成一个一个的遥控器按钮,当全部归纳完成后,Vue示例也就变成了最终我们的项目,能够自动运行。

经过重构,依托Vue的各种功能使逻辑部分的代码量减少了,除此之外对项目本身来说并没有什么改进,因为没有路由所以刷新页面状态丢失问题仍然存在;因为没有使用Vuex还遇到一个数据污染的坑,只能用深拷贝解决;并且基于组件的开发模式,让代码组织更零碎了,这些问题都需要二次重构。

二次重构

二次重构目标是完善路由、Vuex、代码组织、野狗云后端。

虽然有了第一次重构的经验,但二次重构一开始还是有点茫然,路由和Vuex应该先上哪一个?想了想,路由做的事是”拆”,Vuex做的事是”改”,感觉改完再拆的工作量会小一点,所以先上Vuex。

Vuex的概念凭空理解有点抽象,一旦用上却觉得的得心应手,而且这个东西不像路由,几乎不需要区分场景都可以用,引入Vuex后数据污染的问题自然就解决了,而且Vuex带来的 action => mutation => store 流程一旦接受了真的会让事情变简单,引入Vuex的过程基本就是将data转移到store,将数据操作分散到actions,getters,mutations中去,同时很多同步数据操作都不需要了,从而使代码量又减少了一些。

之后开始引入路由,一开始拿不准应该怎么划分视图,大的视图肯定是登录、注册、主界面,问题是主界面需不需要再细分,理论上可以分的很细,但结合应用实际使用场景发现,界面的切换相对频繁,组件频繁载入和卸载的开销会很大,而且将耦合紧密的组件拆到不同的视图,需要记录很多状态信息,有点得不偿失,最终作罢,没有将主视图继续分下去。考虑到三个视图的访问重叠性不高,自然就需要将组件做成异步加载,只在访问到的时候才加载组件,Vue自身支持异步组件,所以这件事变得非常简单,只要能返回一个Promise,你可以使用任意方式获取组件。

接下来要接入野狗云,实现真正的用户管理和数据统计,野狗云可以提供用户鉴权和数据存储等一系列功能,通过它只需要用js就可以开发一个完整的WEB应用。这样之前所有对localStorage的操作都要改成对野狗云的操作,数据到了云端也变得更可靠了。

至此二次重构就完成了,业务代码总体感觉减少了很多,但总代码量估计没少多少,毕竟还增加了三个框架文件,不过经过重重拆分,文件数量从当初的三两个js变成了十来个js,模块化方面用的seajs而不是webpack,因为个人对 webpack仍然持观望态度,目前还感觉不到用它的必要性,关键是基于webpack开发的代码会夹杂很多私货,让你的代码变得不原生,离了他就运行不起来,这个我不太能接受,而且在多页面场景seajs配合本地缓存比webpack更有优势,当然了,他们的的区别就跟jQuery和Vue的区别一样,本质不是一个东西,关键在于使用场景,适合的就是最好的。

后记

经过两次重构的实践和踩坑,对Vue框架有了更深刻的认识,Vue想要用的灵活自如,对开发者的项目架构能力有一个最低要求,如果要将Vue引入底层,对基础设施建设者的规划能力也有一个最低要求,这些都是jQuery技术栈所不存在的,使用Vue的过程也是接受这些约束的过程,他们能引导开发者建立自己的规则体系,这是好事也是大势所趋,毕竟真正的自由只存在于规则中。

本文的完整代码见Github。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 本文介绍了DataTables插件的官方网站以及其基本特点和使用方法,包括分页处理、数据过滤、数据排序、数据类型检测、列宽度自动适应、CSS定制样式、隐藏列等功能。同时还介绍了其易用性、可扩展性和灵活性,以及国际化和动态创建表格的功能。此外,还提供了参数初始化和延迟加载的示例代码。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了解决IE678伪类不兼容问题的方法,包括少用CSS3和HTML5独有的属性,使用CSS hacker,使用last-child清除浮动、批量添加标签、去掉list item最后一个的border-right等技巧。同时还介绍了使用after清除浮动时加上IE独有属性zoom:1的处理方法。另外,本文还提到可以使用jQuery代替批量添加标签的功能,以及使用负边距和CSS2选择器element+element去掉list item最后一个的border-right的方法。 ... [详细]
  • 本文介绍了使用jQuery实现图片预加载和等比例缩放的方法,同时提供了演示和相关代码。该方法可以重置图片的宽度和高度,并使图片在水平和垂直方向上居中显示。 ... [详细]
  • 获取ul中第一个li元素的五种方法和多个ul中第一个li元素的四种方法
    本文介绍了获取ul中第一个li元素的五种方法和多个ul中第一个li元素的四种方法,包括使用jQuery的选择器和遍历方法。通过这些方法,可以方便地获取到所需的元素,并进行相应的操作。 ... [详细]
  • 如何压缩网站页面以减少页面加载时间
    本文介绍了影响网站打开时间的两个因素,即网页加载速度和网站页面大小。重点讲解了如何通过压缩网站页面来减少页面加载时间。具体包括图片压缩、Javascript压缩、CSS压缩和HTML压缩等方法,并推荐了相应的压缩工具。此外,还提到了一款Google Chrome插件——网页加载速度分析工具Speed Tracer。 ... [详细]
  • mui框架offcanvas侧滑超出部分隐藏无法滚动如何解决
    web前端|js教程off-canvas,部分,超出web前端-js教程mui框架中off-canvas侧滑的一个缺点就是无法出现滚动条,因为它主要用途是设置类似于qq界面的那种格 ... [详细]
author-avatar
智慧与财富的拥有者_678
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有