vue使用之剑走偏锋——菜单组件篇

背景

习惯了这样的写法了,上来先来一个背景,交待一下事情的起因。事情的起因很简单,用惯了mvc框架,想来一发前后端完全分离的框架试试。选用的人员和技术是这样子的,让原本做java的web开发的人员使用vue,在visual studio code里面写纯前端的代码,然后由.net的同事,提示webapi2的接口。关于这个设计中的权限验证等问题,会单独一篇笔记进行介绍。

这里要说的是,由于前后端分离,导致没有了后台的java模板或者.net的razor之类的视图引擎。没有了这种东西会很尴尬,因为需要用ajax来获取数据,获取到数据之后呢,用jquery的选择器选择dom然后一个个填充,提交的时候再用jquery的选择器选择dom取其值——。这样子的话,估计我要被同事们骂死……。为了邻里和谐,我觉得vue比较流行,而且它的mvvm据说速度不错,试用了一下,觉得简单方便条条框框少,毕竟我只是要用它的mvvm功能,只是为了把对象与dom绑定,把事件相绑定。

单面(SPA) vs 多页

这个是我比较头疼的问题,其实个人比较倾向单面应用,因为直观上觉得虽然第一次要加载的东西比较多,但是,由于浏览器有缓存以及做好载入界面,用户其实是容易接受的。而多页面每次都要加载许多东西,虽然也有缓存,但是许多对象都需要初始化,直觉上就知道总的性能不如单页应用。然后我就开始搭建vue的spa了,用了vue的webpack模板,搭建出来的项目如下:

由于使用的工具是vscode,所以,输入命令,调用bower,npm等还是比较爽的,而且可以直接开发了。但是,我发现,我想使用的是一个开源的基于bootstrap的后台管理系统模板,这个模板相互依赖特别多,我理了半天,没理清楚,更别说把它做成vue的组件化了。没过多久,我就放弃了这条我其实比较喜欢的路。

放弃了spa,选择了多页,但是,多页又带来了另外一个问题,就是是用iframe将菜单、导航等独立在外以便共用,还是每个页面都带一个菜单、导航。

iframe VS 纯多页

公司的项目一直都是在使用iframe,但是,这次的项目有个明确的要求,就是要自适应布局,要能在手机上无缝转换,这个,就是我很不放心iframe,我试着将iframe放在bootstrap自适应的布局中,确实也可以很好的进行工作,但是,总觉得有一天它无故导致出现滚动条,无故导致某些东西展示不全。同时,它还有一个致命的问题,就是模态弹窗只能遮住iframe,而非整个浏览器页面,这就很头疼。这样用户的操作流程就是开放性的了,很难摸清楚用户的实际操作流程,会导致什么意外的情况发生。

所以,最后,只能用纯多页的了。

纯多页的前端

纯多页其实也存在一个问题,就是上面所说的,共用区域在每个页面里面都要写一次,其实,头部导航、左边菜单,还是很烦的,加上没有后台帮助渲染,前端的代码少不了。所以,我自己写了一个方法,用来将其它的html页面加载至当前界面的当前位置,其实类似于include。

function HtmlInclude(url) {
    var req = false;

    // Safari, Firefox, 及其他非微软浏览器
    if (window.XMLHttpRequest) {
        try {
            req = new XMLHttpRequest();
        } catch (e) {
            req = false;
        }
    } else if (window.ActiveXObject) {

        // For Internet Explorer on Windows
        try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                req = false;
            }
        }
    }
    if (req) {
        // 同步请求,等待收到全部内容
        req.open('GET', url, false);
        req.send(null);
        document.write(req.responseText);
    } else {
        document.write("对不起,你的浏览器不支持" +
            "XMLHTTPRequest 对象。这个网页的显示要求" +
            "Internet Explorer 5 以上版本, " +
            "或 Firefox 或 Safari 浏览器,也可能会有其他可兼容的浏览器存在。");
    }
}

调用的方法如下:

这样,在

<script>
        HtmlInclude("snip/menu_left.html");
      </script>

的位置,最终就会变成"snip/menu_left.html"中的代码,简单完美!但是,在后面的调试过程中发现,浏览器中根本无法调试"snip/menu_left.html"中的代码,这就很尴尬了~~~

vue组件的剑走偏锋

vue的组件化提供了相当牛逼的特性,但是,对于单文件的支持非常地不行,只能在webpack等“编译”功能的前提下,才可以使用.vue文件之类的组件单文件模式。但是,公司内部其实连html,css,javascript是非常模糊,让一下子跃过html,css,js直接去用webpack编译,估计不仅调试起来让人崩溃,甚至连开始都开始不了。所以,咱们还是从实际出发,以html为骨骼,以css为皮肉, 以javascript为筋脉。

查阅了一下,vue提供了另外两个模式的方式,其一是内联模板,这种内联模板其实是让组件的调用者给予组件的template内容,这相当于在每个页面里面都要把对应的组件的模板写一遍,与我们的需求不符。其二便是X-Templates,这个东西与我们需要的功能类似。它将template内容单独写成html格式的js文件,然后可以通过<script type='text/x-template' src='' id''>去加载,在之后再加载与之对应的组件js文件,并在组件的template处写上面那个x-template标签中的id。这下又尴尬了,每个组件的引用必须引用两个文件,而且还分先后,并且,引用模板的js文件时,需要特殊指定type,同时,因为是js文件,编辑器对html提示功能就瞎了。所以,vue内置的这两种模式并不适合我。

我的方案

可能是经历的原因,我觉得,我的任何项目里面都要有jquery,虽然vue提供了ajax的请求插件,但是,我依然觉得有必须引用一下jquery,有了它,我才有安全感,客户的各种奇葩需求,我心中才有底,不然今天动画,明天校验的,我能给愁死。

于是,我做了另外一个打算,既然

Vue.component('my-component', {
  template: ""
});

我给template这个对象字符串,而我又想给它的是html页面,那么我用jquery请求就是喽,如下:

Vue.component('my-component', {
  template: $.getSync("templates/com1.html")
});

这样子的话,我只需要在templates文件夹中增加这个com1.html,供vue使用即可。这个$.getSync是我实现的一个jquery的扩展方法,因为jquery的同步请求只有$.ajax中才有,而且还是要通过回调,$.get方法是异步的,除非设置全局同步,全局同步会影响其它的功能代码,所以,万船无奈自己用$.ajax封装了一个$.getSync方法。

jQuery.extend({
      getSync:function(url){
        var result=null;
        $.ajax({
          url:url,
          async:false,
          success:function(data){
            result=data;
          }
        });
        return result;
      }
    });
原文地址:https://www.cnblogs.com/ensleep/p/7259907.html