• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

elementui解决el-select组件失去焦点blur事件每次获取的是上一次选值的问题

武飞扬头像
iVRJay
帮助1

目录

【问题描述】

【问题摘要】 

【分析问题】

 【完整Test代码】

【封装自定义指令】


↑↑↑↑↑↑↑↑↑↑↑↑ 不想看解决问题过程的可点击上方【封装自定义指令】目录直接跳转获取结果即可~~~

【问题描述】

        一位朋友遇到这么一个开发场景:在表格里面嵌入el-select组件,每次修改值后,失去焦点时将修改值提交后台保存,但是发现在el-select组件失去焦点时,blur事件的evt.target.value值总为前一次选择的值;

【问题摘要】 

1、el-select组件失去焦点时需要获取组件当前值而不是上一次的值;

2、el-select组件切换选项时不提交后台,只有当组件失去焦点后才提交当前值;

【分析问题】

        一刚开始以为是下拉框收起动画延时问题导致内部value值被延时修改,所以就在blur事件里延时获取evt.target.value,貌似没问题了

  1.  
    blurHandler(evt){
  2.  
    setTimeout(() => {
  3.  
    console.log(evt.target.value);
  4.  
    },250)
  5.  
    },

随后又发现通过@blur绑定事件只会触发一次,好吧那就加修饰符吧:@blur.capture.native,好像解决只触发一次的问题了

  1.  
    <el-select v-model="value" @blur.capture.native="nativeBlurHandler" ref="select">
  2.  
    <el-option
  3.  
    v-for="item in options"
  4.  
    :key="item.value"
  5.  
    :label="item.label"
  6.  
    :value="item.value">
  7.  
    </el-option>
  8.  
    </el-select>

但是随之而来的问题就是,每次切换取值后都会触发一次blur事件,这可不是我们想要的,这不变成change事件了吗?继续深挖!

那就打印一下this.$refs.select看看吧,找到this.$refs.select.$data, 看里面有定义啥变量没,发现了如下变量:

  1.  
    log(eventName){
  2.  
    let {
  3.  
    createdSelected,
  4.  
    inputHovering,
  5.  
    isOnComposition,
  6.  
    isSilentBlur,
  7.  
    menuVisibleOnFocus,
  8.  
    softFocus,
  9.  
    visible
  10.  
    } = this.$refs.select.$data;
  11.  
     
  12.  
    console.table([
  13.  
    {
  14.  
    name: eventName,
  15.  
    value: '',
  16.  
    },
  17.  
    // {
  18.  
    // name: 'createdSelected',
  19.  
    // value: createdSelected
  20.  
    // },
  21.  
    {
  22.  
    name: 'inputHovering',
  23.  
    value: inputHovering
  24.  
    },
  25.  
    // {
  26.  
    // name: 'isOnComposition',
  27.  
    // value: isOnComposition
  28.  
    // },
  29.  
    {
  30.  
    name: 'isSilentBlur',
  31.  
    value: isSilentBlur
  32.  
    },
  33.  
    // {
  34.  
    // name: 'menuVisibleOnFocus',
  35.  
    // value: menuVisibleOnFocus
  36.  
    // },
  37.  
    // {
  38.  
    // name: 'softFocus',
  39.  
    // value: softFocus
  40.  
    // },
  41.  
    {
  42.  
    name: 'visible',
  43.  
    value: visible
  44.  
    },
  45.  
    ])
  46.  
    }
学新通

 通过反复测试发现只有inputHovering,isSilentBlur,visible这三个变量与el-select组件focus,blur事件有关联:

学新通

 通过上图可以发现,只有最下方的失去焦点事件才是我们想要的,此时visible==false,isSilentBlur==true,正好满足我们的判断条件,于是blur事件改造成这样了:

  1.  
    nativeBlurHandler(evt){
  2.  
    console.log('nativeBlurHandler', {...this.$refs.select});
  3.  
    let {
  4.  
    isSilentBlur,
  5.  
    visible
  6.  
    } = this.$refs.select;
  7.  
    if( isSilentBlur && !visible ) {
  8.  
    console.log('提交', this.$refs.select.selected.currentValue);
  9.  
    }
  10.  
    this.log('blur事件');
  11.  
    },

