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 相关文章推荐
JQuery与iframe交互实现代码
Dec 24 Javascript
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
Jan 07 Javascript
Array.prototype 的泛型应用分析
Apr 30 Javascript
jQuery插件jcrop+Fileapi完美实现图片上传+裁剪+预览的代码分享
Apr 22 Javascript
js+cookies实现悬浮购物车的方法
May 25 Javascript
js css实现垂直方向自适应的三角提示菜单
Jun 26 Javascript
JS使用tofixed与round处理数据四舍五入的区别
Oct 25 Javascript
Angular使用操作事件指令ng-click传多个参数示例
Mar 27 Javascript
利用Node.js批量抓取高清妹子图片实例教程
Aug 02 Javascript
vue实现分环境打包步骤(给不同的环境配置相对应的打包命令)
Jun 04 Javascript
MockJs结合json-server模拟后台数据
Aug 26 Javascript
vue实现导航标题栏随页面滚动渐隐渐显效果
Mar 12 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
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
深入PHP magic quotes的详解
2013/06/17 PHP
PHP JSON出错:Cannot use object of type stdClass as array解决方法
2014/08/16 PHP
PHP基于工厂模式实现的计算器实例
2015/07/16 PHP
ThinkPHP实现生成和校验验证码功能
2017/04/28 PHP
JS中剪贴板兼容性、判断复制成功或失败
2021/03/09 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
详解JavaScript跨域总结与解决办法
2016/10/31 Javascript
微信小程序实现皮肤功能(夜间模式)
2017/06/18 Javascript
angular.js4使用 RxJS 处理多个 Http 请求
2017/09/23 Javascript
浅谈Vuex的状态管理(全家桶)
2017/11/04 Javascript
vscode中vue-cli项目es-lint的配置方法
2018/07/30 Javascript
vue项目持久化存储数据的实现代码
2018/10/01 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
Typescript 中的 interface 和 type 到底有什么区别详解
2019/06/18 Javascript
Vue中keep-alive 实现后退不刷新并保持滚动位置
2020/03/17 Javascript
[40:57]TI4 循环赛第二日 iG vs EG
2014/07/11 DOTA
[46:04]Liquid vs VP Supermajor决赛 BO 第四场 6.10
2018/07/05 DOTA
详解Python 模拟实现生产者消费者模式的实例
2017/08/10 Python
基于python元祖与字典与集合的粗浅认识
2017/08/23 Python
python编程测试电脑开启最大线程数实例代码
2018/02/09 Python
python 普通克里金(Kriging)法的实现
2019/12/19 Python
pytorch 自定义卷积核进行卷积操作方式
2019/12/30 Python
tensorflow:指定gpu 限制使用量百分比,设置最小使用量的实现
2020/02/06 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
2020/04/01 Python
Python中qutip用法示例详解
2020/10/02 Python
Python confluent kafka客户端配置kerberos认证流程详解
2020/10/12 Python
css3针对移动端卡顿问题的解决(动画性能优化)
2020/02/14 HTML / CSS
世界最大的私人旅行指南出版商:孤独星球
2016/08/23 全球购物
英国领先的杂志订阅网站:Magazine.co.uk
2018/01/25 全球购物
用Python写一个for循环的例子
2016/07/19 面试题
教师节活动主持词
2014/04/02 职场文书
双方协议书
2014/04/22 职场文书
2014年扶贫帮困工作总结
2014/12/09 职场文书
曾国藩励志经典名言37句,蕴含哲理
2019/10/14 职场文书
Python中的套接字编程是什么?
2021/06/21 Python