用VUE一点一点改造jQuery项目(一)

      接触vue已经一段时间了,虽然框架的便利和特性让人眼馋,但还是迟迟没法应用到实际项目中,究其原因,主要是网上介绍vue实际应用的教程基本都是一整套全家桶压过来,如我一般知识不全面的小白很难一下子跨进去,最终往往在知识准备阶段就耗光了热情。所以,我打算从手头的旧项目着手,一点一点进行改造,一口吃不掉,那就小口慢咬,即所谓“蚕食”。过程中也会遇到一些小坎儿,我会把这期间的思路和考量写出来,希望能得到一些有营养的指点和交流。

       前置知识:对vue的基本指令有点儿了解即可。

1、项目简介

首先简单介绍一下要改造的项目,是个数据管理系统,涉及到大量的数据展示、修改提交等行为,与vue标榜的数据驱动还是很有契合点的。

1-1 项目概况

2、项目改造

因为第一个界面(左上角)目前正在调改,所以我以它作为改造对象。改造思路大致如下:

2-1 整改方案

实际操作时,我喜欢一个一个知识点去改,感觉这样更利于知识的吸收和个人成长,而且也基本不会影响在运行项目的正常使用,破坏的可能性最小。OK,从易到难走起~~

1)基本结构搭建

① 在页面中引入框架:<script src="../lib/vue.min.js"></script>

② 创建Vue实例:var vm = new Vue({el:"#VueApp",data:{},computed:{},methods:{}});

2)使用{{}}取代dom操作

繁杂的DOM操作(命名id、获取元素、操作元素...)一直是很多前端er的一个痛点,使用{{}}可以很大程度上缩减代码量,更有利于后期维护,更重要的是——不用再为命名id发愁了。{{}}的修改比较容易,我简单举个例子,比如修改右上方的“姓名、性别...”

① 在 vm > data 中设置PatientInfo:{PatientName:"",PatientSex:"",PatientBir:"",PatientCardId:""}

② 在 html 中使用 v-text 对绑定数据 <span v-text="PatientInfo.PatientName"></span>

对于①,在实际项目中,后端接口会直接返回一个对象,对象的内容即上方PatientInfo的内容,所以实际改造中,我是将PatientInfo设置为空对象(节省代码嘛);

对于②,之所以使用 v-text 而不是 {{}},首先当然是为了避免页面加载时空白时间过长,所以我不希望在Vue实例的根元素上使用 v-cloak,同时也不希望在页面中的分支节点上设置很多 v-cloak ,毕竟页面中的元素哪怕能早1-2秒展示都会让人更舒心,所以不到不得已,能避则避。

稍微复杂的修改,最多也只涉及到过滤器,以iframe中的“检查日期”为例,后端接口返回的日期是带着毫秒的(2017-08-20 16:23:12.175),这时可在 Vue 实例前创建个全局过滤器(因为其它页面也会用到所以先建个全局的)。

创建过滤器:Vue.filter("date",function(value){return value?value.split('.')[0]:''});

使用过滤器:<span>{{ NewResult.ClientTime | date }}<span>

值得注意的是 v-text 和 v-html 中不能使用过滤器,所以只能如上写在{{}}中,后续需要使用 v-cloak 优化一下用户体验。

3)使用v-model优化表单

自从 Angular 提出双向绑定开始,这个功能就几乎成为后续框架的必备(Vue中就是 v-model 了)。做这个调改时我还是比较兴奋的,因为可以减少大量的表单dom操作,同时在这个示例项目还别有一番好处。具体情况如下:

上图所示主展示区是个 iframe ,它左上角的第四个按钮的作用是“添加检查记录”(即表单的填写提交)。类似的页面目前有30多个(与上方的设备列表一一对应),每个表单的字段自然也各不相同(如图 3-1)。

之前 jQuery 的做法是为每个表单单独写一个提交函数,这代码量相当吓人。现在使用Vue,我的做法是让这n多的表单共用一个函数(前提是它们使用的接口相同,只是提交的参数有区别):

