vue2组件之select2调用的示例代码


Posted in Javascript onOctober 12, 2017

目前,项目中使用了纯前端的静态项目+RESTFul接口的模式。为了更好的对数据进行操作,前端使用了vue2的mvvm功能,但是由于不是单页面应用,所以,并没有涉及到其它的如vue-route等功能,也未使用webpack等编译功能,所以,也没有使用.vue文件功能。这时候,如果用到控件,则多数从原jquery的组件中选择。

select下拉搜索选择

这次的需求调研与设计是原来做winform开发的同事,由于用惯了devexpress这个控件库,所以,对于searchlookupeditor这个控件情有独钟,所以,在设计的时候,许多地方都用到。

最初实现

最初,我使用了select2绑定select标签,设定其change事件 ,在事件中修改对应的vue的data值,同时,在vue中设定watch``data中被绑定的属性,属性值发生变化,则修改对应的dom的val,然后再触发select2的change事件。当然,这种对应关系,我在select标签上放了一个data-vuep来保存其与vue属性的对应关系,并放在全局的select2vue和dom2vue中。

//mounted中的部分代码
            select2vue = {};
          $("select").each(function (index, item) {
            var s2 = $(item).select2({
              language: "zh-CN", //设置 提示语言
              width: "100%", //设置下拉框的宽度
              theme: "classic",
              placeholder: "请选择"
            }).on("change", function (e) {
              console.log(e);
              var v = $(e.target).val();
              var p = $(e.target).attr("data-vuep");
              eval("vue_cust_busi." + p + "='" + v + "';");
              //$(e.target).find("option").attr("selected",false);
              //$(e.target).find("option[value='"+v+"']").attr("selected",true);
            });

            var p = $(item).attr("data-vuep");
            select2vue[p] = s2;
            dom2vue[p] = item;
          });
          setTimeout(function(){
            vue_cust_busi.editor.ID_CUST="3";
            vue_cust_busi.editor.NAME_CUST="*有限责任公司";
            console.log("修改");
          },10,null);


//watch中的部分代码
          "temp.P1": function (val) {
            fire(arguments.callee.name.toString(), val);

          },
//通用函数

    function fire(p, val) {
      $(dom2vue[p]).val(val);
      select2vue[p].trigger("change");
    }

//html

                        <select data-vuep="editor.P1" class="form-control "> 
                            <option value="" ></option>  
                            <option v-for="yearOpt in yearOpts" v-bind:value="yearOpt">{{yearOpt}}</option> 
                        </select>

为什么要用一个data-vuep来将数据与vue的属性关联呢,因为我发现,select2初始化了这个select标签之后,修改这个标签的值无法触发修改vue对应的v-model的属性。所以,只能用这个方法。
 最终形成的结果是:

select2到vue.editor.P1:
1.select2被选择某一项,触发其change事件。
2.select2的change事件修改vue.editor.P1的值。
3.vue.editor.P1的值被修改,触发watch,watch又引发select2的change事件,但是,select2内部监控到选择和之前的一致,所以,不再执行change事件的委托。

上面这种流程一定程度是实现了数据的双向绑定,但是,非常复杂。在后续的使用中发现,在mounted中无法为select2默认值,必须在mounted中调用setTimeout生成一个定时执行的事件来执行数据绑定操作,才会触发上述流程,达到设定触始值的效果。

使用vue指令

经过一番挣扎,觉得上面这种方式还是不行。

上述方案不好的原因如下:

1.vue事件中的代码操作了dom,这样,在生命周期上可能会出现问题,特别是后来使用了setTimeout之后,生命周期变得更加不可控制。
2.每增加一个select组件,都需要增加 html标签、watch,而且,html 标签和watch既不是传统的写法,也不是vue的写法,而是发明了一种新的东西,这破坏了开发体验。
3.维护性比较差,当想删除一个select的时候,必须要去watch里面去找与html中data-vuep相等的属性监控方法,并将其删除掉。
4.兼容性不好,本方案选择将页面所有的select全部用select2初始化了一次,使得不论是否需要的,都会被影响;其次,如果不统一初始化,那么又多出了在mounted中为每一个select写初始化代码的工作,同时,也要为每个select取一个id。

为了解决这个问题,我又找到了最初看到的那个vue使用指令和select2的整合的例子。网上有好多,我不知道版权是谁的,姑且上我最先看到的那个吧。https://3water.com/article/125654.htm

原文中的代码如下:

<!DOCTYPE html>
<html>
<head>
  <title>vue select2 封装</title>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="external nofollow" rel="stylesheet" />
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
  <style type="text/css">
    .content{
      text-align: center;
      padding:50px;
    }
    .content *{
      text-align: left;
    }
    .select{
      width: 350px;
    }
  </style>
</head>
<body>
  <div class="content" id="vue-example">
    <select class="select" v-select2='options' v-model="selectValue"></select>
    <br/>
    <span>结果:{{ selectValue }}</span>
  </div>
</body>
<script type="text/javascript">
  Vue.directive('select2', {
   inserted: function (el, binding, vnode) {
     let options = binding.value || {};
 
    $(el).select2(options).on("select2:select", (e) => {
     // v-model looks for
     // - an event named "change"
     // - a value with property path "$event.target.value"
       el.dispatchEvent(new Event('change', { target: e.target })); //说好的双向绑定,竟然不安套路
    });
   },
   update: function(el, binding, vnode) {
    $(el).trigger("change");
   }
  });
 
  var vueApp = new Vue({
   el: "#vue-example",
   data: {
    selectValue: '你还没有选值',
    options: {
      data: [
          { id: 0, text: 'enhancement' },
        { id: 1, text: 'bug' },
        { id: 2, text: 'duplicate' },
        { id: 3, text: 'invalid' },
        { id: 4, text: 'wontfix' }
      ]
    }
   }
  });
