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代码
Sep 07 Javascript
Jquery选择器 $实现原理
Dec 02 Javascript
Ext JS框架程序中阻止键盘触发回退或者刷新页面的代码分享
Jun 07 Javascript
详解JavaScript中的属性和特性
Dec 08 Javascript
js实现符合国情的日期插件详解
Jan 19 Javascript
前端构建工具之gulp的语法教程
Jun 12 Javascript
关于jquery form表单序列化的注意事项详解
Aug 01 jQuery
使用Node.js写一个代码生成器的方法步骤
May 10 Javascript
在layui中使用form表单监听ajax异步验证注册的实例
Sep 03 Javascript
用jQuery实现抽奖程序
Apr 12 jQuery
Vue Cli3 打包配置并自动忽略console.log语句的方法
Apr 23 Javascript
element跨分页操作选择详解
Jun 29 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
Syphon 使用方法
2021/03/03 冲泡冲煮
DISCUZ在win2003环境下 Unable to access ./include/common.inc.php in... 的问题终极解决方案
2011/11/21 PHP
简单的jquery拖拽排序效果实现代码
2011/09/20 Javascript
基于jquery封装的一个js分页
2011/11/15 Javascript
JavaScript基础知识之数据类型
2012/08/06 Javascript
JS数学函数Exp使用说明
2012/08/09 Javascript
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
jquery 单引号和双引号的区别及使用注意
2013/07/31 Javascript
jquery的ajax简单结构示例代码
2014/02/17 Javascript
JavaSript中变量的作用域闭包的深入理解
2014/05/12 Javascript
javascript模拟map输出与去除重复项的方法
2015/02/09 Javascript
JavaScript获取表格(table)当前行的值、删除行、增加行
2015/07/03 Javascript
JS组件系列之Bootstrap Icon图标选择组件
2016/01/28 Javascript
10个JavaScript中易犯小错误
2016/02/14 Javascript
vue2.0+webpack环境的构造过程
2016/11/08 Javascript
vue.js element-ui validate中代码不执行问题解决方法
2017/12/18 Javascript
webstorm中vue语法的支持详解
2018/05/09 Javascript
JQuery事件冒泡和默认行为代码实例
2020/05/13 jQuery
解决element-ui里的下拉多选框 el-select 时,默认值不可删除问题
2020/08/14 Javascript
JavaScript代码实现简单计算器
2020/12/27 Javascript
Python入门篇之函数
2014/10/20 Python
用python写的一个wordpress的采集程序
2016/02/27 Python
python处理Excel xlrd的简单使用
2017/09/12 Python
代码详解django中数据库设置
2019/01/28 Python
python 队列基本定义与使用方法【初始化、赋值、判断等】
2019/10/24 Python
python Plotly绘图工具的简单使用
2020/03/03 Python
如何基于Python实现word文档重新排版
2020/09/29 Python
Python爬虫之App爬虫视频下载的实现
2020/12/08 Python
HTML5 Web存储方式的localStorage和sessionStorage进行数据本地存储案例应用
2012/12/09 HTML / CSS
在数据文件自动增长时,自动增长是否会阻塞对文件的更新
2014/05/01 面试题
计算机相关的自我评价
2014/01/15 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
师德师风事迹材料
2014/12/20 职场文书
孔繁森观后感
2015/06/10 职场文书
入党申请书怎么写?
2019/06/11 职场文书
关于mysql中时间日期类型和字符串类型的选择
2021/11/27 MySQL