① 初始化页面时先在Vue实例中声明一个变量(JSON格式),它包含所有表单的字段及初始值(如图 3-2),同时深拷贝一个作为备份,用于提交表单后对表单内容进行重置;

② 将上述提到的变量中的表单字段与页面中的输入框绑定好,之后当用户填完表单时,借助 v-model 的双向绑定变量的值也相应会自动整理妥当。待要上传时直接通过序号从变量中调取相应表单的数据提交即可(如图 3-3)。

③ 至于数据校验,因为本项目中大多数表单内容为数字,所以主要使用 html5 自带的表单校验(如:min、max、step、required等),文本使用 v-model.trim 修饰符。当然还是有一些内容需要自定义规则校验的,这个就需要根据实际情况在调取到相关表单数据后做点小处理。

3-1 表单示例
3-2 初始化表单字段
3-3 表单数据的提交和重置

4)template/v-if组合

既然提到表单,就先说说表单弹窗吧。这里我主要考虑了这么几种方式:

① 最初表单只有不到10个,当时是全部放在外层页面内,每个表单单独有一个弹窗结构(虽然使用 bootstrap 会导致相关的 html 代码会比较多,但还可以忍受),但就目前的情况而言,这种方式会导致外层页面代码过肥。

② 将每个设备对应的表单弹窗代码放到各自的 iframe 页面中,待用户切换到该设备下时,再将表单弹窗从iframe中拿到外层页面中,这种方式我使用了一段时间,但心理上觉得这样取来取去的挺不安心的。

③ 现在我是将所有弹窗还放在外层页面,然后因为每个表单头尾相同,且表单中都有“姓名、日期”条目,所以将他们放在一个弹窗结构中,使用 “template、v-if、v-else-if”(如<template v-if="CurrentEnumId==1">)来包裹切换中间不同的部分。代码量压缩了20K,但是还是很肥(70K),后来也相关把弹窗做成组件从页面中分离出去,不过因为时间关系暂且这样了。

在使用 template 时有一点需要注意:当在 table 中使用 template 标签时,IE浏览器是不认的,针对这个问题,我考虑以后将弹窗内容较多的几个块做成组件,然后用 <tr is="xxx"> 引入,不过目前还在思考寻觅其它解决方案。

4-1 弹窗结构

5)用组件优化重复的代码块

从图1-1和2-1中可以看到,不同页面调用了某些相同的区块,这些区块都很适合做成组件,此处我以“图片上传预览”为例(在多个表单中都有如图3-1的图片上传预览功能)。这里我先结合组件所需功能说说思路:

① 初始时,组件显示如图3-1所示灰色色块,当点击色块时触发选择图片窗口,选中图片并确定后,图片自动上传到后台并返回图片地址(提交表单时要用),接着再去除灰色色块展示图片,这时当鼠标hover图片时灰色色块半透明显示(因为上面要展示点文字信息)。

② 允许拖拽上传。

从上述功能中可以梳理出所需的变量如下:ImgSrc(图片地址)、labelStyle(灰色色块的状态)、ShowImg(控制图片的显示,只有在加载正确时才显示)、ImgStyle(控制图片的样式,确保图片无论是横条还是竖条都能水平垂直居中)、drag(用来存储拖拽的文件信息,以便在多个函数间共享)

至于要接收的参数和输出的参数,可根据实际情况而定,我这里只设置了从外层接收数据,“输出”直接修改了实例的数据。建议还是使用 $emit 触发实例中的方法。

5-1 图片上传预览组件

值得注意的是:使用组件时最好使用 <div is="xxx"> 的方式,而不要使用自定义的标签名,因为在IE下可能报错“无效标签”。

目前已经按照图2-1所示的思路完成修改,测试时尚未发现什么大问题。除上述指令和方法外,其它涉及到的常用但简单的指令还有:v-for、v-show、v-on、v-bind等。

请多多指导,谢谢(未完待续...)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容