</script>
</html>

作者也说了,对vue2.x的双向绑定机制不了解,希望路过的大神帮帮忙。

我不是vue2的大神,甚至连新手都不算,只能说是初学者。我对代码进行了调整,当然,也是操作了dom,但是由于封装在指令里面了,使用人员不需要再次操作,不涉及到开发人员操作dom的情况,我还是可以接受的。

Vue.directive('select2', {
      inserted: function (el, binding, vnode) {
        let options = binding.value || {};

        $(el).select2(options).on("select2:select", (e) => {
          // v-model looks for
          // - an event named "change"
          // - a value with property path "$event.target.value"
          el.dispatchEvent(new Event('change', { target: e.target })); //说好的双向绑定,竟然不安套路
          console.log("fire change in insert");
        });
      },
      update: function (el, binding, vnode) {
        for (var i = 0; i < vnode.data.directives.length; i++) {
          if (vnode.data.directives[i].name == "model") {
            $(el).val(vnode.data.directives[i].value);
            console.log("new value in update:"+vnode.data.directives[i].value);
          }
        }
        $(el).trigger("change");
        console.log("fire change in update");
      }
    });

//html代码

<select v-select2="" v-model="editor.P1" required="required" class="form-control ">
 <option value=""></option>
 <option v-for="item in codes" v-bind:value="item.NAME">{{item.NAME}}</option>
</select>

经过好几天的研究,终于我发现在作者原来的代码的update中,加入修改el的val值,然后再触发select2的change事件,就可以了。而在使用方面,只需要给加一个v-select2即可,v-model以及option的配置都依照vue2的推荐方式,原封不动。之所以加了一个空的option是因为如果不加,默认select2是选择第一个选项的,但是,由于未知原因,与vue.editor.P1并不同步。

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

Javascript 相关文章推荐
热点新闻滚动特效的js代码
Aug 17 Javascript
js实现的复制兼容chrome和IE
Apr 03 Javascript
jQuery插件expander实现图片翻转特效
May 21 Javascript
js继承实现方法详解
Dec 16 Javascript
bootstrap弹出层的多种触发方式
May 10 Javascript
vue.js中过滤器的使用教程
Jun 08 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
在vue项目中,使用axios跨域处理
Mar 07 Javascript
axios对请求各种异常情况处理的封装方法
Sep 25 Javascript
JS实现判断有效的数独算法示例
Feb 25 Javascript
详解Vue前端生产环境发布配置实战篇
May 07 Javascript
Vue 3.0 全家桶抢先体验
Apr 28 Javascript
vue2.x select2 指令封装详解
Oct 12 #Javascript
一个简易时钟效果js实现代码
Mar 25 #Javascript
微信小程序实现页面跳转传值的方法
Oct 12 #Javascript
微信小程序 页面滑动事件的实例详解
Oct 12 #Javascript
微信小程序 动画的简单实例
Oct 12 #Javascript
node通过npm写一个cli命令行工具
Oct 12 #Javascript
JS实现自定义状态栏动画文字效果示例
Oct 12 #Javascript
You might like
摩卡咖啡
2021/03/03 咖啡文化
php获得文件扩展名三法
2006/11/25 PHP
php开发文档 会员收费1期
2012/08/14 PHP
php curl获取网页内容(IPV6下超时)的解决办法
2013/07/16 PHP
php基于curl重写file_get_contents函数实例
2016/11/08 PHP
js cookies实现简单统计访问次数
2009/11/24 Javascript
JavaScript OOP面向对象介绍
2010/12/02 Javascript
js的Boolean对象初始值示例
2014/03/04 Javascript
js图片延迟技术一般的思路与示例
2014/03/20 Javascript
什么是Node.js?Node.js详细介绍
2014/06/01 Javascript
Node.js实现简单聊天服务器
2014/06/20 Javascript
jQuery制作效果超棒的手风琴折叠菜单
2015/04/03 Javascript
讲解JavaScript中for...in语句的使用方法
2015/06/03 Javascript
JavaScript中模拟实现jsonp
2015/06/19 Javascript
javascript实现类似百度分享功能的方法
2015/07/27 Javascript
javascript动态获取登录时间和在线时长
2016/02/25 Javascript
BootStrap智能表单实战系列(七)验证的支持
2016/06/13 Javascript
jQuery实现手机自定义弹出输入框
2016/06/13 Javascript
最简单纯JavaScript实现Tab标签页切换的方式(推荐)
2016/07/25 Javascript
分分钟玩转Vue.js组件
2016/10/25 Javascript
jQuery Pagination分页插件_动力节点Java学院整理
2017/07/17 jQuery
swiper自定义分页器使用方法详解
2020/09/14 Javascript
使用webpack搭建vue项目及注意事项
2019/06/10 Javascript
JS数组转字符串实现方法解析
2020/09/04 Javascript
Django中使用Celery的方法示例
2018/11/29 Python
基于jupyter代码无法在pycharm中运行的解决方法
2020/04/21 Python
基于python实现操作git过程代码解析
2020/07/27 Python
车工岗位职责
2013/11/26 职场文书
3分钟演讲稿
2014/04/30 职场文书
热门专业求职信
2014/05/24 职场文书
火烧圆明园的观后感
2015/06/03 职场文书
2015年学校管理工作总结
2015/07/20 职场文书
幼儿园师德师风心得体会
2016/01/12 职场文书
2019奶茶店创业计划书范本!
2019/07/15 职场文书
来探秘“德国中小企业”的成功之道
2019/07/26 职场文书
Python中Schedule模块使用详解 周期任务神器
2022/04/19 Python