zoukankan      html  css  js  c++  java
  • 实现一个可以实时提示的textarea组件

    该组件输入、换行、变换光标可以实时给出提示

    效果: 

    textarea.vue

    <template>
      <div>
        <el-input
          id="user-input"
          type="textarea" 
          placeholder="请换行输入不同的通知用户" 
          :autosize="{minRows: 2, maxRows: 10}" 
          v-model="inputValue" 
          @blur="closeHint"
          @input="settingHint"
          @click.native="settingHint"
          @keyup.native="disposeKey">
        </el-input>
        <input-hint 
          :all-items="hintItems" 
          :position = 'hintPosition'
          @select = "replaceStr"
        ></input-hint>
      </div>
    </template>
    
    <script lang="ts">
    import { Vue, Component, Prop } from "vue-property-decorator";
    import InputHint from "./inputHint.vue";
    import $ from "jquery";
    
    @Component({
      components: {
        InputHint
      }
    })
    export default class AdvancedTextarea extends Vue {
      inputValue: string = '';
      Seprator = "
    ";
      allUsers: string[] = [];
      hintItems: string[] = []; //传入提示框的项,可以是html字符串;为空则表示不显示提示框
      initPosition = { //输入框的信息,用于计算提示框位置
        left: 15,
        top: 5,
        rowHeight: 20,  //一行的高度
        fontSize: 7  //一个字的宽度
      }
      hintPosition = {
        left: this.initPosition.left,
        top: this.initPosition.top
      }
    
      //按上下左右键时,重置提示框
      disposeKey(e) {
        if (e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40) {
          this.settingHint();
        }
      }
    
      settingHint(val?) {
        let cursorLocation = $('#user-input').caret(); //光标位置
        let newStr = this.inputValue.slice(0, cursorLocation);  //输入框光标前的字符
        let newArr = newStr.split(this.Seprator);
        let searchKey = newArr.length === 0 ? "" : newArr[newArr.length - 1];
        let regExp = new RegExp(searchKey, 'ig');
        this.hintItems = searchKey ?
          this.allUsers.filter(item => item.indexOf(searchKey) !== -1).map(item => item.replace(regExp, `<strong>${searchKey}</strong>`)) :
          this.allUsers;
        this.hintPosition.left = this.initPosition.left + this.initPosition.fontSize * (searchKey.length > 0 ? searchKey.length - 1 : 0);
        this.hintPosition.top = this.initPosition.top + this.initPosition.rowHeight * (newArr.length > 10 ? 10 : newArr.length);
      }
    
      closeHint() {
        //延后关闭是因为立即关闭的话,点击提示框内容就无法触发点击事件
        window.setTimeout(() => {
          this.hintItems = null;
          window.clearTimeout();
        }, 200);
    
      }
    
      //将光标当前值替换为选中值
      replaceStr(val) {
        let cursorLocation = $('#user-input').caret(); //光标位置
        let newStr = this.inputValue.slice(0, cursorLocation);  //输入框光标前的字符
        let row = newStr.split(this.Seprator).length - 1;  //光标所在行
        let oriArr = this.inputValue.split(this.Seprator);
        oriArr[row] = val;
        this.inputValue = oriArr.join(this.Seprator);
        $('#user-input').focus();
      }
    
      getAllUsers() {
        this.allUsers = [
          'xiaoming@qq.com',
          'daming@163.com',
          'liuxioawei@gridsum.com',
          '432454354@qq.com',
          'zhangzheng@qq.com',
          'mostlove@163.com',
          'wangweihao@gridsum.com',
          '67900332@qq.com',
          'xiaosi@qq.com',
          'loveshuang@163.com',
          'liuxioawei@gridsum.com',
          '87456563@qq.com',
          'yaru@qq.com',
          'wuyuetian@163.com',
          'junjun@gridsum.com',
          '67576889@qq.com',
          'shuanger@qq.com',
          'she@163.com',
          'ruiji@gridsum.com',
          '45454334@qq.com',
        ]
      }
    
      mounted() {
        if (this.allUsers.length === 0) {
          this.getAllUsers();
        }
      }
    }
    
    </script>
    View Code

    inputHint.vue

    <template>
      <div v-show="allItems&&allItems.length!==0">
        <ul class="el-dropdown-menu el-popper max-height new-scoll-bar" :style="{left: position.left+'px', top: position.top+'px'}">
            <li class="el-dropdown-menu__item" v-for="(item,index) in allItems" :key="index" v-html="item" @click="selectItem(item)"></li>
        </ul>
      </div>
    </template>
    
    <style lang="postcss" scoped>
    .max-height {
      max-height: 250px;
      overflow-y: auto;
    }
    </style>
    
    <script lang="ts">
    import { Vue, Component } from "vue-property-decorator";
    
    @Component({
      props: {
        allItems: {
          type: Array,
          default: []
        },
        position: {
          type: Object,
          default: {
            left: 0,
            top: 0
          }
        }
      }
    })
    
    export default class InputHint extends Vue {
      allItems = this.allItems;
      selectItem(item: string) {
        let regExp = /<strong>|</strong>/g;
        let str = item.replace(regExp, '');
        this.$emit('select', str)
      }
    }
    </script>
    View Code
  • 相关阅读:
    系统吞吐量、TPS(QPS)、用户并发量、性能測试概念和公式
    限流实现与解决方案
    mysql事务,select for update,及数据的一致性处理
    **MySQL锁机制与用法分析**
    死锁的排查
    系统中异常的设计与处理
    Spring如何处理线程并发问题
    ThreadLocal作用、场景、原理
    Database Administration Statements
    mybatis 无法自动补全,没有获得dtd文件
  • 原文地址:https://www.cnblogs.com/XHappyness/p/9264574.html
Copyright © 2011-2022 走看看