zoukankan      html  css  js  c++  java
  • Vue

    实现这三个功能的踩坑记录。

    1. 需求

    在Vue中,有一个input, 双击时编辑文本,点击该input节点外的其他地方,则取消编辑。

    那么这里有三个要实现的地方
    第一是双击显示编辑框。
    第二是自动聚焦点击的显示框。
    第三是点击编辑框外的地方,隐藏编辑框。

    一二点都是在startPipeLineNameEdit这个method中去实现。


    2. 实现双击显示编辑框

    思路: 使用两个span包含双击前和双击后的代码,用isEditingPipeLineName这个变量去控制显示与否。(PipeLineName与我写的当前组件有关)。
    然后绑定一个双击时的事件@dblclick="startPipeLineNameEdit"。
    父组件BoardArea大致代码

           //PipeLine是子组件,可见可以有很多个子组件实例,因为v-for了一个数组
          <PipeLine
            v-for="pipeLine in wrappedPipeLineList"
            :pipeLine="pipeLine"
            class="pipe-line-item"
            :key="pipeLine.id"
          />
    

    子组件PipeLine大致代码

          
          <span v-show="!isEditingPipeLineName">
                ..未双击前
             <span @dblclick="startPipeLineNameEdit"></span>
             <span></span>
          </span>
          <span v-show="isEditingPipeLineName" v-model="editPipeLineName">
                ...双击后
            <input class="edit-pipeline"...>
            <button ...>save</button>
          </span>
    

    3. 实现编辑框自动聚焦。

    方案一: 手动操作DOM(不建议,不符合Vue思想)
    方案二: 自定义指令,无效。加入TODO,日后研究
    方案三: autofocus,无效。加入TODO。

    思路:操作DOM,找出那个DOM节点,然后focus。初学Vue,也想不到其他办法了。其实在Vue中自行操作DOM节点不好,因为Vue是数据驱动的,是自行更新DOM。

        startPipeLineNameEdit() {
          this.isEditingPipeLineName = true;
          let edit_pipeline = document.querySelector('.edit-pipeline');
          
          edit_pipeline.focus();   
        },
    

    问题1 死活不能focus。


    Google后,发现https://forum.vuejs.org/t/setting-focus-to-textarea-not-working/17891。
    原来Vue有一个DOM更新周期,可以用$nextTick立即触发。

        startPipeLineNameEdit() {
          this.isEditingPipeLineName = true;
    
          this.$nextTick(() => {
            let edit_pipeline = document.querySelector('.edit-pipeline');
            edit_pipeline.focus();
          }
        },
    

    问题2 只能focus第一个pipeline


    原因:
    解决办法:改成querySelectorAll然后遍历好了

        startPipeLineNameEdit() {
          this.isEditingPipeLineName = true;
    
          this.$nextTick(() => {
            let edit_pipelines = document.querySelectorAll('.edit-pipeline');
            edit_pipelines.forEach((element) => {
              element.focus();
            })
          });
        },
    


    4. 实现点击编辑框外的地方,隐藏编辑框

    方法1 首先想到的是“点击外面”,然后google: "vue click away", "vue click outside"等关键字,找到https://stackoverflow.com/questions/36170425/detect-click-outside-element。

    里面有自定义vue指令的,也有两个轮子。选用其中一个轮子vue-clickaway。

    // 按文档上开整
    <input class="edit-pipeline" type="text" v-model="editPipeLineName" v-on-clickaway="away">
    
    
    away() {
       console.log('clicked away');
       this.isEditingPipeLineName = false;
    },
    

    方法1出现的问题(还没解决有TODO)

    性能损耗严重: 如果有n个Pipeline, 则每次会触发n次这个函数。如果这个函数里面有密集计算(例如加个循环加法),导致非常卡。

    弃用这个轮子,可能这个轮子不适合去实现这个功能。
    还有个原生和jQuery的“点击外面”的方法,现在功力不行,加入TODO。

    方法2 监听blur事件

    得益于自动聚焦(focus),那么我可以监听focus的相反事件blur。

    <input class="edit-pipeline" type="text" v-model="editPipeLineName" @blur="away">
    


    4. 问题又出现了,要解决blur和click冲突问题

    原因应该是把逻辑写在blur里面不对。
    方案一: 延迟blur函数里面的逻辑。可以用lodash里面的debounce或者直接在blur执行的回调函数里setTimeout(我这里采用这一种最简单的方案,延迟100毫秒)
    方案二: 改为mousedown。用户体验不好。


    总结

    应该有其他优雅的实现方法,加入TODO。

  • 相关阅读:
    jQuery获取Select选择的Text和 Value(转)
    android学习---EditText
    android学习---Activity
    android学习---LinearLayout
    android学习---布局Layout
    android颜色码制表
    java面试题二
    java面试题一
    基本排序算法java实现
    Integer与int的区别
  • 原文地址:https://www.cnblogs.com/allen2333/p/10480739.html
Copyright © 2011-2022 走看看