Vue与jQuery混用的数据共享(不使用Vue-cli)

Vue与jQuery混用的数据共享(不使用Vue-cli)

* 前言:本示例没有使用webpack,配置环境是参考廖雪峰廖大的node.js教程搭建。 *

* 环境:Node.js + Koa2 + nunjunks + Vue + jQuery 配置详情和教程可参考下面的链接 *
廖大教程链接

* 示例:一个在页面上使用基于jQuery的bootstrap-datetimepicker日期控件的实例 *

要点一:Vue与jQuery混用时的数值共享 - 利用 window

下面这个例子中包含一个页面初始化的函数,包含以下逻辑:

window.onload()中使用ajax从数据库读取树的值;在读取成功的回调过程中:

- 将数据重构并赋值给自定义Vue组件,一个Tree树;
- 将与DatePicker有关的jQuery方法添加到window.onload()方法中,以便使jQuery能在window的全局调用下工作。

这个逻辑,实际上就是让jQuery和Vue在Window对象下实现了平行工作。并且可以通过操作window的全局变量实现数据共享。

JS代码

window.onload = function() {
    var treeDataList = []
    $.getJSON('/api/divisions').done(function(data) {
        var divList = []
        divList = sortDivList(data.divList)
        console.log(JSON.stringify(divList))
        // 将获取的divs转换成树的结构 取得去重的WZ名
        uniqWZ = []
        bigBSNList = []
        for (var i in divList) {
            uniqWZ.push(divList[i].warZone)
        }
        uniqWZ = new Set(uniqWZ)
        uniqWZ = Array.from(uniqWZ)
        // 按照Tree的递归型数据结构将获取到的JSON重构
        for (var i = 0; i < uniqWZ.length; i++) {
            var tlist = []
            var tobj = {}
            for (var j = 0; j < divList.length; j++) {
                if (divList[j].warZone === uniqWZ[i]) {
                    var t = divList[j].branchSysName
                    tobj = {
                        name: t
                    }
                    tlist.push(tobj)
                }
            }
            var obj = {}
            obj.name = uniqWZ[i]
            obj.childs = tlist
            bigBSNList.push(obj)
        }
        // 将重构的JSON封装入符合Tree组件的对应props的list中
        var treeDataList = [{
            name: '单位名称', // 根级目录名字
            isOpen: true, // 是否初始展开目录
            hightLight: true, // 是否初始高亮
            className: undefined, // 添加自定义样式
            childs: bigBSNList
        }]
        // 回调中调用Vue根实例初始化方法
        activeVue(treeDataList)
        // jQuery混用的日历控件相关
        $('.form_datetime').datetimepicker({
            weekStart: 1,
            todayBtn: 1,
            autoclose: 1,
            todayHighlight: 1,
            startView: 2,
            forceParse: 0,
            showMeridian: 1
        })
        $("#date11").change(function(event) {
            // 这里实际是设置了window下的一个全局变量,并没有更改到vm里data中的selDate11变量。因为jQuery和$的平行关系所致
            window.Vue.selDate11 = $("#date11").val()
            console.log(window)
            console.log(this)
            console.log(Vue)
        })
    }).fail(function(jqXHR, textStatus) {
        alert('Error: ' + jqXHR.status)
    })
} 

分析

这段代码是上面代码片段的截图,我们在这里放了很多暴力调试用的log。

Vue与jQuery混用的数据共享(不使用Vue-cli)_第1张图片

从Chrome的页面“检查”console输出如下结果:

Vue与jQuery混用的数据共享(不使用Vue-cli)_第2张图片

进一步,打开 window 变量这一行,发现里面的变量是这样:

Vue与jQuery混用的数据共享(不使用Vue-cli)_第3张图片

可以看到我们刚写在 window.onload()方法中的activeVue()方法,也有我们刚赋值的 selDate11 了。(

从这里能清楚看到jQuery、Vue框架的平行关系:二者是没法直接调用对方变量实现互相传值的)

接下来,我们先随意指定一个页面上的按钮,让它来调用vm中的method,读取这个写入window的全局变量。

html代码

按钮调用的方法代码

其中,在Vue根实例vmmethods 方法中定义的setDate():

setDate: function () {
// 在这里才真正让vm实例读到了jQuery取得的值
this.selDate11 = Vue.selDate11
console.log("Gooooooood Date !!!" + this.selDate11)
}

这样就完成了数据共享!

扩展

上面的实例实现了 jQuery控件数据 -> Vue的vm根实例 逻辑

反过来,想让vm借助window进行jQuery操作的范例请参考笔记《学习 Bootstrap 网格系统因窗口大小变化导致按钮点击事件无效》


* 示例要点二:Vue与jQuery混用时的view动态刷新 *

Vue作者尤雨溪大神反复强调过最好不要将Vue和jQuery混用,因为这样做的两个直观问题是:

  1. 通过jQuery改变的数值只能使用window下的全局变量传递给Vue的vm实例
  2. jQuery对视图的改变无法直接通过vm更新(Vue读取的js原生事件,不响应jQuery封装的事件)

要想在这里实现Vue的刷新,需要使用domdispatchEvent()自己发送一个event,这个页面原生的event会被Vue框架捕捉到,进而实现刷新

(实验失败(:з」∠),目前仅记录过程,几个链接可供参考研究探讨)

参考一:传送门01
参考二:传送门02
参考三:传送门03
参考四:传送门04


要点一补充:jQuery中两种事件响应

// (一)第一种input事件响应
$("#input1").bind("input propertychange change",function(event){
this.dateText = $("#input1").val()
console.log('呵呵'+this.dateText) 
// 注意这里的this.dateText相当于是当前DOM!!!既不是Window也不是Vue!
// (二)另一种input事件响应,上面用的是`bind`,这里是`change`
$("#input1").change(function(event){
this.dateText = $("#input1").val()
});

要点二补充:(失败)

如果有个标签

input中的输入值用v-model绑定到了Vue上,想利用jQuery修改值并更Vue新视图的话,就要使用这种方法。但是这里实验不成功,是没理解dispatchEvent的正确用法。

$("#input1").dispatchEvent('input')

你可能感兴趣的:(前端)