又因为value取值从evt.target.value获取的不是实时的,也就是值不正确,继续深挖,发现this.$refs.select.selected.currentValue就是我们想要的正确的值,于是乎,问题就解决了!测试demo完整代码如下:

 【完整Test代码】

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="UTF-8">
  5.  
    <!-- import CSS -->
  6.  
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7.  
    </head>
  8.  
    <body>
  9.  
    <div id="app">
  10.  
    <el-select v-model="value" placeholder="请选择" @blur="blurHandler" @blur.capture.native="nativeBlurHandler" ref="select">
  11.  
    <el-option
  12.  
    v-for="item in options"
  13.  
    :key="item.value"
  14.  
    :label="item.label"
  15.  
    :value="item.value">
  16.  
    </el-option>
  17.  
    </el-select>
  18.  
    </div>
  19.  
    </body>
  20.  
    <!-- import Vue before Element -->
  21.  
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  22.  
    <!-- import JavaScript -->
  23.  
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  24.  
    <script>
  25.  
    let selectElm;
  26.  
    new Vue({
  27.  
    el: '#app',
  28.  
    data: function() {
  29.  
    return {
  30.  
    options: [{
  31.  
    value: '黄金糕',
  32.  
    label: '黄金糕'
  33.  
    }, {
  34.  
    value: '双皮奶',
  35.  
    label: '双皮奶'
  36.  
    }, {
  37.  
    value: '蚵仔煎',
  38.  
    label: '蚵仔煎'
  39.  
    }, {
  40.  
    value: '龙须面(传统面食)',
  41.  
    label: '龙须面(传统面食)'
  42.  
    }, {
  43.  
    value: '北京烤鸭',
  44.  
    label: '北京烤鸭'
  45.  
    }],
  46.  
    value: ''
  47.  
    }
  48.  
    },
  49.  
    methods: {
  50.  
    focusHandler(evt){
  51.  
    this.log('focus事件');
  52.  
    },
  53.  
    blurHandler(evt){
  54.  
    setTimeout(() => {
  55.  
    console.log(evt.target.value);
  56.  
    },250)
  57.  
    },
  58.  
    nativeBlurHandler(evt){
  59.  
    console.log('nativeBlurHandler', {...this.$refs.select});
  60.  
    let {
  61.  
    isSilentBlur,
  62.  
    visible
  63.  
    } = this.$refs.select;
  64.  
    if( isSilentBlur && !visible ) {
  65.  
    console.log('提交', this.$refs.select.selected.currentValue);
  66.  
    }
  67.  
    this.log('blur事件');
  68.  
    },
  69.  
    log(eventName){
  70.  
    let {
  71.  
    createdSelected,
  72.  
    inputHovering,
  73.  
    isOnComposition,
  74.  
    isSilentBlur,
  75.  
    menuVisibleOnFocus,
  76.  
    softFocus,
  77.  
    visible
  78.  
    } = this.$refs.select.$data;
  79.  
     
  80.  
    console.table([
  81.  
    {
  82.  
    name: eventName,
  83.  
    value: '',
  84.  
    },
  85.  
    // {
  86.  
    // name: 'createdSelected',
  87.  
    // value: createdSelected
  88.  
    // },
  89.  
    {
  90.  
    name: 'inputHovering',
  91.  
    value: inputHovering
  92.  
    },
  93.  
    // {
  94.  
    // name: 'isOnComposition',
  95.  
    // value: isOnComposition
  96.  
    // },
  97.  
    {
  98.  
    name: 'isSilentBlur',
  99.  
    value: isSilentBlur
  100.  
    },
  101.  
    // {
  102.  
    // name: 'menuVisibleOnFocus',
  103.  
    // value: menuVisibleOnFocus
  104.  
    // },
  105.  
    // {
  106.  
    // name: 'softFocus',
  107.  
    // value: softFocus
  108.  
    // },
  109.  
    {
  110.  
    name: 'visible',
  111.  
    value: visible
  112.  
    },
  113.  
    ])
  114.  
    }
  115.  
    }
  116.  
    })
  117.  
    </script>
  118.  
    </html>
学新通

【封装自定义指令】

想到给组件添加ref实际并不是那么好用且麻烦,所以我又将其封装成了指令,指令代码及用法如下,大家随取随用哈↓↓↓↓↓↓

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="UTF-8">
  5.  
    <!-- import CSS -->
  6.  
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7.  
    </head>
  8.  
    <body>
  9.  
    <div id="app">
  10.  
    <el-row>
  11.  
    <el-col :span="24">
  12.  
    <el-select v-select-blur="selectBlurHandler" v-model="value">
  13.  
    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
  14.  
    </el-option>
  15.  
    </el-select>
  16.  
    </el-col>
  17.  
    </el-row>
  18.  
    </div>
  19.  
    </body>
  20.  
    <!-- import Vue before Element -->
  21.  
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  22.  
    <!-- import JavaScript -->
  23.  
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  24.  
    <script>
  25.  
    Vue.directive('select-blur', {
  26.  
    bind: function(el, binding, vnode) {
  27.  
    const selectComponent = vnode.componentInstance;
  28.  
    if( selectComponent.$options.name === 'ElSelect' ) {
  29.  
    selectComponent.$watch('visible', (n,o) => {
  30.  
    const {
  31.  
    isSilentBlur,
  32.  
    visible,
  33.  
    } = selectComponent;
  34.  
    if(isSilentBlur && !visible) {
  35.  
    selectComponent.handleBlur();
  36.  
    }
  37.  
    })
  38.  
    selectComponent.$on('blur', () => {
  39.  
    let {
  40.  
    visible,
  41.  
    selected: {
  42.  
    currentValue
  43.  
    }
  44.  
    } = selectComponent;
  45.  
    if (!visible) {
  46.  
    binding?.value && typeof binding.value === 'function' && binding.value(currentValue);
  47.  
    selectComponent.blur(); //处理页面频繁聚焦失焦导致重复触发blur事件的问题
  48.  
    }
  49.  
    }, true);
  50.  
    }
  51.  
    },
  52.  
    unbind: function(el, binding, vnode) {
  53.  
    const selectComponent = vnode.componentInstance;
  54.  
    if( selectComponent.$options.name === 'ElSelect' ) {
  55.  
    selectComponent.$off('blur');
  56.  
    }
  57.  
    }
  58.  
    });
  59.  
     
  60.  
    const app = new Vue({
  61.  
    el: '#app',
  62.  
    data: function() {
  63.  
    return {
  64.  
    options: [{
  65.  
    value: '黄金糕',
  66.  
    label: '黄金糕'
  67.  
    }, {
  68.  
    value: '双皮奶',
  69.  
    label: '双皮奶'
  70.  
    }, {
  71.  
    value: '蚵仔煎',
  72.  
    label: '蚵仔煎'
  73.  
    }, {
  74.  
    value: '龙须面(传统面食)',
  75.  
    label: '龙须面(传统面食)'
  76.  
    }, {
  77.  
    value: '北京烤鸭',
  78.  
    label: '北京烤鸭'
  79.  
    }],
  80.  
    value: ''
  81.  
    }
  82.  
    },
  83.  
    methods: {
  84.  
    selectBlurHandler(val) {
  85.  
    console.log('提交', val);
  86.  
    },
  87.  
    }
  88.  
    })
  89.  
    </script>
  90.  
    </html>
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggjjgb
系列文章
更多 icon
同类精品
更多 icon
继续加载